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