drv_adc.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. * Copyright (c) 2022, Xiaohua Semiconductor Co., Ltd.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2022-04-28 CDT first version
  10. * 2022-06-08 xiaoxiaolisunny add hc32f460 series
  11. * 2022-06-14 CDT fix a bug of internal trigger
  12. */
  13. #include <board.h>
  14. #include <drivers/adc.h>
  15. #include <drv_adc.h>
  16. #include <drv_config.h>
  17. #define DBG_TAG "drv.adc"
  18. #define DBG_LVL DBG_INFO
  19. #include <rtdbg.h>
  20. #ifdef RT_USING_ADC
  21. typedef struct
  22. {
  23. struct rt_adc_device rt_adc;
  24. CM_ADC_TypeDef *instance;
  25. struct adc_dev_init_params init;
  26. } adc_device;
  27. #if !defined(BSP_USING_ADC1) && !defined(BSP_USING_ADC2) && !defined(BSP_USING_ADC3)
  28. #error "Please define at least one BSP_USING_ADCx"
  29. #endif
  30. static adc_device g_adc_dev_array[] =
  31. {
  32. #ifdef BSP_USING_ADC1
  33. {
  34. {0},
  35. CM_ADC1,
  36. ADC1_INIT_PARAMS,
  37. },
  38. #endif
  39. #ifdef BSP_USING_ADC2
  40. {
  41. {0},
  42. CM_ADC2,
  43. ADC2_INIT_PARAMS,
  44. },
  45. #endif
  46. #ifdef BSP_USING_ADC3
  47. {
  48. {0},
  49. CM_ADC3,
  50. ADC3_INIT_PARAMS,
  51. },
  52. #endif
  53. };
  54. static void _adc_internal_trigger0_set(adc_device *p_adc_dev)
  55. {
  56. uint32_t u32TriggerSel;
  57. 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);
  58. if (is_internal_trig0_enabled == RT_FALSE)
  59. {
  60. return;
  61. }
  62. #if defined(HC32F4A0)
  63. switch ((rt_uint32_t)p_adc_dev->instance)
  64. {
  65. case (rt_uint32_t)CM_ADC1:
  66. u32TriggerSel = AOS_ADC1_0;
  67. break;
  68. case (rt_uint32_t)CM_ADC2:
  69. u32TriggerSel = AOS_ADC2_0;
  70. break;
  71. case (rt_uint32_t)CM_ADC3:
  72. u32TriggerSel = AOS_ADC3_0;
  73. break;
  74. default:
  75. break;
  76. }
  77. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg0_enable);
  78. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg1_enable);
  79. #endif
  80. #if defined(HC32F460)
  81. switch ((rt_uint32_t)p_adc_dev->instance)
  82. {
  83. case (rt_uint32_t)CM_ADC1:
  84. u32TriggerSel = AOS_ADC1_0;
  85. break;
  86. case (rt_uint32_t)CM_ADC2:
  87. u32TriggerSel = AOS_ADC2_0;
  88. break;
  89. default:
  90. break;
  91. }
  92. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg0_enable);
  93. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig0_comtrg1_enable);
  94. #endif
  95. AOS_SetTriggerEventSrc(u32TriggerSel, p_adc_dev->init.internal_trig0_sel);
  96. }
  97. static void _adc_internal_trigger1_set(adc_device *p_adc_dev)
  98. {
  99. uint32_t u32TriggerSel;
  100. 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);
  101. if (is_internal_trig1_enabled == RT_FALSE)
  102. {
  103. return;
  104. }
  105. #if defined(HC32F4A0)
  106. switch ((rt_uint32_t)p_adc_dev->instance)
  107. {
  108. case (rt_uint32_t)CM_ADC1:
  109. u32TriggerSel = AOS_ADC1_1;
  110. break;
  111. case (rt_uint32_t)CM_ADC2:
  112. u32TriggerSel = AOS_ADC2_1;
  113. break;
  114. case (rt_uint32_t)CM_ADC3:
  115. u32TriggerSel = AOS_ADC3_1;
  116. break;
  117. default:
  118. break;
  119. }
  120. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg0_enable);
  121. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg1_enable);
  122. #endif
  123. #if defined(HC32F460)
  124. switch ((rt_uint32_t)p_adc_dev->instance)
  125. {
  126. case (rt_uint32_t)CM_ADC1:
  127. u32TriggerSel = AOS_ADC1_1;
  128. break;
  129. case (rt_uint32_t)CM_ADC2:
  130. u32TriggerSel = AOS_ADC2_1;
  131. break;
  132. default:
  133. break;
  134. }
  135. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG1, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg0_enable);
  136. AOS_CommonTriggerCmd(u32TriggerSel, AOS_COMM_TRIG2, (en_functional_state_t)p_adc_dev->init.internal_trig1_comtrg1_enable);
  137. #endif
  138. AOS_SetTriggerEventSrc(u32TriggerSel, p_adc_dev->init.internal_trig1_sel);
  139. }
  140. static rt_err_t _adc_enable(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  141. {
  142. adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
  143. ADC_ChCmd(p_adc_dev->instance, ADC_SEQ_A, channel, (en_functional_state_t)enabled);
  144. return 0;
  145. }
  146. static rt_err_t _adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  147. {
  148. rt_err_t rt_ret = RT_ERROR;
  149. if (!value)
  150. {
  151. return -RT_EINVAL;
  152. }
  153. adc_device *p_adc_dev = rt_container_of(device, adc_device, rt_adc);
  154. if (p_adc_dev->init.hard_trig_enable == RT_FALSE && p_adc_dev->instance->STR == 0)
  155. {
  156. ADC_Start(p_adc_dev->instance);
  157. }
  158. uint32_t start_time = rt_tick_get();
  159. do
  160. {
  161. if (ADC_GetStatus(p_adc_dev->instance, ADC_FLAG_EOCA) == SET)
  162. {
  163. ADC_ClearStatus(p_adc_dev->instance, ADC_FLAG_EOCA);
  164. rt_ret = LL_OK;
  165. break;
  166. }
  167. }
  168. while ((rt_tick_get() - start_time) < p_adc_dev->init.eoc_poll_time_max);
  169. if (rt_ret == LL_OK)
  170. {
  171. /* Get any ADC value of sequence A channel that needed. */
  172. *value = ADC_GetValue(p_adc_dev->instance, channel);
  173. }
  174. return rt_ret;
  175. }
  176. static struct rt_adc_ops g_adc_ops =
  177. {
  178. _adc_enable,
  179. _adc_convert,
  180. };
  181. static void _adc_clock_enable(void)
  182. {
  183. #if defined(HC32F4A0)
  184. #if defined(BSP_USING_ADC1)
  185. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC1, ENABLE);
  186. #endif
  187. #if defined(BSP_USING_ADC2)
  188. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC2, ENABLE);
  189. #endif
  190. #if defined(BSP_USING_ADC3)
  191. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC3, ENABLE);
  192. #endif
  193. #endif
  194. #if defined(HC32F460)
  195. #if defined(BSP_USING_ADC1)
  196. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC1, ENABLE);
  197. #endif
  198. #if defined(BSP_USING_ADC2)
  199. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC2, ENABLE);
  200. #endif
  201. #endif
  202. }
  203. extern rt_err_t rt_hw_board_adc_init(CM_ADC_TypeDef *ADCx);
  204. static int rt_hw_adc_init(void)
  205. {
  206. int ret, i = 0;
  207. stc_adc_init_t stcAdcInit = {0};
  208. int32_t ll_ret = 0;
  209. _adc_clock_enable();
  210. uint32_t dev_cnt = sizeof(g_adc_dev_array) / sizeof(g_adc_dev_array[0]);
  211. for (; i < dev_cnt; i++)
  212. {
  213. ADC_DeInit(g_adc_dev_array[i].instance);
  214. /* Initializes ADC. */
  215. stcAdcInit.u16Resolution = g_adc_dev_array[i].init.resolution;
  216. stcAdcInit.u16DataAlign = g_adc_dev_array[i].init.data_align;
  217. stcAdcInit.u16ScanMode = (g_adc_dev_array[i].init.continue_conv_mode_enable) ? ADC_MD_SEQA_CONT : ADC_MD_SEQA_SINGLESHOT;
  218. ll_ret = ADC_Init((void *)g_adc_dev_array[i].instance, &stcAdcInit);
  219. if (ll_ret != LL_OK)
  220. {
  221. ret = -RT_ERROR;
  222. break;
  223. }
  224. ADC_TriggerCmd(g_adc_dev_array[i].instance, ADC_SEQ_A, (en_functional_state_t)g_adc_dev_array[i].init.hard_trig_enable);
  225. ADC_TriggerConfig(g_adc_dev_array[i].instance, ADC_SEQ_A, g_adc_dev_array[i].init.hard_trig_src);
  226. if (g_adc_dev_array[i].init.hard_trig_enable && g_adc_dev_array[i].init.hard_trig_src != ADC_HARDTRIG_ADTRG_PIN)
  227. {
  228. _adc_internal_trigger0_set(&g_adc_dev_array[i]);
  229. _adc_internal_trigger1_set(&g_adc_dev_array[i]);
  230. }
  231. rt_hw_board_adc_init((void *)g_adc_dev_array[i].instance);
  232. ret = rt_hw_adc_register(&g_adc_dev_array[i].rt_adc, \
  233. (const char *)g_adc_dev_array[i].init.name, \
  234. &g_adc_ops, (void *)g_adc_dev_array[i].instance);
  235. if (ret != RT_EOK)
  236. {
  237. /* TODO err handler */
  238. // LOG_E("failed register %s, err=%d", g_adc_dev_array[i].name, ret);
  239. }
  240. }
  241. return ret;
  242. }
  243. INIT_DEVICE_EXPORT(rt_hw_adc_init);
  244. #endif