drv_adc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-03-04 stevetong459 first version
  9. * 2022-07-15 Aligagago add APM32F4 series MCU support
  10. * 2022-12-26 luobeihai add APM32F0 series MCU support
  11. * 2023-03-27 luobeihai add APM32E1/S1 series MCU support
  12. */
  13. #include <board.h>
  14. #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
  15. #define DBG_TAG "drv.adc"
  16. #define DBG_LVL DBG_INFO
  17. #include <rtdbg.h>
  18. #define DRV_ADC_CHANNEL_MAX_NUM 16
  19. #define DRV_ADC_TIME_OUT 0xFFF
  20. #define APM32_ADC_GET_PORT(pin_num) ((GPIO_T *)(GPIOA_BASE + (0x400u * (((pin_num) >> 4) & 0xFu))))
  21. #define APM32_ADC_GET_PIN(pin_num) ((uint16_t)(1u << ((pin_num) & 0xFu)))
  22. struct apm32_adc
  23. {
  24. const char *name;
  25. ADC_T *adc;
  26. ADC_Config_T adc_config;
  27. rt_base_t channel_pin[DRV_ADC_CHANNEL_MAX_NUM];
  28. struct rt_adc_device adc_dev;
  29. };
  30. #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
  31. static struct apm32_adc adc_config[] =
  32. {
  33. #ifdef BSP_USING_ADC1
  34. {
  35. "adc1",
  36. ADC1,
  37. {
  38. ADC_MODE_INDEPENDENT,
  39. DISABLE,
  40. DISABLE,
  41. ADC_EXT_TRIG_CONV_None,
  42. ADC_DATA_ALIGN_RIGHT,
  43. 1
  44. },
  45. {
  46. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  47. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  48. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  49. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
  50. },
  51. },
  52. #endif
  53. #ifdef BSP_USING_ADC2
  54. {
  55. "adc2",
  56. ADC2,
  57. {
  58. ADC_MODE_INDEPENDENT,
  59. DISABLE,
  60. DISABLE,
  61. ADC_EXT_TRIG_CONV_None,
  62. ADC_DATA_ALIGN_RIGHT,
  63. 1
  64. },
  65. {
  66. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  67. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  68. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  69. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
  70. },
  71. },
  72. #endif
  73. #ifdef BSP_USING_ADC3
  74. {
  75. "adc3",
  76. ADC3,
  77. {
  78. ADC_MODE_INDEPENDENT,
  79. DISABLE,
  80. DISABLE,
  81. ADC_EXT_TRIG_CONV_None,
  82. ADC_DATA_ALIGN_RIGHT,
  83. 1
  84. },
  85. {
  86. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  87. GET_PIN(F, 6), GET_PIN(F, 7), GET_PIN(F, 8), GET_PIN(F, 9),
  88. GET_PIN(F, 10)
  89. },
  90. },
  91. #endif
  92. };
  93. #elif defined(SOC_SERIES_APM32F4)
  94. static struct apm32_adc adc_config[] =
  95. {
  96. #ifdef BSP_USING_ADC1
  97. {
  98. "adc1",
  99. ADC1,
  100. {
  101. ADC_RESOLUTION_12BIT,
  102. DISABLE,
  103. DISABLE,
  104. ADC_EXT_TRIG_EDGE_NONE,
  105. ADC_EXT_TRIG_CONV_TMR1_CC1,
  106. ADC_DATA_ALIGN_RIGHT,
  107. 1
  108. },
  109. {
  110. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  111. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  112. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  113. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
  114. },
  115. },
  116. #endif
  117. #ifdef BSP_USING_ADC2
  118. {
  119. "adc2",
  120. ADC2,
  121. {
  122. ADC_RESOLUTION_12BIT,
  123. DISABLE,
  124. DISABLE,
  125. ADC_EXT_TRIG_EDGE_NONE,
  126. ADC_EXT_TRIG_CONV_TMR1_CC1,
  127. ADC_DATA_ALIGN_RIGHT,
  128. 1
  129. },
  130. {
  131. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  132. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  133. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  134. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
  135. },
  136. },
  137. #endif
  138. #ifdef BSP_USING_ADC3
  139. {
  140. "adc3",
  141. ADC3,
  142. {
  143. ADC_RESOLUTION_12BIT,
  144. DISABLE,
  145. DISABLE,
  146. ADC_EXT_TRIG_EDGE_NONE,
  147. ADC_EXT_TRIG_CONV_TMR1_CC1,
  148. ADC_DATA_ALIGN_RIGHT,
  149. 1
  150. },
  151. {
  152. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  153. GET_PIN(F, 6), GET_PIN(F, 7), GET_PIN(F, 8), GET_PIN(F, 9),
  154. GET_PIN(F, 10), GET_PIN(F, 3), GET_PIN(C, 0), GET_PIN(C, 1),
  155. GET_PIN(C, 2), GET_PIN(C, 3)
  156. },
  157. },
  158. #endif
  159. };
  160. #elif defined(SOC_SERIES_APM32F0)
  161. static struct apm32_adc adc_config[] =
  162. {
  163. #ifdef BSP_USING_ADC1
  164. {
  165. "adc1",
  166. ADC,
  167. {
  168. ADC_RESOLUTION_12B,
  169. ADC_DATA_ALIGN_RIGHT,
  170. ADC_SCAN_DIR_UPWARD,
  171. ADC_CONVERSION_SINGLE,
  172. ADC_EXT_TRIG_CONV_TRG0,
  173. ADC_EXT_TRIG_EDGE_NONE
  174. },
  175. {
  176. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  177. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  178. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  179. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
  180. },
  181. },
  182. #endif
  183. };
  184. #endif
  185. static rt_err_t apm32_adc_channel_check(struct rt_adc_device *device, rt_uint32_t channel)
  186. {
  187. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  188. if ((adc_cfg->adc == ADC1) || (adc_cfg->adc == ADC2))
  189. {
  190. if (channel <= 15)
  191. {
  192. return RT_EOK;
  193. }
  194. }
  195. #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1)
  196. if (adc_cfg->adc == ADC3)
  197. {
  198. if (channel <= 8)
  199. {
  200. return RT_EOK;
  201. }
  202. }
  203. #endif
  204. #if defined(SOC_SERIES_APM32F4)
  205. if (adc_cfg->adc == ADC3)
  206. {
  207. if (channel <= 13)
  208. {
  209. return RT_EOK;
  210. }
  211. }
  212. #endif
  213. LOG_E("channel %d of %s is not supported.", channel, adc_cfg->name);
  214. return -RT_ERROR;
  215. }
  216. static rt_err_t apm32_adc_gpio_init(struct rt_adc_device *device, rt_uint32_t channel)
  217. {
  218. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  219. GPIO_Config_T hw_gpio_config;
  220. if (apm32_adc_channel_check(device, channel) != RT_EOK)
  221. {
  222. return -RT_ERROR;
  223. }
  224. #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
  225. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
  226. hw_gpio_config.mode = GPIO_MODE_ANALOG;
  227. #elif defined(SOC_SERIES_APM32F4)
  228. RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
  229. hw_gpio_config.mode = GPIO_MODE_AN;
  230. #elif defined(SOC_SERIES_APM32F0)
  231. RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
  232. hw_gpio_config.mode = GPIO_MODE_AN;
  233. #endif
  234. hw_gpio_config.pin = APM32_ADC_GET_PIN(adc_cfg->channel_pin[channel]);
  235. GPIO_Config(APM32_ADC_GET_PORT(adc_cfg->channel_pin[channel]), &hw_gpio_config);
  236. return RT_EOK;
  237. }
  238. /**
  239. * @brief This function will control the adc to enable or disable.
  240. *
  241. * @param device is a pointer to adc device.
  242. *
  243. * @param channel is the adc channel.
  244. *
  245. * @param enabled is the status to indicate enable or disable.
  246. *
  247. * @return RT_EOK indicates successful enable or disable adc, other value indicates failed.
  248. */
  249. static rt_err_t apm32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  250. {
  251. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  252. RT_ASSERT(device != RT_NULL);
  253. #if defined(SOC_SERIES_APM32F0)
  254. if (enabled)
  255. {
  256. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  257. if (apm32_adc_gpio_init(device, channel) != RT_EOK)
  258. {
  259. return -RT_ERROR;
  260. }
  261. ADC_Config(&adc_cfg->adc_config);
  262. ADC_Enable();
  263. }
  264. else
  265. {
  266. ADC_Disable();
  267. }
  268. #elif defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1) \
  269. || defined(SOC_SERIES_APM32F4)
  270. if (enabled)
  271. {
  272. if (adc_cfg->adc == ADC1)
  273. {
  274. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  275. }
  276. else if (adc_cfg->adc == ADC2)
  277. {
  278. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC2);
  279. }
  280. #ifdef BSP_USING_ADC3
  281. else if (adc_cfg->adc == ADC3)
  282. {
  283. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC3);
  284. }
  285. #endif /* BSP_USING_ADC3 */
  286. if (apm32_adc_gpio_init(device, channel) != RT_EOK)
  287. {
  288. return -RT_ERROR;
  289. }
  290. ADC_Config(adc_cfg->adc, &adc_cfg->adc_config);
  291. ADC_Enable(adc_cfg->adc);
  292. }
  293. else
  294. {
  295. ADC_Disable(adc_cfg->adc);
  296. }
  297. #endif /* SOC_SERIES_APM32F0 */
  298. return RT_EOK;
  299. }
  300. /**
  301. * @brief This function will get the adc conversion value.
  302. *
  303. * @param device is a pointer to adc device.
  304. *
  305. * @param channel is the adc channel.
  306. *
  307. * @param value is a pointer to the adc conversion value.
  308. *
  309. * @return RT_EOK indicates successful get adc value, other value indicates failed.
  310. */
  311. static rt_err_t apm32_adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  312. {
  313. #if !defined(SOC_SERIES_APM32F0)
  314. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  315. #endif
  316. volatile rt_uint32_t counter = 0;
  317. RT_ASSERT(device != RT_NULL);
  318. RT_ASSERT(value != RT_NULL);
  319. if (apm32_adc_channel_check(device, channel) != RT_EOK)
  320. {
  321. return -RT_ERROR;
  322. }
  323. #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
  324. ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_13CYCLES5);
  325. ADC_StartCalibration(adc_cfg->adc);
  326. /* Check the end of ADC calibration */
  327. while (ADC_ReadCalibrationStartFlag(adc_cfg->adc))
  328. {
  329. if (++counter > DRV_ADC_TIME_OUT)
  330. {
  331. return -RT_ETIMEOUT;
  332. }
  333. }
  334. ADC_EnableSoftwareStartConv(adc_cfg->adc);
  335. while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC))
  336. {
  337. if (++counter > DRV_ADC_TIME_OUT)
  338. {
  339. return -RT_ETIMEOUT;
  340. }
  341. }
  342. *value = ADC_ReadConversionValue(adc_cfg->adc);
  343. #elif defined(SOC_SERIES_APM32F4)
  344. ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_15CYCLES);
  345. ADC_SoftwareStartConv(adc_cfg->adc);
  346. while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC))
  347. {
  348. if (++counter > DRV_ADC_TIME_OUT)
  349. {
  350. return -RT_ETIMEOUT;
  351. }
  352. }
  353. *value = ADC_ReadConversionValue(adc_cfg->adc);
  354. #elif defined(SOC_SERIES_APM32F0)
  355. ADC_ConfigChannel((uint16_t)(1u << ((channel) & 0xFu)), ADC_SAMPLE_TIME_239_5);
  356. ADC_StartConversion();
  357. while (!ADC_ReadStatusFlag(ADC_FLAG_CC))
  358. {
  359. if (++counter > DRV_ADC_TIME_OUT)
  360. {
  361. return -RT_ETIMEOUT;
  362. }
  363. }
  364. *value = ADC_ReadConversionValue();
  365. #endif
  366. return RT_EOK;
  367. }
  368. static const struct rt_adc_ops apm32_adc_ops =
  369. {
  370. .enabled = apm32_adc_enabled,
  371. .convert = apm32_adc_get_value,
  372. };
  373. /**
  374. * @brief ADC initialization function.
  375. *
  376. * @return RT_EOK indicates successful initialization, other value indicates failed;
  377. */
  378. static int rt_hw_adc_init(void)
  379. {
  380. rt_err_t result = RT_EOK;
  381. rt_size_t obj_num = sizeof(adc_config) / sizeof(struct apm32_adc);
  382. rt_uint32_t i = 0;
  383. for (i = 0; i < obj_num; i++)
  384. {
  385. /* register ADC device */
  386. if (rt_hw_adc_register(&adc_config[i].adc_dev, adc_config[i].name, &apm32_adc_ops, &adc_config[i]) == RT_EOK)
  387. {
  388. LOG_D("%s init success", adc_config[i].name);
  389. }
  390. else
  391. {
  392. LOG_D("%s init failed", adc_config[i].name);
  393. result = -RT_ERROR;
  394. }
  395. }
  396. return result;
  397. }
  398. INIT_BOARD_EXPORT(rt_hw_adc_init);
  399. #endif /* BSP_USING_ADCX */