drv_adc.c 7.6 KB

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