drv_adc.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Copyright (c) 2021-2023 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <rtthread.h>
  7. #ifdef BSP_USING_ADC
  8. #include <rtdevice.h>
  9. #include "board.h"
  10. #include "drv_adc.h"
  11. #ifdef BSP_USING_ADC12
  12. #include "hpm_adc12_drv.h"
  13. #endif
  14. #ifdef BSP_USING_ADC16
  15. #include "hpm_adc16_drv.h"
  16. #endif
  17. #include "hpm_sysctl_drv.h"
  18. typedef struct
  19. {
  20. bool enabled;
  21. } adc_channel_state_t;
  22. typedef struct
  23. {
  24. char *adc_name;
  25. struct rt_adc_device hpm_adc_device;
  26. bool is_adc12;
  27. bool adc_enabled;
  28. uint32_t adc_base;
  29. adc_channel_state_t chn_state[16];
  30. }hpm_rtt_adc;
  31. static uint32_t hpm_adc_init_clock(struct rt_adc_device *device);
  32. static rt_err_t hpm_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled);
  33. static rt_err_t hpm_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value);
  34. static rt_uint8_t hpm_get_resolution(struct rt_adc_device *device);
  35. static rt_int16_t hpm_get_vref(struct rt_adc_device *device);
  36. static const struct rt_adc_ops hpm_adc_ops =
  37. {
  38. .enabled = hpm_adc_enabled,
  39. .convert = hpm_get_adc_value,
  40. .get_resolution = hpm_get_resolution,
  41. .get_vref = hpm_get_vref,
  42. };
  43. static hpm_rtt_adc hpm_adc_config_tbl[] =
  44. {
  45. #ifdef BSP_USING_ADC0
  46. {
  47. .adc_name = "adc0",
  48. #ifdef BSP_USING_ADC12
  49. .is_adc12 = true,
  50. #else
  51. .is_adc12 = false,
  52. #endif
  53. .adc_base = (uint32_t)HPM_ADC0,
  54. },
  55. #endif
  56. #ifdef BSP_USING_ADC1
  57. {
  58. .adc_name = "adc1",
  59. #ifdef BSP_USING_ADC12
  60. .is_adc12 = true,
  61. #else
  62. .is_adc12 = false,
  63. #endif
  64. .adc_base = (uint32_t)HPM_ADC1,
  65. },
  66. #endif
  67. #ifdef BSP_USING_ADC2
  68. {
  69. .adc_name = "adc2",
  70. #ifdef BSP_USING_ADC12
  71. .is_adc12 = true,
  72. #else
  73. .is_adc12 = false,
  74. #endif
  75. .adc_base = (uint32_t)HPM_ADC2,
  76. },
  77. #endif
  78. #ifdef BSP_USING_ADC3
  79. {
  80. .adc_name = "adc3",
  81. .is_adc12 = false,
  82. .adc_base = (uint32_t)HPM_ADC3,
  83. },
  84. #endif
  85. };
  86. static uint8_t adc_nums = sizeof(hpm_adc_config_tbl) / sizeof(hpm_rtt_adc);
  87. static uint32_t hpm_adc_init_clock(struct rt_adc_device *device)
  88. {
  89. hpm_rtt_adc *hpm_adc;
  90. uint32_t clock_freq = 0;
  91. RT_ASSERT(device != RT_NULL);
  92. hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
  93. #if defined(ADC12_SOC_MAX_CH_NUM)
  94. if (hpm_adc->is_adc12)
  95. {
  96. clock_freq = board_init_adc12_clock((ADC12_Type*)hpm_adc->adc_base,true);
  97. } else
  98. #endif
  99. {
  100. clock_freq = board_init_adc16_clock((ADC16_Type*)hpm_adc->adc_base,true);
  101. }
  102. return clock_freq;
  103. }
  104. static rt_err_t init_adc_config(hpm_rtt_adc *adc)
  105. {
  106. hpm_stat_t ret;
  107. if (adc->is_adc12) {
  108. #ifdef BSP_USING_ADC12
  109. adc12_config_t cfg;
  110. adc12_get_default_config(&cfg);
  111. cfg.res = adc12_res_12_bits;
  112. cfg.conv_mode = adc12_conv_mode_oneshot;
  113. cfg.adc_ahb_en = true;
  114. cfg.adc_clk_div = 3;
  115. ret = adc12_init((ADC12_Type *)adc->adc_base, &cfg);
  116. if (ret != status_success) {
  117. return -RT_ERROR;
  118. }
  119. #endif
  120. } else {
  121. #ifdef BSP_USING_ADC16
  122. adc16_config_t cfg;
  123. adc16_get_default_config(&cfg);
  124. cfg.conv_mode = adc16_conv_mode_oneshot;
  125. cfg.res = adc16_res_16_bits;
  126. cfg.adc_clk_div = 4;
  127. cfg.sel_sync_ahb = true;
  128. cfg.adc_ahb_en = true;
  129. cfg.wait_dis = 0;
  130. ret = adc16_init((ADC16_Type *)adc->adc_base, &cfg);
  131. if (ret != status_success) {
  132. return -RT_ERROR;
  133. }
  134. #endif
  135. #if defined(ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT) && ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT
  136. /* enable oneshot mode */
  137. adc16_enable_oneshot_mode((ADC16_Type *)adc->adc_base);
  138. #endif
  139. }
  140. return RT_EOK;
  141. }
  142. static rt_err_t init_channel_config(hpm_rtt_adc *adc, uint16_t channel)
  143. {
  144. hpm_stat_t ret;
  145. if (adc->is_adc12) {
  146. #ifdef BSP_USING_ADC12
  147. adc12_channel_config_t ch_cfg;
  148. adc12_get_channel_default_config(&ch_cfg);
  149. ch_cfg.ch = channel;
  150. ch_cfg.diff_sel = adc12_sample_signal_single_ended;
  151. ch_cfg.sample_cycle = 20;
  152. ret = adc12_init_channel((ADC12_Type *)adc->adc_base, &ch_cfg);
  153. if (ret != status_success) {
  154. return -RT_ERROR;
  155. }
  156. #endif
  157. } else {
  158. #ifdef BSP_USING_ADC16
  159. adc16_channel_config_t ch_cfg;
  160. adc16_get_channel_default_config(&ch_cfg);
  161. ch_cfg.ch = channel;
  162. ch_cfg.sample_cycle = 20;
  163. ret = adc16_init_channel((ADC16_Type *)adc->adc_base, &ch_cfg);
  164. if (ret != status_success) {
  165. return -RT_ERROR;
  166. }
  167. #endif
  168. }
  169. return RT_EOK;
  170. }
  171. static rt_err_t hpm_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
  172. {
  173. hpm_rtt_adc *hpm_adc;
  174. rt_err_t ret;
  175. RT_ASSERT(device != RT_NULL);
  176. hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
  177. if (enabled == RT_TRUE) {
  178. if (!hpm_adc->chn_state[channel].enabled)
  179. {
  180. if (!hpm_adc->adc_enabled)
  181. {
  182. (void)hpm_adc_init_clock(device);
  183. ret = init_adc_config(hpm_adc);
  184. if (ret != RT_EOK) {
  185. return -RT_ERROR;
  186. }
  187. hpm_adc->adc_enabled = true;
  188. }
  189. hpm_adc->chn_state[channel].enabled = true;
  190. ret = init_channel_config(hpm_adc, channel);
  191. if (ret != RT_EOK) {
  192. return -RT_ERROR;
  193. }
  194. }
  195. }
  196. else
  197. {
  198. /* Since the ADC channel cannot be truly disabled, do nothing here */
  199. }
  200. return RT_EOK;
  201. }
  202. static rt_err_t hpm_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
  203. {
  204. hpm_rtt_adc *hpm_adc;
  205. rt_err_t ret;
  206. rt_uint16_t val;
  207. RT_ASSERT(device != RT_NULL);
  208. RT_ASSERT(value != RT_NULL);
  209. hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
  210. uint32_t adc_chn = (uint16_t)channel;
  211. if (hpm_adc->is_adc12) {
  212. #ifdef BSP_USING_ADC12
  213. adc12_get_oneshot_result((ADC12_Type *)hpm_adc->adc_base, adc_chn, &val);
  214. *value = val;
  215. #endif
  216. } else {
  217. #ifdef BSP_USING_ADC16
  218. hpm_stat_t status = adc16_get_oneshot_result((ADC16_Type *)hpm_adc->adc_base, adc_chn, &val);
  219. *value = val;
  220. // rt_kprintf("%s, status=%d\n", __func__, status);
  221. #endif
  222. }
  223. return RT_EOK;
  224. }
  225. static rt_uint8_t hpm_get_resolution(struct rt_adc_device *device)
  226. {
  227. hpm_rtt_adc *hpm_adc;
  228. RT_ASSERT(device != RT_NULL);
  229. hpm_adc = (hpm_rtt_adc *)device->parent.user_data;
  230. if (hpm_adc->is_adc12) {
  231. return 12;
  232. } else {
  233. return 16;
  234. }
  235. }
  236. static rt_int16_t hpm_get_vref(struct rt_adc_device *device)
  237. {
  238. return -RT_EIO;
  239. }
  240. int rt_hw_adc_init(void)
  241. {
  242. rt_err_t ret = RT_EOK;
  243. for (uint32_t i = 0; i < adc_nums; i++) {
  244. ret = rt_hw_adc_register(&hpm_adc_config_tbl[i].hpm_adc_device,
  245. hpm_adc_config_tbl[i].adc_name,
  246. &hpm_adc_ops,
  247. &hpm_adc_config_tbl[i]);
  248. if (ret != RT_EOK) {
  249. ret = RT_ERROR;
  250. break;
  251. }
  252. }
  253. return ret;
  254. }
  255. INIT_BOARD_EXPORT(rt_hw_adc_init);
  256. #endif /* BSP_USING_ADC */