1#[cfg(not(stm32u5))]
2use pac::adc::vals::{Adcaldif, Boost};
3#[allow(unused)]
4use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel};
5use pac::adccommon::vals::Presc;
6
7use super::{
8 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel,
9};
10use crate::dma::Transfer;
11use crate::time::Hertz;
12use crate::{pac, rcc, Peripheral};
13
14pub const VREF_DEFAULT_MV: u32 = 3300;
16pub const VREF_CALIB_MV: u32 = 3300;
18
19#[cfg(stm32g4)]
21const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
22#[cfg(stm32h7)]
23const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
24#[cfg(stm32u5)]
25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55);
26
27#[cfg(stm32g4)]
28const VREF_CHANNEL: u8 = 18;
29#[cfg(stm32g4)]
30const TEMP_CHANNEL: u8 = 16;
31
32#[cfg(stm32h7)]
33const VREF_CHANNEL: u8 = 19;
34#[cfg(stm32h7)]
35const TEMP_CHANNEL: u8 = 18;
36
37#[cfg(not(stm32u5))]
39const VBAT_CHANNEL: u8 = 17;
40
41#[cfg(stm32u5)]
42const VREF_CHANNEL: u8 = 0;
43#[cfg(stm32u5)]
44const TEMP_CHANNEL: u8 = 19;
45#[cfg(stm32u5)]
46const VBAT_CHANNEL: u8 = 18;
47
48pub struct VrefInt;
51impl<T: Instance> AdcChannel<T> for VrefInt {}
52impl<T: Instance> SealedAdcChannel<T> for VrefInt {
53 fn channel(&self) -> u8 {
54 VREF_CHANNEL
55 }
56}
57
58pub struct Temperature;
60impl<T: Instance> AdcChannel<T> for Temperature {}
61impl<T: Instance> SealedAdcChannel<T> for Temperature {
62 fn channel(&self) -> u8 {
63 TEMP_CHANNEL
64 }
65}
66
67pub struct Vbat;
69impl<T: Instance> AdcChannel<T> for Vbat {}
70impl<T: Instance> SealedAdcChannel<T> for Vbat {
71 fn channel(&self) -> u8 {
72 VBAT_CHANNEL
73 }
74}
75
76#[allow(unused)]
79enum Prescaler {
80 NotDivided,
81 DividedBy2,
82 DividedBy4,
83 DividedBy6,
84 DividedBy8,
85 DividedBy10,
86 DividedBy12,
87 DividedBy16,
88 DividedBy32,
89 DividedBy64,
90 DividedBy128,
91 DividedBy256,
92}
93
94impl Prescaler {
95 fn from_ker_ck(frequency: Hertz) -> Self {
96 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
97 match raw_prescaler {
98 0 => Self::NotDivided,
99 1 => Self::DividedBy2,
100 2..=3 => Self::DividedBy4,
101 4..=5 => Self::DividedBy6,
102 6..=7 => Self::DividedBy8,
103 8..=9 => Self::DividedBy10,
104 10..=11 => Self::DividedBy12,
105 _ => unimplemented!(),
106 }
107 }
108
109 fn divisor(&self) -> u32 {
110 match self {
111 Prescaler::NotDivided => 1,
112 Prescaler::DividedBy2 => 2,
113 Prescaler::DividedBy4 => 4,
114 Prescaler::DividedBy6 => 6,
115 Prescaler::DividedBy8 => 8,
116 Prescaler::DividedBy10 => 10,
117 Prescaler::DividedBy12 => 12,
118 Prescaler::DividedBy16 => 16,
119 Prescaler::DividedBy32 => 32,
120 Prescaler::DividedBy64 => 64,
121 Prescaler::DividedBy128 => 128,
122 Prescaler::DividedBy256 => 256,
123 }
124 }
125
126 fn presc(&self) -> Presc {
127 match self {
128 Prescaler::NotDivided => Presc::DIV1,
129 Prescaler::DividedBy2 => Presc::DIV2,
130 Prescaler::DividedBy4 => Presc::DIV4,
131 Prescaler::DividedBy6 => Presc::DIV6,
132 Prescaler::DividedBy8 => Presc::DIV8,
133 Prescaler::DividedBy10 => Presc::DIV10,
134 Prescaler::DividedBy12 => Presc::DIV12,
135 Prescaler::DividedBy16 => Presc::DIV16,
136 Prescaler::DividedBy32 => Presc::DIV32,
137 Prescaler::DividedBy64 => Presc::DIV64,
138 Prescaler::DividedBy128 => Presc::DIV128,
139 Prescaler::DividedBy256 => Presc::DIV256,
140 }
141 }
142}
143
144pub enum Averaging {
146 Disabled,
147 Samples2,
148 Samples4,
149 Samples8,
150 Samples16,
151 Samples32,
152 Samples64,
153 Samples128,
154 Samples256,
155 Samples512,
156 Samples1024,
157}
158
159impl<'d, T: Instance> Adc<'d, T> {
160 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
162 embassy_hal_internal::into_ref!(adc);
163 rcc::enable_and_reset::<T>();
164
165 let prescaler = Prescaler::from_ker_ck(T::frequency());
166
167 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
168
169 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
170 info!("ADC frequency set to {} Hz", frequency.0);
171
172 if frequency > MAX_ADC_CLK_FREQ {
173 panic!("Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 );
174 }
175
176 #[cfg(stm32h7)]
177 {
178 let boost = if frequency < Hertz::khz(6_250) {
179 Boost::LT6_25
180 } else if frequency < Hertz::khz(12_500) {
181 Boost::LT12_5
182 } else if frequency < Hertz::mhz(25) {
183 Boost::LT25
184 } else {
185 Boost::LT50
186 };
187 T::regs().cr().modify(|w| w.set_boost(boost));
188 }
189 let mut s = Self {
190 adc,
191 sample_time: SampleTime::from_bits(0),
192 };
193 s.power_up();
194 s.configure_differential_inputs();
195
196 s.calibrate();
197 blocking_delay_us(1);
198
199 s.enable();
200 s.configure();
201
202 s
203 }
204
205 fn power_up(&mut self) {
206 T::regs().cr().modify(|reg| {
207 reg.set_deeppwd(false);
208 reg.set_advregen(true);
209 });
210
211 blocking_delay_us(10);
212 }
213
214 fn configure_differential_inputs(&mut self) {
215 T::regs().difsel().modify(|w| {
216 for n in 0..20 {
217 w.set_difsel(n, Difsel::SINGLE_ENDED);
218 }
219 });
220 }
221
222 fn calibrate(&mut self) {
223 T::regs().cr().modify(|w| {
224 #[cfg(not(adc_u5))]
225 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
226 w.set_adcallin(true);
227 });
228
229 T::regs().cr().modify(|w| w.set_adcal(true));
230
231 while T::regs().cr().read().adcal() {}
232 }
233
234 fn enable(&mut self) {
235 T::regs().isr().write(|w| w.set_adrdy(true));
236 T::regs().cr().modify(|w| w.set_aden(true));
237 while !T::regs().isr().read().adrdy() {}
238 T::regs().isr().write(|w| w.set_adrdy(true));
239 }
240
241 fn configure(&mut self) {
242 T::regs().cfgr().modify(|w| {
244 w.set_cont(false);
245 w.set_exten(Exten::DISABLED);
246 });
247 }
248
249 pub fn enable_vrefint(&self) -> VrefInt {
251 T::common_regs().ccr().modify(|reg| {
252 reg.set_vrefen(true);
253 });
254
255 VrefInt {}
256 }
257
258 pub fn enable_temperature(&self) -> Temperature {
260 T::common_regs().ccr().modify(|reg| {
261 reg.set_vsenseen(true);
262 });
263
264 Temperature {}
265 }
266
267 pub fn enable_vbat(&self) -> Vbat {
269 T::common_regs().ccr().modify(|reg| {
270 reg.set_vbaten(true);
271 });
272
273 Vbat {}
274 }
275
276 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
278 self.sample_time = sample_time;
279 }
280
281 pub fn sample_time(&self) -> SampleTime {
283 self.sample_time
284 }
285
286 pub fn set_resolution(&mut self, resolution: Resolution) {
288 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
289 }
290
291 pub fn set_averaging(&mut self, averaging: Averaging) {
293 let (enable, samples, right_shift) = match averaging {
294 Averaging::Disabled => (false, 0, 0),
295 Averaging::Samples2 => (true, 1, 1),
296 Averaging::Samples4 => (true, 3, 2),
297 Averaging::Samples8 => (true, 7, 3),
298 Averaging::Samples16 => (true, 15, 4),
299 Averaging::Samples32 => (true, 31, 5),
300 Averaging::Samples64 => (true, 63, 6),
301 Averaging::Samples128 => (true, 127, 7),
302 Averaging::Samples256 => (true, 255, 8),
303 Averaging::Samples512 => (true, 511, 9),
304 Averaging::Samples1024 => (true, 1023, 10),
305 };
306
307 T::regs().cfgr2().modify(|reg| {
308 reg.set_rovse(enable);
309 reg.set_osvr(samples);
310 reg.set_ovss(right_shift);
311 })
312 }
313
314 fn convert(&mut self) -> u16 {
316 T::regs().isr().modify(|reg| {
317 reg.set_eos(true);
318 reg.set_eoc(true);
319 });
320
321 T::regs().cr().modify(|reg| {
323 reg.set_adstart(true);
324 });
325
326 while !T::regs().isr().read().eos() {
327 }
329
330 T::regs().dr().read().0 as u16
331 }
332
333 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
335 self.read_channel(channel)
336 }
337
338 pub async fn read(
364 &mut self,
365 rx_dma: &mut impl RxDma<T>,
366 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
367 readings: &mut [u16],
368 ) {
369 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
370 assert!(
371 sequence.len() == readings.len(),
372 "Sequence length must be equal to readings length"
373 );
374 assert!(
375 sequence.len() <= 16,
376 "Asynchronous read sequence cannot be more than 16 in length"
377 );
378
379 Self::cancel_conversions();
381
382 T::regs().sqr1().modify(|w| {
384 w.set_l(sequence.len() as u8 - 1);
385 });
386
387 for (i, (channel, sample_time)) in sequence.enumerate() {
389 Self::configure_channel(channel, sample_time);
390 match i {
391 0..=3 => {
392 T::regs().sqr1().modify(|w| {
393 w.set_sq(i, channel.channel());
394 });
395 }
396 4..=8 => {
397 T::regs().sqr2().modify(|w| {
398 w.set_sq(i - 4, channel.channel());
399 });
400 }
401 9..=13 => {
402 T::regs().sqr3().modify(|w| {
403 w.set_sq(i - 9, channel.channel());
404 });
405 }
406 14..=15 => {
407 T::regs().sqr4().modify(|w| {
408 w.set_sq(i - 14, channel.channel());
409 });
410 }
411 _ => unreachable!(),
412 }
413 }
414
415 T::regs().isr().modify(|reg| {
419 reg.set_ovr(true);
420 });
421 T::regs().cfgr().modify(|reg| {
422 reg.set_cont(true);
423 reg.set_dmngt(Dmngt::DMA_ONE_SHOT);
424 });
425
426 let request = rx_dma.request();
427 let transfer = unsafe {
428 Transfer::new_read(
429 rx_dma,
430 request,
431 T::regs().dr().as_ptr() as *mut u16,
432 readings,
433 Default::default(),
434 )
435 };
436
437 T::regs().cr().modify(|reg| {
439 reg.set_adstart(true);
440 });
441
442 transfer.await;
444
445 Self::cancel_conversions();
447
448 T::regs().cfgr().modify(|reg| {
450 reg.set_cont(false);
451 reg.set_dmngt(Dmngt::from_bits(0));
452 });
453 }
454
455 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
456 channel.setup();
457
458 let channel = channel.channel();
459
460 Self::set_channel_sample_time(channel, sample_time);
461
462 #[cfg(any(stm32h7, stm32u5))]
463 {
464 T::regs().cfgr2().modify(|w| w.set_lshift(0));
465 T::regs()
466 .pcsel()
467 .modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
468 }
469 }
470
471 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
472 Self::configure_channel(channel, self.sample_time);
473
474 T::regs().sqr1().modify(|reg| {
475 reg.set_sq(0, channel.channel());
476 reg.set_l(0);
477 });
478
479 self.convert()
480 }
481
482 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
483 let sample_time = sample_time.into();
484 if ch <= 9 {
485 T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time));
486 } else {
487 T::regs().smpr(1).modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
488 }
489 }
490
491 fn cancel_conversions() {
492 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
493 T::regs().cr().modify(|reg| {
494 reg.set_adstp(Adstp::STOP);
495 });
496 while T::regs().cr().read().adstart() {}
497 }
498 }
499}