drv_adc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-04-28 CDT first version
  9. * 2022-06-08 xiaoxiaolisunny add hc32f460 series
  10. * 2022-06-14 CDT fix a bug of internal trigger
  11. * 2024-02-20 CDT support HC32F448
  12. * add function for associating with the dma
  13. */
  14. #include <board.h>
  15. #include <drivers/adc.h>
  16. #include <drv_adc.h>
  17. #include <drv_config.h>
  18. #define DBG_TAG "drv.adc"
  19. #define DBG_LVL DBG_INFO
  20. #include <rtdbg.h>
  21. #ifdef BSP_USING_ADC
  22. typedef struct
  23. {
  24. struct rt_adc_device rt_adc;
  25. CM_ADC_TypeDef *instance;
  26. struct adc_dev_init_params init;
  27. } adc_device;
  28. #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
  29. enum
  30. {
  31. #ifdef BSP_USING_ADC1
  32. ADC1_INDEX,
  33. #endif
  34. #ifdef BSP_USING_ADC2
  35. ADC2_INDEX,
  36. #endif
  37. #ifdef BSP_USING_ADC3
  38. ADC3_INDEX,
  39. #endif
  40. };
  41. static adc_device _g_adc_dev_array[] =
  42. {
  43. #ifdef BSP_USING_ADC1
  44. {
  45. {0},
  46. CM_ADC1,
  47. ADC1_INIT_PARAMS,
  48. },
  49. #endif
  50. #ifdef BSP_USING_ADC2
  51. {
  52. {0},
  53. CM_ADC2,
  54. ADC2_INIT_PARAMS,
  55. },
  56. #endif
  57. #ifdef BSP_USING_ADC3
  58. {
  59. {0},
  60. CM_ADC3,
  61. ADC3_INIT_PARAMS,
  62. },
  63. #endif
  64. };
  65. static void _adc_internal_trigger0_set(adc_device *p_adc_dev)
  66. {
  67. uint32_t u32TriggerSel;
  68. 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);
  69. if (is_internal_trig0_enabled == RT_FALSE)
  70. {
  71. return;
  72. }
  73. switch ((rt_uint32_t)p_adc_dev->instance)
  74. {
  75. case (rt_uint32_t)CM_ADC1:
  76. u32TriggerSel = AOS_ADC1_0;
  77. break;
  78. case (rt_uint32_t)CM_ADC2:
  79. u32TriggerSel = AOS_ADC2_0;
  80. break;
  81. #if defined (HC32F472) || defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) || defined (HC32F334)
  82. case (rt_uint32_t)CM_ADC3:
  83. u32TriggerSel = AOS_ADC3_0;
  84. break;
  85. #endif
  86. default:
  87. break;
  88. }
  89. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg0_enable);
  90. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg1_enable);
  91. AOS_SetTriggerEventSrc(u32TriggerSel, p_adc_dev->init.internal_trig0_sel);
  92. }
  93. static void _adc_internal_trigger1_set(adc_device *p_adc_dev)
  94. {
  95. uint32_t u32TriggerSel;
  96. 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);
  97. if (is_internal_trig1_enabled == RT_FALSE)
  98. {
  99. return;
  100. }
  101. switch ((rt_uint32_t)p_adc_dev->instance)
  102. {
  103. case (rt_uint32_t)CM_ADC1:
  104. u32TriggerSel = AOS_ADC1_1;
  105. break;
  106. case (rt_uint32_t)CM_ADC2:
  107. u32TriggerSel = AOS_ADC2_1;
  108. break;
  109. #if defined (HC32F472) || defined (HC32F4A0) || defined (HC32F448) || defined (HC32F4A8) || defined (HC32F334)
  110. case (rt_uint32_t)CM_ADC3:
  111. u32TriggerSel = AOS_ADC3_1;
  112. break;
  113. #endif
  114. default:
  115. break;
  116. }
  117. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg0_enable);
  118. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg1_enable);
  119. AOS_SetTriggerEventSrc(u32TriggerSel, p_adc_dev->init.internal_trig1_sel);
  120. }
  121. static rt_err_t _adc_enable(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
  122. {
  123. adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
  124. ADC_ChCmd(p_adc_dev->instance, ADC_SEQ_A, channel, (en_functional_state_t)enabled);
  125. /* user_data != NULL */
  126. if (device->parent.user_data != RT_NULL)
  127. {
  128. struct adc_dev_priv_params *adc_dev_priv = device->parent.user_data;
  129. if ((ADC_USING_EOCA_DMA_FLAG == adc_dev_priv->flag) && (adc_dev_priv->ops->dma_trig_config != RT_NULL))
  130. {
  131. adc_dev_priv->ops->dma_trig_config();
  132. }
  133. }
  134. return 0;
  135. }
  136. static rt_err_t _adc_convert(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
  137. {
  138. rt_err_t rt_ret = -RT_ERROR;
  139. rt_uint32_t timeCnt;
  140. if (!value)
  141. {
  142. return -RT_EINVAL;
  143. }
  144. adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
  145. if (p_adc_dev->init.hard_trig_enable == RT_FALSE)
  146. {
  147. if (p_adc_dev->instance->STR == 0)
  148. {
  149. ADC_Start(p_adc_dev->instance);
  150. }
  151. uint32_t start_time = rt_tick_get();
  152. do
  153. {
  154. if (ADC_GetStatus(p_adc_dev->instance, ADC_FLAG_EOCA) == SET)
  155. {
  156. ADC_ClearStatus(p_adc_dev->instance, ADC_FLAG_EOCA);
  157. rt_ret = LL_OK;
  158. break;
  159. }
  160. }
  161. while ((rt_tick_get() - start_time) < p_adc_dev->init.eoc_poll_time_max);
  162. if (rt_ret == LL_OK)
  163. {
  164. /* Get any ADC value of sequence A channel that needed. */
  165. *value = ADC_GetValue(p_adc_dev->instance, channel);
  166. }
  167. }
  168. else if (p_adc_dev->init.hard_trig_enable == RT_TRUE)
  169. {
  170. /* DMA src/dest/tc... config; start/stop trigger */
  171. if (p_adc_dev->init.adc_eoca_dma != RT_NULL)
  172. {
  173. if (p_adc_dev->rt_adc.parent.user_data != RT_NULL)
  174. {
  175. struct adc_dev_priv_params *adc_dev_priv = device->parent.user_data;
  176. struct dma_config *adc_eoca_dma;
  177. adc_eoca_dma = p_adc_dev->init.adc_eoca_dma;
  178. if ((ADC_USING_EOCA_DMA_FLAG == adc_dev_priv->flag) && (adc_dev_priv->ops->dma_trig_start != RT_NULL))
  179. {
  180. DMA_ClearTransCompleteStatus(adc_eoca_dma->Instance, adc_eoca_dma->flag);
  181. (void)DMA_SetTransCount(adc_eoca_dma->Instance, adc_eoca_dma->channel, 1U);
  182. (void)DMA_SetSrcAddr(adc_eoca_dma->Instance, adc_eoca_dma->channel, (uint32_t)(&p_adc_dev->instance->DR0) + channel * 2);
  183. (void)DMA_SetDestAddr(adc_eoca_dma->Instance, adc_eoca_dma->channel, (uint32_t)(value));
  184. (void)DMA_ChCmd(adc_eoca_dma->Instance, adc_eoca_dma->channel, ENABLE);
  185. adc_dev_priv->ops->dma_trig_start();
  186. timeCnt = 0;
  187. /* wait DMA transfer completed */
  188. while (RESET == DMA_GetTransCompleteStatus(adc_eoca_dma->Instance, adc_eoca_dma->flag) && (timeCnt < p_adc_dev->init.eoc_poll_time_max))
  189. {
  190. rt_thread_mdelay(1);
  191. timeCnt++;
  192. }
  193. if (timeCnt >= p_adc_dev->init.eoc_poll_time_max)
  194. {
  195. (void)DMA_ChCmd(adc_eoca_dma->Instance, adc_eoca_dma->channel, DISABLE);
  196. rt_ret = -RT_ETIMEOUT;
  197. }
  198. if (adc_dev_priv->ops->dma_trig_stop != RT_NULL)
  199. {
  200. adc_dev_priv->ops->dma_trig_stop();
  201. }
  202. }
  203. }
  204. }
  205. }
  206. return rt_ret;
  207. }
  208. static rt_uint8_t _adc_get_resolution(struct rt_adc_device *device)
  209. {
  210. rt_uint8_t resolution = 0;
  211. rt_uint16_t accsel;
  212. adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
  213. accsel = ADC_GetResolution(p_adc_dev->instance);
  214. switch (accsel)
  215. {
  216. case ADC_RESOLUTION_12BIT:
  217. resolution = 12;
  218. break;
  219. case ADC_RESOLUTION_10BIT:
  220. resolution = 10;
  221. break;
  222. case ADC_RESOLUTION_8BIT:
  223. resolution = 8;
  224. break;
  225. default:
  226. break;
  227. }
  228. return resolution;
  229. }
  230. static rt_int16_t _adc_get_vref(struct rt_adc_device *device)
  231. {
  232. rt_int16_t vref = 0;
  233. adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
  234. vref = p_adc_dev->init.vref;
  235. return vref;
  236. }
  237. static struct rt_adc_ops _g_adc_ops =
  238. {
  239. _adc_enable,
  240. _adc_convert,
  241. _adc_get_resolution,
  242. _adc_get_vref
  243. };
  244. static void _adc_clock_enable(void)
  245. {
  246. #if defined(BSP_USING_ADC1)
  247. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC1, ENABLE);
  248. #endif
  249. #if defined(BSP_USING_ADC2)
  250. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC2, ENABLE);
  251. #endif
  252. #if defined(BSP_USING_ADC3)
  253. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC3, ENABLE);
  254. #endif
  255. }
  256. static void hc32_adc_get_dma_info(void)
  257. {
  258. #ifdef BSP_ADC1_USING_DMA
  259. static struct dma_config adc1_eoca_dma = ADC1_EOCA_DMA_CONFIG;
  260. _g_adc_dev_array[ADC1_INDEX].init.adc_eoca_dma = &adc1_eoca_dma;
  261. #endif
  262. #ifdef BSP_ADC2_USING_DMA
  263. static struct dma_config adc2_eoca_dma = ADC2_EOCA_DMA_CONFIG;
  264. _g_adc_dev_array[ADC2_INDEX].init.adc_eoca_dma = &adc2_eoca_dma;
  265. #endif
  266. #ifdef BSP_ADC3_USING_DMA
  267. static struct dma_config adc3_eoca_dma = ADC3_EOCA_DMA_CONFIG;
  268. _g_adc_dev_array[ADC3_INDEX].init.adc_eoca_dma = &adc3_eoca_dma;
  269. #endif
  270. }
  271. static void hc32_adc_dma_config(adc_device *p_adc_dev)
  272. {
  273. stc_dma_init_t stcDmaInit;
  274. /* DMA/AOS FCG enable */
  275. FCG_Fcg0PeriphClockCmd(p_adc_dev->init.adc_eoca_dma->clock, ENABLE);
  276. (void)DMA_StructInit(&stcDmaInit);
  277. stcDmaInit.u32BlockSize = 1UL;
  278. stcDmaInit.u32TransCount = 1UL;
  279. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_16BIT;
  280. stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_FIX;
  281. stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;
  282. stcDmaInit.u32SrcAddr = (uint32_t)RT_NULL;
  283. stcDmaInit.u32DestAddr = (uint32_t)RT_NULL;
  284. if (LL_OK != DMA_Init(p_adc_dev->init.adc_eoca_dma->Instance, p_adc_dev->init.adc_eoca_dma->channel, &stcDmaInit))
  285. {
  286. rt_kprintf("[%s:%d]ADC DMA init error!\n", __func__, __LINE__);
  287. }
  288. AOS_SetTriggerEventSrc(p_adc_dev->init.adc_eoca_dma->trigger_select, p_adc_dev->init.adc_eoca_dma->trigger_event);
  289. /* Clear DMA TC flag */
  290. DMA_ClearTransCompleteStatus(p_adc_dev->init.adc_eoca_dma->Instance, p_adc_dev->init.adc_eoca_dma->flag);
  291. /* Enable DMA unit */
  292. DMA_Cmd(p_adc_dev->init.adc_eoca_dma->Instance, ENABLE);
  293. }
  294. extern rt_err_t rt_hw_board_adc_init(CM_ADC_TypeDef *ADCx);
  295. int rt_hw_adc_init(void)
  296. {
  297. int ret = RT_EOK, i = 0;
  298. stc_adc_init_t stcAdcInit = {0};
  299. int32_t ll_ret = 0;
  300. _adc_clock_enable();
  301. hc32_adc_get_dma_info();
  302. uint32_t dev_cnt = sizeof(_g_adc_dev_array) / sizeof(_g_adc_dev_array[0]);
  303. for (; i < dev_cnt; i++)
  304. {
  305. ADC_DeInit(_g_adc_dev_array[i].instance);
  306. /* Initializes ADC. */
  307. stcAdcInit.u16Resolution = _g_adc_dev_array[i].init.resolution;
  308. stcAdcInit.u16DataAlign = _g_adc_dev_array[i].init.data_align;
  309. stcAdcInit.u16ScanMode = (_g_adc_dev_array[i].init.continue_conv_mode_enable) ? ADC_MD_SEQA_CONT : ADC_MD_SEQA_SINGLESHOT;
  310. ll_ret = ADC_Init((void *)_g_adc_dev_array[i].instance, &stcAdcInit);
  311. if (ll_ret != LL_OK)
  312. {
  313. ret = -RT_ERROR;
  314. break;
  315. }
  316. ADC_TriggerCmd(_g_adc_dev_array[i].instance, ADC_SEQ_A, (en_functional_state_t)_g_adc_dev_array[i].init.hard_trig_enable);
  317. ADC_TriggerConfig(_g_adc_dev_array[i].instance, ADC_SEQ_A, _g_adc_dev_array[i].init.hard_trig_src);
  318. if (_g_adc_dev_array[i].init.hard_trig_enable && _g_adc_dev_array[i].init.hard_trig_src != ADC_HARDTRIG_ADTRG_PIN)
  319. {
  320. _adc_internal_trigger0_set(&_g_adc_dev_array[i]);
  321. _adc_internal_trigger1_set(&_g_adc_dev_array[i]);
  322. }
  323. if (_g_adc_dev_array[i].init.adc_eoca_dma != RT_NULL)
  324. {
  325. hc32_adc_dma_config(&_g_adc_dev_array[i]);
  326. }
  327. rt_hw_board_adc_init((void *)_g_adc_dev_array[i].instance);
  328. ret = rt_hw_adc_register(&_g_adc_dev_array[i].rt_adc, \
  329. (const char *)_g_adc_dev_array[i].init.name, \
  330. &_g_adc_ops, (void *)_g_adc_dev_array[i].instance);
  331. if (ret != RT_EOK)
  332. {
  333. LOG_E("failed register %s, err=%d", _g_adc_dev_array[i].init.name, ret);
  334. }
  335. }
  336. return ret;
  337. }
  338. INIT_DEVICE_EXPORT(rt_hw_adc_init);
  339. #endif
  340. #endif /* BSP_USING_ADC */