| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- /*
- * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-04-28 CDT first version
- * 2022-06-08 xiaoxiaolisunny add hc32f460 series
- * 2022-06-14 CDT fix a bug of internal trigger
- * 2024-02-20 CDT support HC32F448
- * add function for associating with the dma
- */
- #include <board.h>
- #include <drivers/adc.h>
- #include <drv_adc.h>
- #include <drv_config.h>
- #define DBG_TAG "drv.adc"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #ifdef BSP_USING_ADC
- typedef struct
- {
- struct rt_adc_device rt_adc;
- CM_ADC_TypeDef *instance;
- struct adc_dev_init_params init;
- } adc_device;
- #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
- enum
- {
- #ifdef BSP_USING_ADC1
- ADC1_INDEX,
- #endif
- #ifdef BSP_USING_ADC2
- ADC2_INDEX,
- #endif
- #ifdef BSP_USING_ADC3
- ADC3_INDEX,
- #endif
- };
- static adc_device _g_adc_dev_array[] =
- {
- #ifdef BSP_USING_ADC1
- {
- {0},
- CM_ADC1,
- ADC1_INIT_PARAMS,
- },
- #endif
- #ifdef BSP_USING_ADC2
- {
- {0},
- CM_ADC2,
- ADC2_INIT_PARAMS,
- },
- #endif
- #ifdef BSP_USING_ADC3
- {
- {0},
- CM_ADC3,
- ADC3_INIT_PARAMS,
- },
- #endif
- };
- static void _adc_internal_trigger0_set(adc_device *p_adc_dev)
- {
- uint32_t u32TriggerSel;
- rt_bool_t is_internal_trig0_enabled = (p_adc_dev->init.hard_trig_src == ADC_HARDTRIG_EVT0 || p_adc_dev->init.hard_trig_src == ADC_HARDTRIG_EVT0_EVT1);
- if (is_internal_trig0_enabled == RT_FALSE)
- {
- return;
- }
- switch ((rt_uint32_t)p_adc_dev->instance)
- {
- case (rt_uint32_t)CM_ADC1:
- u32TriggerSel = AOS_ADC1_0;
- break;
- case (rt_uint32_t)CM_ADC2:
- u32TriggerSel = AOS_ADC2_0;
- break;
- #if defined (HC32F472) || defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) || defined (HC32F334)
- case (rt_uint32_t)CM_ADC3:
- u32TriggerSel = AOS_ADC3_0;
- break;
- #endif
- default:
- break;
- }
- AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg0_enable);
- AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg1_enable);
- AOS_SetTriggerEventSrc(u32TriggerSel, p_adc_dev->init.internal_trig0_sel);
- }
- static void _adc_internal_trigger1_set(adc_device *p_adc_dev)
- {
- uint32_t u32TriggerSel;
- rt_bool_t is_internal_trig1_enabled = (p_adc_dev->init.hard_trig_src == ADC_HARDTRIG_EVT1 || p_adc_dev->init.hard_trig_src == ADC_HARDTRIG_EVT0_EVT1);
- if (is_internal_trig1_enabled == RT_FALSE)
- {
- return;
- }
- switch ((rt_uint32_t)p_adc_dev->instance)
- {
- case (rt_uint32_t)CM_ADC1:
- u32TriggerSel = AOS_ADC1_1;
- break;
- case (rt_uint32_t)CM_ADC2:
- u32TriggerSel = AOS_ADC2_1;
- break;
- #if defined (HC32F472) || defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) || defined (HC32F334)
- case (rt_uint32_t)CM_ADC3:
- u32TriggerSel = AOS_ADC3_1;
- break;
- #endif
- default:
- break;
- }
- AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg0_enable);
- AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg1_enable);
- AOS_SetTriggerEventSrc(u32TriggerSel, p_adc_dev->init.internal_trig1_sel);
- }
- static rt_err_t _adc_enable(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
- {
- adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
- ADC_ChCmd(p_adc_dev->instance, ADC_SEQ_A, channel, (en_functional_state_t)enabled);
- /* user_data != NULL */
- if (device->parent.user_data != RT_NULL)
- {
- struct adc_dev_priv_params *adc_dev_priv = device->parent.user_data;
- if ((ADC_USING_EOCA_DMA_FLAG == adc_dev_priv->flag) && (adc_dev_priv->ops->dma_trig_config != RT_NULL))
- {
- adc_dev_priv->ops->dma_trig_config();
- }
- }
- return 0;
- }
- static rt_err_t _adc_convert(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
- {
- rt_err_t rt_ret = -RT_ERROR;
- rt_uint32_t timeCnt;
- if (!value)
- {
- return -RT_EINVAL;
- }
- adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
- if (p_adc_dev->init.hard_trig_enable == RT_FALSE)
- {
- if (p_adc_dev->instance->STR == 0)
- {
- ADC_Start(p_adc_dev->instance);
- }
- uint32_t start_time = rt_tick_get();
- do
- {
- if (ADC_GetStatus(p_adc_dev->instance, ADC_FLAG_EOCA) == SET)
- {
- ADC_ClearStatus(p_adc_dev->instance, ADC_FLAG_EOCA);
- rt_ret = LL_OK;
- break;
- }
- }
- while ((rt_tick_get() - start_time) < p_adc_dev->init.eoc_poll_time_max);
- if (rt_ret == LL_OK)
- {
- /* Get any ADC value of sequence A channel that needed. */
- *value = ADC_GetValue(p_adc_dev->instance, channel);
- }
- }
- else if (p_adc_dev->init.hard_trig_enable == RT_TRUE)
- {
- /* DMA src/dest/tc... config; start/stop trigger */
- if (p_adc_dev->init.adc_eoca_dma != RT_NULL)
- {
- if (p_adc_dev->rt_adc.parent.user_data != RT_NULL)
- {
- struct adc_dev_priv_params *adc_dev_priv = device->parent.user_data;
- struct dma_config *adc_eoca_dma;
- adc_eoca_dma = p_adc_dev->init.adc_eoca_dma;
- if ((ADC_USING_EOCA_DMA_FLAG == adc_dev_priv->flag) && (adc_dev_priv->ops->dma_trig_start != RT_NULL))
- {
- DMA_ClearTransCompleteStatus(adc_eoca_dma->Instance, adc_eoca_dma->flag);
- (void)DMA_SetTransCount(adc_eoca_dma->Instance, adc_eoca_dma->channel, 1U);
- (void)DMA_SetSrcAddr(adc_eoca_dma->Instance, adc_eoca_dma->channel, (uint32_t)(&p_adc_dev->instance->DR0) + channel * 2);
- (void)DMA_SetDestAddr(adc_eoca_dma->Instance, adc_eoca_dma->channel, (uint32_t)(value));
- (void)DMA_ChCmd(adc_eoca_dma->Instance, adc_eoca_dma->channel, ENABLE);
- adc_dev_priv->ops->dma_trig_start();
- timeCnt = 0;
- /* wait DMA transfer completed */
- while (RESET == DMA_GetTransCompleteStatus(adc_eoca_dma->Instance, adc_eoca_dma->flag) && (timeCnt < p_adc_dev->init.eoc_poll_time_max))
- {
- rt_thread_mdelay(1);
- timeCnt++;
- }
- if (timeCnt >= p_adc_dev->init.eoc_poll_time_max)
- {
- (void)DMA_ChCmd(adc_eoca_dma->Instance, adc_eoca_dma->channel, DISABLE);
- rt_ret = -RT_ETIMEOUT;
- }
- if (adc_dev_priv->ops->dma_trig_stop != RT_NULL)
- {
- adc_dev_priv->ops->dma_trig_stop();
- }
- }
- }
- }
- }
- return rt_ret;
- }
- static rt_uint8_t _adc_get_resolution(struct rt_adc_device *device)
- {
- rt_uint8_t resolution = 0;
- rt_uint16_t accsel;
- adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
- accsel = ADC_GetResolution(p_adc_dev->instance);
- switch (accsel)
- {
- case ADC_RESOLUTION_12BIT:
- resolution = 12;
- break;
- case ADC_RESOLUTION_10BIT:
- resolution = 10;
- break;
- case ADC_RESOLUTION_8BIT:
- resolution = 8;
- break;
- default:
- break;
- }
- return resolution;
- }
- static rt_int16_t _adc_get_vref(struct rt_adc_device *device)
- {
- rt_int16_t vref = 0;
- adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
- vref = p_adc_dev->init.vref;
- return vref;
- }
- static struct rt_adc_ops _g_adc_ops =
- {
- _adc_enable,
- _adc_convert,
- _adc_get_resolution,
- _adc_get_vref
- };
- static void _adc_clock_enable(void)
- {
- #if defined(BSP_USING_ADC1)
- FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC1, ENABLE);
- #endif
- #if defined(BSP_USING_ADC2)
- FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC2, ENABLE);
- #endif
- #if defined(BSP_USING_ADC3)
- FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC3, ENABLE);
- #endif
- }
- static void hc32_adc_get_dma_info(void)
- {
- #ifdef BSP_ADC1_USING_DMA
- static struct dma_config adc1_eoca_dma = ADC1_EOCA_DMA_CONFIG;
- _g_adc_dev_array[ADC1_INDEX].init.adc_eoca_dma = &adc1_eoca_dma;
- #endif
- #ifdef BSP_ADC2_USING_DMA
- static struct dma_config adc2_eoca_dma = ADC2_EOCA_DMA_CONFIG;
- _g_adc_dev_array[ADC2_INDEX].init.adc_eoca_dma = &adc2_eoca_dma;
- #endif
- #ifdef BSP_ADC3_USING_DMA
- static struct dma_config adc3_eoca_dma = ADC3_EOCA_DMA_CONFIG;
- _g_adc_dev_array[ADC3_INDEX].init.adc_eoca_dma = &adc3_eoca_dma;
- #endif
- }
- static void hc32_adc_dma_config(adc_device *p_adc_dev)
- {
- stc_dma_init_t stcDmaInit;
- /* DMA/AOS FCG enable */
- FCG_Fcg0PeriphClockCmd(p_adc_dev->init.adc_eoca_dma->clock, ENABLE);
- (void)DMA_StructInit(&stcDmaInit);
- stcDmaInit.u32BlockSize = 1UL;
- stcDmaInit.u32TransCount = 1UL;
- stcDmaInit.u32DataWidth = DMA_DATAWIDTH_16BIT;
- stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_FIX;
- stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;
- stcDmaInit.u32SrcAddr = (uint32_t)RT_NULL;
- stcDmaInit.u32DestAddr = (uint32_t)RT_NULL;
- if (LL_OK != DMA_Init(p_adc_dev->init.adc_eoca_dma->Instance, p_adc_dev->init.adc_eoca_dma->channel, &stcDmaInit))
- {
- rt_kprintf("[%s:%d]ADC DMA init error!\n", __func__, __LINE__);
- }
- AOS_SetTriggerEventSrc(p_adc_dev->init.adc_eoca_dma->trigger_select, p_adc_dev->init.adc_eoca_dma->trigger_event);
- /* Clear DMA TC flag */
- DMA_ClearTransCompleteStatus(p_adc_dev->init.adc_eoca_dma->Instance, p_adc_dev->init.adc_eoca_dma->flag);
- /* Enable DMA unit */
- DMA_Cmd(p_adc_dev->init.adc_eoca_dma->Instance, ENABLE);
- }
- extern rt_err_t rt_hw_board_adc_init(CM_ADC_TypeDef *ADCx);
- int rt_hw_adc_init(void)
- {
- int ret = RT_EOK, i = 0;
- stc_adc_init_t stcAdcInit = {0};
- int32_t ll_ret = 0;
- _adc_clock_enable();
- hc32_adc_get_dma_info();
- uint32_t dev_cnt = sizeof(_g_adc_dev_array) / sizeof(_g_adc_dev_array[0]);
- for (; i < dev_cnt; i++)
- {
- ADC_DeInit(_g_adc_dev_array[i].instance);
- /* Initializes ADC. */
- stcAdcInit.u16Resolution = _g_adc_dev_array[i].init.resolution;
- stcAdcInit.u16DataAlign = _g_adc_dev_array[i].init.data_align;
- stcAdcInit.u16ScanMode = (_g_adc_dev_array[i].init.continue_conv_mode_enable) ? ADC_MD_SEQA_CONT : ADC_MD_SEQA_SINGLESHOT;
- ll_ret = ADC_Init((void *)_g_adc_dev_array[i].instance, &stcAdcInit);
- if (ll_ret != LL_OK)
- {
- ret = -RT_ERROR;
- break;
- }
- ADC_TriggerCmd(_g_adc_dev_array[i].instance, ADC_SEQ_A, (en_functional_state_t)_g_adc_dev_array[i].init.hard_trig_enable);
- ADC_TriggerConfig(_g_adc_dev_array[i].instance, ADC_SEQ_A, _g_adc_dev_array[i].init.hard_trig_src);
- if (_g_adc_dev_array[i].init.hard_trig_enable && _g_adc_dev_array[i].init.hard_trig_src != ADC_HARDTRIG_ADTRG_PIN)
- {
- _adc_internal_trigger0_set(&_g_adc_dev_array[i]);
- _adc_internal_trigger1_set(&_g_adc_dev_array[i]);
- }
- if (_g_adc_dev_array[i].init.adc_eoca_dma != RT_NULL)
- {
- hc32_adc_dma_config(&_g_adc_dev_array[i]);
- }
- rt_hw_board_adc_init((void *)_g_adc_dev_array[i].instance);
- ret = rt_hw_adc_register(&_g_adc_dev_array[i].rt_adc, \
- (const char *)_g_adc_dev_array[i].init.name, \
- &_g_adc_ops, (void *)_g_adc_dev_array[i].instance);
- if (ret != RT_EOK)
- {
- LOG_E("failed register %s, err=%d", _g_adc_dev_array[i].init.name, ret);
- }
- }
- return ret;
- }
- INIT_DEVICE_EXPORT(rt_hw_adc_init);
- #endif
- #endif /* BSP_USING_ADC */
|