drv_adc.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. */
  10. #include <board.h>
  11. #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
  12. #define LOG_TAG "drv.adc"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. #define DRV_ADC_CHANNEL_MAX_NUM 14
  16. #define DRV_ADC_TIME_OUT 0xFFF
  17. #define _ADC_GET_PORT(pin_num) ((GPIO_T *)(GPIOA_BASE + (0x400u * (((pin_num) >> 4) & 0xFu))))
  18. #define _ADC_GET_PIN(pin_num) ((uint16_t)(1u << ((pin_num) & 0xFu)))
  19. struct apm32_adc
  20. {
  21. const char *name;
  22. ADC_T *adc;
  23. ADC_Config_T adc_config;
  24. rt_base_t channel_pin[DRV_ADC_CHANNEL_MAX_NUM];
  25. struct rt_adc_device adc_dev;
  26. };
  27. static struct apm32_adc adc_config[] =
  28. {
  29. #ifdef BSP_USING_ADC1
  30. {
  31. "adc1",
  32. ADC1,
  33. {
  34. ADC_MODE_INDEPENDENT,
  35. DISABLE,
  36. DISABLE,
  37. ADC_EXT_TRIG_CONV_None,
  38. ADC_DATA_ALIGN_RIGHT,
  39. 1
  40. },
  41. {
  42. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3), GET_PIN(A, 4),
  43. GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7), GET_PIN(B, 0), GET_PIN(B, 1),
  44. GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3)
  45. },
  46. RT_NULL
  47. },
  48. #endif
  49. #ifdef BSP_USING_ADC2
  50. {
  51. "adc2",
  52. ADC2,
  53. {
  54. ADC_MODE_INDEPENDENT,
  55. DISABLE,
  56. DISABLE,
  57. ADC_EXT_TRIG_CONV_None,
  58. ADC_DATA_ALIGN_RIGHT,
  59. 1
  60. },
  61. {
  62. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3), GET_PIN(A, 4),
  63. GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7), GET_PIN(B, 0), GET_PIN(B, 1),
  64. GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3)
  65. },
  66. RT_NULL
  67. },
  68. #endif
  69. #ifdef BSP_USING_ADC3
  70. {
  71. "adc3",
  72. ADC3,
  73. {
  74. ADC_MODE_INDEPENDENT,
  75. DISABLE,
  76. DISABLE,
  77. ADC_EXT_TRIG_CONV_None,
  78. ADC_DATA_ALIGN_RIGHT,
  79. 1
  80. },
  81. {
  82. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3), GET_PIN(F, 6),
  83. GET_PIN(F, 7), GET_PIN(F, 8), GET_PIN(F, 9), GET_PIN(F, 10)
  84. },
  85. RT_NULL
  86. },
  87. #endif
  88. };
  89. static rt_err_t _adc_channel_check(struct rt_adc_device *device, rt_uint32_t channel)
  90. {
  91. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  92. if (adc_cfg->adc == ADC3)
  93. {
  94. if (channel <= 8)
  95. {
  96. return RT_EOK;
  97. }
  98. }
  99. else
  100. {
  101. if (channel <= 13)
  102. {
  103. return RT_EOK;
  104. }
  105. }
  106. LOG_E("channel %d of %s is not supported.", channel, adc_cfg->name);
  107. return -RT_ERROR;
  108. }
  109. static rt_err_t _adc_gpio_init(struct rt_adc_device *device, rt_uint32_t channel)
  110. {
  111. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  112. GPIO_Config_T hw_gpio_config;
  113. if (_adc_channel_check(device, channel) != RT_EOK)
  114. {
  115. return -RT_ERROR;
  116. }
  117. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
  118. hw_gpio_config.mode = GPIO_MODE_ANALOG;
  119. hw_gpio_config.pin = _ADC_GET_PIN(adc_cfg->channel_pin[channel]);
  120. GPIO_Config(_ADC_GET_PORT(adc_cfg->channel_pin[channel]), &hw_gpio_config);
  121. return RT_EOK;
  122. }
  123. /**
  124. * @brief This function will control the adc to enable or disable.
  125. *
  126. * @param device is a pointer to adc device.
  127. *
  128. * @param channel is the adc channel.
  129. *
  130. * @param enabled is the status to indicate enable or disable.
  131. *
  132. * @return RT_EOK indicates successful enable or disable adc, other value indicates failed.
  133. */
  134. static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  135. {
  136. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  137. RT_ASSERT(device != RT_NULL);
  138. if (enabled)
  139. {
  140. if (adc_cfg->adc == ADC1)
  141. {
  142. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  143. }
  144. else if (adc_cfg->adc == ADC2)
  145. {
  146. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC2);
  147. }
  148. else
  149. {
  150. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC3);
  151. }
  152. if (_adc_gpio_init(device, channel) != RT_EOK)
  153. {
  154. return -RT_ERROR;
  155. }
  156. ADC_Config(adc_cfg->adc, &adc_cfg->adc_config);
  157. ADC_Enable(adc_cfg->adc);
  158. }
  159. else
  160. {
  161. ADC_Disable(adc_cfg->adc);
  162. }
  163. return RT_EOK;
  164. }
  165. /**
  166. * @brief This function will get the adc conversion value.
  167. *
  168. * @param device is a pointer to adc device.
  169. *
  170. * @param channel is the adc channel.
  171. *
  172. * @param value is a pointer to the adc conversion value.
  173. *
  174. * @return RT_EOK indicates successful get adc value, other value indicates failed.
  175. */
  176. static rt_err_t _adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  177. {
  178. struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
  179. volatile rt_uint32_t counter = 0;
  180. RT_ASSERT(device != RT_NULL);
  181. RT_ASSERT(value != RT_NULL);
  182. if (_adc_channel_check(device, channel) != RT_EOK)
  183. {
  184. return -RT_ERROR;
  185. }
  186. ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_13CYCLES5);
  187. ADC_StartCalibration(adc_cfg->adc);
  188. /* Check the end of ADC calibration */
  189. while (ADC_ReadCalibrationStartFlag(adc_cfg->adc))
  190. {
  191. if (++counter > DRV_ADC_TIME_OUT)
  192. {
  193. return RT_ETIMEOUT;
  194. }
  195. }
  196. ADC_EnableSoftwareStartConv(adc_cfg->adc);
  197. counter = 0;
  198. while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC))
  199. {
  200. if (++counter > DRV_ADC_TIME_OUT)
  201. {
  202. return RT_ETIMEOUT;
  203. }
  204. }
  205. *value = ADC_ReadConversionValue(adc_cfg->adc);
  206. return RT_EOK;
  207. }
  208. static const struct rt_adc_ops _adc_ops =
  209. {
  210. .enabled = _adc_enabled,
  211. .convert = _adc_get_value,
  212. };
  213. /**
  214. * @brief ADC initialization function.
  215. *
  216. * @return RT_EOK indicates successful initialization, other value indicates failed;
  217. */
  218. static int rt_hw_adc_init(void)
  219. {
  220. rt_err_t result = RT_EOK;
  221. rt_size_t obj_num = sizeof(adc_config) / sizeof(struct apm32_adc);
  222. rt_uint32_t i = 0;
  223. for (i = 0; i < obj_num; i++)
  224. {
  225. /* register ADC device */
  226. if (rt_hw_adc_register(&adc_config[i].adc_dev, adc_config[i].name, &_adc_ops, adc_config))
  227. {
  228. LOG_D("%s init success", adc_config[i].name);
  229. }
  230. else
  231. {
  232. LOG_D("%s init failed", adc_config[i].name);
  233. result = -RT_ERROR;
  234. }
  235. }
  236. return result;
  237. }
  238. INIT_BOARD_EXPORT(rt_hw_adc_init);
  239. #endif /* BSP_USING_ADCX */