support adc bus

This commit is contained in:
wlyu 2022-02-16 18:01:25 +08:00
parent 5185501d72
commit efd8999988
8 changed files with 378 additions and 182 deletions

View File

@ -81,8 +81,6 @@ void PlcReadUATask(void *arg)
if(EOK != ret)
{
plc_print("plc: [%s] read failed\n", __func__);
free(plc_demo_dev.priv_data);
return;
}
free(plc_demo_dev.priv_data);
ops->close(&plc_demo_dev);
@ -94,5 +92,5 @@ void PlcReadTest(int argc, char *argv[])
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
plc, PlcReadTest, test PLC);
plc, PlcReadTest, Read PLC);

View File

@ -34,6 +34,7 @@ extern int ExtSramInit(void);
#include <connect_ethernet.h>
#include <connect_uart.h>
#include <connect_adc.h>
#define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority
4 bits for subpriority */
@ -628,6 +629,11 @@ void InitBoardHardware()
#ifdef BSP_USING_LPUART
Imrt1052HwUartInit();
#endif
#ifdef BSP_USING_ADC
Imrt1052HwAdcInit();
#endif
InstallConsole(KERNEL_CONSOLE_BUS_NAME, KERNEL_CONSOLE_DRV_NAME, KERNEL_CONSOLE_DEVICE_NAME);

View File

@ -35,6 +35,10 @@ menuconfig BSP_USING_ADC
default y
select RESOURCES_ADC
if BSP_USING_ADC
source "$BSP_DIR/third_party_driver/adc/Kconfig"
endif
menuconfig BSP_USING_SPI
bool "Using SPI device"
default y

View File

@ -0,0 +1,29 @@
config BSP_USING_ADC1
bool "Enable ADC1"
default y
if BSP_USING_ADC1
config ADC_BUS_NAME_1
string "adc bus 1 name"
default "adc1"
config ADC_DRV_NAME_1
string "adc bus 1 driver name"
default "adc1_drv"
config ADC_1_DEVICE_NAME_0
string "adc bus 1 device name"
default "adc1_dev"
endif
config BSP_USING_ADC2
bool "Enable ADC2"
default y
if BSP_USING_ADC2
config ADC_BUS_NAME_2
string "adc bus 2 name"
default "adc2"
config ADC_DRV_NAME_2
string "adc bus 2 driver name"
default "adc2_drv"
config ADC_2_DEVICE_NAME_0
string "adc bus 2 device name"
default "adc2_dev"
endif

View File

@ -1,3 +1,3 @@
SRC_FILES := fsl_adc.c adc_interrupt.c
SRC_FILES := fsl_adc.c connect_adc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,178 +0,0 @@
/*
* Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file adc_interrupt.c
* @brief Demo for ADC function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.1.18
*/
#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_adc.h"
#include "fsl_common.h"
#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define DEMO_ADC_BASE ADC1
#define DEMO_ADC_IRQn ADC1_IRQn
//#define DEMO_ADC_USER_CHANNEL 0U
#define DEMO_ADC_USER_CHANNEL 3U
#define DEMO_ADC_CHANNEL_GROUP 0U
#define EXAMPLE_ADC_IRQHandler ADC1_IRQHandler
#define adc_print KPrintf
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
volatile bool g_AdcConversionDoneFlag;
volatile uint32_t g_AdcConversionValue;
volatile uint32_t g_AdcInterruptCounter;
const uint32_t g_Adc_12bitFullRange = 4096U;
/*******************************************************************************
* Code
******************************************************************************/
//#define ADC_BUS_NAME_1 "adc1"
//#define ADC_DRV_NAME_1 "adc1_drv"
//#define ADC_1_DEVICE_NAME_0 "adc1_dev0"
//
//static struct Bus *adc_bus = NONE; /* I2C bus handle */
//
//void AdcInit(const char *bus_name, const char *dev_name, const char *drv_name)
//{
// /* find I2C device and get I2C handle */
// adc_bus = BusFind(bus_name);
// if (NONE == adc_bus){
// i2c_print("%s can't find %s bus!\n", __func__, bus_name);
// }
// else{
// i2c_print("%s find %s bus!\n", __func__, bus_name);
// }
//
// adc_bus->owner_haldev = BusFindDevice(adc_bus, dev_name);
// adc_bus->owner_driver = BusFindDriver(adc_bus, drv_name);
//
// if(adc_bus->match(adc_bus->owner_driver, adc_bus->owner_haldev)){
// i2c_print("i2c match drv %s %p dev %s %p error\n", drv_name, adc_bus->owner_driver, dev_name, adc_bus->owner_haldev);
// }
// else{
// i2c_print("HS3000Init successfully!write %p read %p\n",
// adc_bus->owner_haldev->dev_done->write,
// adc_bus->owner_haldev->dev_done->read);
// }
//}
//
//void TestAdcInit(void)
//{
// AdcInit(ADC_BUS_NAME_1, ADC_1_DEVICE_NAME_0, ADC_DRV_NAME_1); /* init sensor */
//}
void EXAMPLE_ADC_IRQHandler(int vector, void *param)
{
g_AdcConversionDoneFlag = true;
/* Read conversion result to clear the conversion completed flag. */
g_AdcConversionValue = ADC_GetChannelConversionValue(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP);
g_AdcInterruptCounter++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC1_IRQn, EXAMPLE_ADC_IRQHandler, NONE);
/*!
* @brief Main function
*/
int test_adc(void)
{
int cnt = 3;
adc_config_t adcConfigStrcut;
adc_channel_config_t adcChannelConfigStruct;
EnableIRQ(DEMO_ADC_IRQn);
adc_print("\r\nADC interrupt Example.\r\n");
/*
* config->enableAsynchronousClockOutput = true;
* config->enableOverWrite = false;
* config->enableContinuousConversion = false;
* config->enableHighSpeed = false;
* config->enableLowPower = false;
* config->enableLongSample = false;
* config->referenceVoltageSource = kADC_ReferenceVoltageSourceVref;
* config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
* config->clockSource = kADC_ClockSourceAD;
* config->clockDriver = kADC_ClockDriver1;
* config->resolution = kADC_Resolution12Bit;
*/
ADC_GetDefaultConfig(&adcConfigStrcut);
ADC_Init(DEMO_ADC_BASE, &adcConfigStrcut);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(DEMO_ADC_BASE, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(DEMO_ADC_BASE))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
/* Configure the user channel and interrupt. */
adcChannelConfigStruct.channelNumber = DEMO_ADC_USER_CHANNEL;
adcChannelConfigStruct.enableInterruptOnConversionCompleted = true;
g_AdcInterruptCounter = 0U; /* Clear the interrupt counter. */
adc_print("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
while (cnt --)
{
adc_print("Press any key to get user channel's ADC value.\r\n");
getchar();
g_AdcConversionDoneFlag = false;
/*
When in software trigger mode, each conversion would be launched once calling the "ADC16_ChannelConfigure()"
function, which works like writing a conversion command and executing it. For another channel's conversion,
just to change the "channelNumber" field in channel configuration structure, and call the function
"ADC_ChannelConfigure()"" again.
Also, the "enableInterruptOnConversionCompleted" inside the channel configuration structure is a parameter
for
the conversion command. It takes affect just for the current conversion. If the interrupt is still required
for the following conversion, it is necessary to assert the "enableInterruptOnConversionCompleted" every
time
for each command.
*/
ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adcChannelConfigStruct);
while (g_AdcConversionDoneFlag == false);
adc_print("ADC Value: %d\r\n", g_AdcConversionValue);
adc_print("ADC Interrupt Counter: %d\r\n", g_AdcInterruptCounter);
}
}
SHELL_EXPORT_CMD (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
adc, test_adc, ADC test );

View File

@ -0,0 +1,303 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_adc.c
* @brief Demo for ADC function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.1.18
*/
#include "board.h"
#include "fsl_adc.h"
#include "fsl_common.h"
#include "dev_adc.h"
#include "bus_adc.h"
#include "connect_adc.h"
#define ADC1_BASE_ADDR ADC1
#define ADC1_IRQ ADC1_IRQn
#define ADC1_USER_CHANNEL 3U
#define ADC1_CHANNEL_GROUP 0U
#define ADC2_BASE_ADDR ADC2
#define ADC2_IRQ ADC2_IRQn
#define ADC2_USER_CHANNEL 4U
#define ADC2_CHANNEL_GROUP 0U
#define adc_print KPrintf
#define ADC1_BUS_NAME "adc1"
#define ADC1_DRV_NAME "adc1_drv"
#define ADC1_DEV_NAME "adc1_dev"
#define ADC2_BUS_NAME "adc2"
#define ADC2_DRV_NAME "adc2_drv"
#define ADC2_DEV_NAME "adc2_dev"
volatile bool adc1_flag;
volatile uint32_t adc1_val;
volatile uint32_t adc1_irq_cnt;
volatile bool adc2_flag;
volatile uint32_t adc2_val;
volatile uint32_t adc2_irq_cnt;
/*******************************************************************************
* Code
******************************************************************************/
void ADC1_IRQHandler(int vector, void *param)
{
adc1_flag = true;
/* Read conversion result to clear the conversion completed flag. */
adc1_val = ADC_GetChannelConversionValue(ADC1_BASE_ADDR, ADC1_CHANNEL_GROUP);
adc1_irq_cnt++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC1_IRQn, ADC1_IRQHandler, NONE);
void ADC2_IRQHandler(int vector, void *param)
{
adc2_flag = true;
/* Read conversion result to clear the conversion completed flag. */
adc2_val = ADC_GetChannelConversionValue(ADC2_BASE_ADDR, ADC2_CHANNEL_GROUP);
adc2_irq_cnt++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC2_IRQn, ADC2_IRQHandler, NONE);
uint32 Imrt1052AdcOpen(void *dev)
{
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
adc_config_t adc_cfg;
#ifdef BSP_USING_ADC1
if (0 == strncmp(adc_dev->haldev.dev_name, ADC1_DEV_NAME, NAME_NUM_MAX)) {
EnableIRQ(ADC1_IRQn);
ADC_GetDefaultConfig(&adc_cfg);
ADC_Init(ADC1, &adc_cfg);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(ADC1, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(ADC1))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
}
#endif
#ifdef BSP_USING_ADC2
if (0 == strncmp(adc_dev->haldev.dev_name, ADC2_DEV_NAME, NAME_NUM_MAX)) {
EnableIRQ(ADC2_IRQn);
ADC_GetDefaultConfig(&adc_cfg);
ADC_Init(ADC2, &adc_cfg);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(ADC2, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(ADC2))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
}
#endif
return EOK;
}
uint32 Imrt1052AdcClose(void *dev)
{
return EOK;
}
uint32 Imrt1052AdcRead(void *dev, struct BusBlockReadParam *read_param)
{
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
adc_channel_config_t ch_cfg;
#ifdef BSP_USING_ADC1
if (0 == strncmp(adc_dev->haldev.dev_name, ADC1_DEV_NAME, NAME_NUM_MAX)) {
/* Configure the user channel and interrupt. */
ch_cfg.channelNumber = ADC1_USER_CHANNEL;
ch_cfg.enableInterruptOnConversionCompleted = true;
adc1_irq_cnt = 0U; /* Clear the interrupt counter. */
adc1_flag = false;
ADC_SetChannelConfig(ADC1, ADC1_CHANNEL_GROUP, &ch_cfg);
while (adc1_flag == false);
adc_print("ADC Value: %d\r\n", adc1_val);
adc_print("ADC Interrupt Counter: %d\r\n", adc1_irq_cnt);
}
#endif
#ifdef BSP_USING_ADC2
if (0 == strncmp(adc_dev->haldev.dev_name, ADC2_DEV_NAME, NAME_NUM_MAX)) {
/* Configure the user channel and interrupt. */
ch_cfg.channelNumber = ADC2_USER_CHANNEL;
ch_cfg.enableInterruptOnConversionCompleted = true;
adc2_irq_cnt = 0U; /* Clear the interrupt counter. */
adc2_flag = false;
ADC_SetChannelConfig(ADC2, ADC2_CHANNEL_GROUP, &ch_cfg);
while (adc2_flag == false);
adc_print("ADC Value: %d\r\n", adc2_val);
adc_print("ADC Interrupt Counter: %d\r\n", adc2_irq_cnt);
}
#endif
return adc1_val;
}
static uint32 Imrt1052AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
uint8 adc_channel;
struct AdcDriver *adc_drv = (struct AdcDriver *)drv;
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)adc_drv->driver.owner_bus->owner_haldev;
struct Imrt1052HwAdc *adc_cfg = (struct Imrt1052HwAdc *)adc_dev->haldev.private_data;
switch (configure_info->configure_cmd)
{
case OPE_CFG:
adc_cfg->adc_channel = *(uint8 *)configure_info->private_data;
if (adc_cfg->adc_channel > 18) {
KPrintf("Imrt1052AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel);
adc_cfg->adc_channel = 0;
ret = ERROR;
}
break;
default:
break;
}
return ret;
}
static const struct AdcDevDone dev_done =
{
Imrt1052AdcOpen,
Imrt1052AdcClose,
NONE,
Imrt1052AdcRead,
};
int Imrt1052HwAdcInit(void)
{
x_err_t ret = EOK;
#ifdef BSP_USING_ADC1
static struct AdcBus adc1_bus;
static struct AdcDriver adc1_drv;
static struct AdcHardwareDevice adc1_dev;
static struct Imrt1052HwAdc adc1_cfg;
adc1_drv.configure = Imrt1052AdcDrvConfigure;
ret = AdcBusInit(&adc1_bus, ADC1_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC1 bus init error %d\n", ret);
return ERROR;
}
ret = AdcDriverInit(&adc1_drv, ADC1_DRV_NAME);
if (ret != EOK) {
KPrintf("ADC1 driver init error %d\n", ret);
return ERROR;
}
ret = AdcDriverAttachToBus(ADC1_DRV_NAME, ADC1_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC1 driver attach error %d\n", ret);
return ERROR;
}
adc1_dev.adc_dev_done = &dev_done;
ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC1_DEV_NAME);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
ret = AdcDeviceAttachToBus(ADC1_DEV_NAME, ADC1_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
#endif
#ifdef BSP_USING_ADC2
static struct AdcBus adc2_bus;
static struct AdcDriver adc2_drv;
static struct AdcHardwareDevice adc2_dev;
static struct Imrt1052HwAdc adc2_cfg;
adc2_drv.configure = Imrt1052AdcDrvConfigure;
ret = AdcBusInit(&adc2_bus, ADC2_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC2 bus init error %d\n", ret);
return ERROR;
}
ret = AdcDriverInit(&adc2_drv, ADC2_DRV_NAME);
if (ret != EOK) {
KPrintf("ADC2 driver init error %d\n", ret);
return ERROR;
}
ret = AdcDriverAttachToBus(ADC2_DRV_NAME, ADC2_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC2 driver attach error %d\n", ret);
return ERROR;
}
adc2_dev.adc_dev_done = &dev_done;
ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC2_DEV_NAME);
if (ret != EOK) {
KPrintf("ADC2 device register error %d\n", ret);
return ERROR;
}
ret = AdcDeviceAttachToBus(ADC2_DEV_NAME, ADC2_BUS_NAME);
if (ret != EOK) {
KPrintf("ADC2 device register error %d\n", ret);
return ERROR;
}
#endif
return ret;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_adc.h
* @brief define stm32f407-st-discovery adc function and struct
* @version 1.1
* @author AIIT XUOS Lab
* @date 2021-12-28
*/
#ifndef CONNECT_ADC_H
#define CONNECT_ADC_H
#include <device.h>
struct Imrt1052HwAdc
{
void *ADCx;
uint8 adc_channel;
};
int Imrt1052HwAdcInit(void);
#endif