drv_adc.c 11 KB

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