drv_adc.c 11 KB

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