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-10-07 qiyu first version
9 */
10
11 #include <board.h>
12 #ifdef BSP_USING_ADC
13 #include "drv_config.h"
14
15 #include "drv_adc.h"
16 #include "rtdbg.h"
17
18
19 static struct c28x_adc c28x_adc_obj[] =
20 {
21 #ifdef BSP_USING_ADC1
22 ADC1_CONFIG,
23 #endif
24
25 #ifdef BSP_USING_ADC2
26 ADC2_CONFIG,
27 #endif
28
29 #ifdef BSP_USING_ADC3
30 ADC3_CONFIG,
31 #endif
32 };
33
34
c28x_adc_enabled(struct rt_adc_device * device,rt_uint32_t channel,rt_bool_t enabled)35 static rt_err_t c28x_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
36 {
37 volatile struct ADC_REGS *c28x_adc_regs;
38 RT_ASSERT(device != RT_NULL);
39 volatile struct c28x_adc *c28x_adc_handler;
40 c28x_adc_handler = (struct c28x_adc *)device->parent.user_data;
41 c28x_adc_regs = c28x_adc_handler->adc_regs;
42
43 if (enabled)
44 {
45 /*
46 * power up the ADC
47 */
48 EALLOW;
49 c28x_adc_regs->ADCCTL1.bit.ADCPWDNZ = 1;
50 EDIS;
51 /*
52 * delay for 1ms to allow ADC time to power up
53 */
54 DELAY_US(1000);
55 }
56 else
57 {
58 /*
59 * power down the ADC
60 */
61 EALLOW;
62 c28x_adc_regs->ADCCTL1.bit.ADCPWDNZ = 0;
63 EDIS;
64 }
65
66 return RT_EOK;
67 }
68
c28x_adc_get_resolution(struct rt_adc_device * device)69 static rt_uint8_t c28x_adc_get_resolution(struct rt_adc_device *device)
70 {
71 struct c28x_adc *c28x_adc_handler;
72 volatile struct ADC_REGS *c28x_adc_regs;
73 c28x_adc_handler = (struct c28x_adc *)device->parent.user_data;
74 c28x_adc_regs = c28x_adc_handler->adc_regs;
75 RT_ASSERT(device != RT_NULL);
76 switch(c28x_adc_regs->ADCCTL2.bit.RESOLUTION)
77 {
78 case ADC_RESOLUTION_12BIT:
79 return 12;
80 case ADC_RESOLUTION_16BIT:
81 return 16;
82 default:
83 return 0;
84 }
85 }
86
c28x_adc_get_vref(struct rt_adc_device * device)87 static rt_int16_t c28x_adc_get_vref (struct rt_adc_device *device)
88 {
89 /*
90 * TODO
91 * Get Vref
92 */
93 RT_ASSERT(device);
94 return 3300;
95 }
96
c28x_adc_get_value(struct rt_adc_device * device,rt_uint32_t channel,rt_uint32_t * value)97 static rt_err_t c28x_adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
98 {
99 RT_ASSERT(device != RT_NULL);
100 RT_ASSERT(value != RT_NULL);
101
102 struct c28x_adc *c28x_adc_handler = (struct c28x_adc*)device->parent.user_data;
103 volatile struct ADC_REGS *c28x_adc_regs = c28x_adc_handler->adc_regs;
104 volatile struct ADC_RESULT_REGS *c28x_adc_result_regs = c28x_adc_handler->adc_results;
105
106 /*
107 * configure channel
108 * only use SOC0 for now
109 */
110 EALLOW;
111 c28x_adc_regs->ADCSOC0CTL.bit.CHSEL = channel; /* SOC0 will convert pin A0 */
112 EDIS;
113 /*
114 * start conversions immediately via software, ADCA
115 */
116 c28x_adc_regs->ADCSOCFRC1.all = 0x0001; //SOC0
117 /*
118 * wait for ADCA to complete, then acknowledge flag
119 */
120 while(c28x_adc_regs->ADCINTFLG.bit.ADCINT1 == 0);
121 c28x_adc_regs->ADCINTFLGCLR.bit.ADCINT1 = 1;
122
123 /*
124 * store results
125 */
126 *value = (rt_uint32_t)c28x_adc_result_regs->ADCRESULT0;
127
128 return RT_EOK;
129 }
130
131 static const struct rt_adc_ops stm_adc_ops =
132 {
133 .enabled = c28x_adc_enabled,
134 .convert = c28x_adc_get_value,
135 .get_resolution = c28x_adc_get_resolution,
136 .get_vref = c28x_adc_get_vref,
137 };
138
HAL_ADC_Init(volatile struct ADC_REGS * c28x_adc_handler)139 static rt_err_t HAL_ADC_Init(volatile struct ADC_REGS *c28x_adc_handler)
140 {
141 int adc_controller_num = 0;
142 Uint16 acqps;
143
144 EALLOW;
145 /*
146 * write configurations
147 */
148 c28x_adc_handler->ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
149 if(c28x_adc_handler == &AdcaRegs)
150 {
151 adc_controller_num = 0;
152 }else if(c28x_adc_handler == &AdcbRegs)
153 {
154 adc_controller_num = 1;
155 }
156 else if(c28x_adc_handler == &AdccRegs)
157 {
158 adc_controller_num = 2;
159 }
160 else if(c28x_adc_handler == &AdcdRegs)
161 {
162 adc_controller_num = 3;
163 }
164 AdcSetMode(adc_controller_num, ADC_RESOLUTION, ADC_SIGNALMODE_SINGLE);
165 c28x_adc_handler->ADCCTL1.bit.INTPULSEPOS = 1;
166 EDIS;
167
168 /*
169 * determine minimum acquisition window (in SYSCLKS) based on resolution
170 */
171 if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)
172 {
173 acqps = 14; //75ns
174 }
175 else
176 {
177 /*
178 * resolution is 16-bit
179 */
180 acqps = 63; //320ns
181 }
182
183 /*
184 * Select the channels to convert and end of conversion flag
185 */
186 EALLOW;
187 c28x_adc_handler->ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
188 c28x_adc_handler->ADCINTSEL1N2.bit.INT1SEL = 0; //end of SOC0 will set INT1 flag
189 c28x_adc_handler->ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag
190 c28x_adc_handler->ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
191 EDIS;
192 return RT_EOK;
193 }
194
c28x_adc_init(void)195 static int c28x_adc_init(void)
196 {
197 int result = RT_EOK;
198 /*
199 * save adc name
200 */
201 int i = 0;
202 /* ADC init */
203 for (i = 0; i < sizeof(c28x_adc_obj) / sizeof(c28x_adc_obj[0]); i++)
204 {
205 if (HAL_ADC_Init(c28x_adc_obj[i].adc_regs) != RT_EOK)
206 {
207 LOG_E("%s init failed", c28x_adc_obj[i].name);
208 result = -RT_ERROR;
209 }
210 else
211 {
212 /* register ADC device */
213 if (rt_hw_adc_register(&c28x_adc_obj[i].c28x_adc_device, c28x_adc_obj[i].name, &stm_adc_ops, &c28x_adc_obj[i]) == RT_EOK)
214 {
215 LOG_D("%s init success", c28x_adc_obj[i].name);
216 }
217 else
218 {
219 LOG_E("%s register failed", c28x_adc_obj[i].name);
220 result = -RT_ERROR;
221 }
222 }
223 }
224
225 return result;
226 }
227 INIT_BOARD_EXPORT(c28x_adc_init);
228
229 #endif /* BSP_USING_ADC */
230