aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/adc/v3.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/adc/v3.rs')
-rw-r--r--embassy-stm32/src/adc/v3.rs874
1 files changed, 402 insertions, 472 deletions
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 16063ce4d..9cc44aa9a 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -1,19 +1,19 @@
1use cfg_if::cfg_if; 1use cfg_if::cfg_if;
2#[cfg(adc_g0)] 2#[cfg(adc_g0)]
3use heapless::Vec; 3use heapless::Vec;
4use pac::adc::vals::Dmacfg;
5#[cfg(adc_g0)] 4#[cfg(adc_g0)]
6use pac::adc::vals::{Ckmode, Smpsel}; 5use pac::adc::vals::Ckmode;
6use pac::adc::vals::Dmacfg;
7#[cfg(adc_v3)] 7#[cfg(adc_v3)]
8use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs}; 8use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs};
9#[cfg(adc_g0)] 9#[cfg(adc_g0)]
10pub use pac::adc::vals::{Ovsr, Ovss, Presc}; 10pub use pac::adc::vals::{Ovsr, Ovss, Presc};
11 11
12use super::{ 12#[allow(unused_imports)]
13 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, 13use super::SealedAdcChannel;
14}; 14use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us};
15use crate::dma::Transfer; 15use crate::adc::ConversionMode;
16use crate::{pac, rcc, Peri}; 16use crate::{Peri, pac, rcc};
17 17
18/// Default VREF voltage used for sample conversion to millivolts. 18/// Default VREF voltage used for sample conversion to millivolts.
19pub const VREF_DEFAULT_MV: u32 = 3300; 19pub const VREF_DEFAULT_MV: u32 = 3300;
@@ -25,70 +25,64 @@ pub const VREF_CALIB_MV: u32 = 3000;
25// TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable 25// TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable
26const SAMPLE_TIMES_CAPACITY: usize = 2; 26const SAMPLE_TIMES_CAPACITY: usize = 2;
27 27
28pub struct VrefInt; 28#[cfg(adc_g0)]
29impl<T: Instance> AdcChannel<T> for VrefInt {} 29impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
30impl<T: Instance> SealedAdcChannel<T> for VrefInt { 30 const CHANNEL: u8 = 13;
31 fn channel(&self) -> u8 { 31}
32 cfg_if! { 32#[cfg(any(adc_h5, adc_h7rs))]
33 if #[cfg(adc_g0)] { 33impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
34 let val = 13; 34 const CHANNEL: u8 = 17;
35 } else if #[cfg(any(adc_h5, adc_h7rs))] { 35}
36 let val = 17; 36#[cfg(adc_u0)]
37 } else if #[cfg(adc_u0)] { 37impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
38 let val = 12; 38 const CHANNEL: u8 = 12;
39 } else { 39}
40 let val = 0; 40#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))]
41 } 41impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
42 } 42 const CHANNEL: u8 = 0;
43 val
44 }
45} 43}
46 44
47pub struct Temperature; 45#[cfg(adc_g0)]
48impl<T: Instance> AdcChannel<T> for Temperature {} 46impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
49impl<T: Instance> SealedAdcChannel<T> for Temperature { 47 const CHANNEL: u8 = 12;
50 fn channel(&self) -> u8 { 48}
51 cfg_if! { 49#[cfg(any(adc_h5, adc_h7rs))]
52 if #[cfg(adc_g0)] { 50impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
53 let val = 12; 51 const CHANNEL: u8 = 16;
54 } else if #[cfg(any(adc_h5, adc_h7rs))] { 52}
55 let val = 16; 53#[cfg(adc_u0)]
56 } else if #[cfg(adc_u0)] { 54impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
57 let val = 11; 55 const CHANNEL: u8 = 11;
58 } else { 56}
59 let val = 17; 57#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))]
60 } 58impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
61 } 59 const CHANNEL: u8 = 17;
62 val
63 }
64} 60}
65 61
66pub struct Vbat; 62#[cfg(adc_g0)]
67impl<T: Instance> AdcChannel<T> for Vbat {} 63impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
68impl<T: Instance> SealedAdcChannel<T> for Vbat { 64 const CHANNEL: u8 = 14;
69 fn channel(&self) -> u8 { 65}
70 cfg_if! { 66#[cfg(any(adc_h5, adc_h7rs))]
71 if #[cfg(adc_g0)] { 67impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
72 let val = 14; 68 const CHANNEL: u8 = 16;
73 } else if #[cfg(any(adc_h5, adc_h7rs))] { 69}
74 let val = 2; 70#[cfg(adc_u0)]
75 } else if #[cfg(any(adc_h5, adc_h7rs))] { 71impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
76 let val = 13; 72 const CHANNEL: u8 = 13;
77 } else { 73}
78 let val = 18; 74#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))]
79 } 75impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
80 } 76 const CHANNEL: u8 = 18;
81 val
82 }
83} 77}
84 78
85cfg_if! { 79cfg_if! {
86 if #[cfg(any(adc_h5, adc_h7rs))] { 80 if #[cfg(any(adc_h5, adc_h7rs))] {
87 pub struct VddCore; 81 pub struct VddCore;
88 impl<T: Instance> AdcChannel<T> for VddCore {} 82 impl<T: Instance> super::AdcChannel<T> for VddCore {}
89 impl<T: Instance> super::SealedAdcChannel<T> for VddCore { 83 impl<T: Instance> super::SealedAdcChannel<T> for VddCore {
90 fn channel(&self) -> u8 { 84 fn channel(&self) -> u8 {
91 6 85 17
92 } 86 }
93 } 87 }
94 } 88 }
@@ -97,7 +91,7 @@ cfg_if! {
97cfg_if! { 91cfg_if! {
98 if #[cfg(adc_u0)] { 92 if #[cfg(adc_u0)] {
99 pub struct DacOut; 93 pub struct DacOut;
100 impl<T: Instance> AdcChannel<T> for DacOut {} 94 impl<T: Instance> super::AdcChannel<T> for DacOut {}
101 impl<T: Instance> super::SealedAdcChannel<T> for DacOut { 95 impl<T: Instance> super::SealedAdcChannel<T> for DacOut {
102 fn channel(&self) -> u8 { 96 fn channel(&self) -> u8 {
103 19 97 19
@@ -106,21 +100,6 @@ cfg_if! {
106 } 100 }
107} 101}
108 102
109/// Number of samples used for averaging.
110#[derive(Copy, Clone, Debug)]
111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
112pub enum Averaging {
113 Disabled,
114 Samples2,
115 Samples4,
116 Samples8,
117 Samples16,
118 Samples32,
119 Samples64,
120 Samples128,
121 Samples256,
122}
123
124cfg_if! { if #[cfg(adc_g0)] { 103cfg_if! { if #[cfg(adc_g0)] {
125 104
126/// Synchronous PCLK prescaler 105/// Synchronous PCLK prescaler
@@ -141,295 +120,150 @@ pub enum Clock {
141 120
142}} 121}}
143 122
144impl<'d, T: Instance> Adc<'d, T> { 123#[cfg(adc_u0)]
145 /// Enable the voltage regulator 124type Ovss = u8;
146 fn init_regulator() { 125#[cfg(adc_u0)]
147 rcc::enable_and_reset::<T>(); 126type Ovsr = u8;
148 T::regs().cr().modify(|reg| { 127#[cfg(adc_v3)]
149 #[cfg(not(any(adc_g0, adc_u0)))] 128type Ovss = OversamplingShift;
150 reg.set_deeppwd(false); 129#[cfg(adc_v3)]
151 reg.set_advregen(true); 130type Ovsr = OversamplingRatio;
152 }); 131
153 132/// Adc configuration
154 // If this is false then each ADC_CHSELR bit enables an input channel. 133#[derive(Default)]
155 // This is the reset value, so has no effect. 134pub struct AdcConfig {
156 #[cfg(any(adc_g0, adc_u0))] 135 #[cfg(any(adc_u0, adc_g0, adc_v3))]
157 T::regs().cfgr1().modify(|reg| { 136 pub oversampling_shift: Option<Ovss>,
158 reg.set_chselrmod(false); 137 #[cfg(any(adc_u0, adc_g0, adc_v3))]
159 }); 138 pub oversampling_ratio: Option<Ovsr>,
160 139 #[cfg(any(adc_u0, adc_g0))]
161 blocking_delay_us(20); 140 pub oversampling_enable: Option<bool>,
162 } 141 #[cfg(adc_v3)]
163 142 pub oversampling_mode: Option<(Rovsm, Trovs, bool)>,
164 /// Calibrate to remove conversion offset
165 fn init_calibrate() {
166 T::regs().cr().modify(|reg| {
167 reg.set_adcal(true);
168 });
169
170 while T::regs().cr().read().adcal() {
171 // spin
172 }
173
174 blocking_delay_us(1);
175 }
176
177 /// Initialize the ADC leaving any analog clock at reset value.
178 /// For G0 and WL, this is the async clock without prescaler.
179 pub fn new(adc: Peri<'d, T>) -> Self {
180 Self::init_regulator();
181 Self::init_calibrate();
182 Self {
183 adc,
184 sample_time: SampleTime::from_bits(0),
185 }
186 }
187
188 #[cfg(adc_g0)] 143 #[cfg(adc_g0)]
189 /// Initialize ADC with explicit clock for the analog ADC 144 pub clock: Option<Clock>,
190 pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self { 145 pub resolution: Option<Resolution>,
191 Self::init_regulator(); 146 pub averaging: Option<Averaging>,
192 147}
193 #[cfg(any(stm32wl5x))]
194 {
195 // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual
196 let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0;
197 match clock {
198 Clock::Async { div: _ } => {
199 assert!(async_clock_available);
200 }
201 Clock::Sync { div: _ } => {
202 if async_clock_available {
203 warn!("Not using configured ADC clock");
204 }
205 }
206 }
207 }
208 match clock {
209 Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div)),
210 Clock::Sync { div } => T::regs().cfgr2().modify(|reg| {
211 reg.set_ckmode(match div {
212 CkModePclk::DIV1 => Ckmode::PCLK,
213 CkModePclk::DIV2 => Ckmode::PCLK_DIV2,
214 CkModePclk::DIV4 => Ckmode::PCLK_DIV4,
215 })
216 }),
217 }
218
219 Self::init_calibrate();
220 148
221 Self { 149impl super::AdcRegs for crate::pac::adc::Adc {
222 adc, 150 fn data(&self) -> *mut u16 {
223 sample_time: SampleTime::from_bits(0), 151 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
224 }
225 } 152 }
226 153
227 // Enable ADC only when it is not already running. 154 // Enable ADC only when it is not already running.
228 fn enable(&mut self) { 155 fn enable(&self) {
229 // Make sure bits are off 156 // Make sure bits are off
230 while T::regs().cr().read().addis() { 157 while self.cr().read().addis() {
231 // spin 158 // spin
232 } 159 }
233 160
234 if !T::regs().cr().read().aden() { 161 if !self.cr().read().aden() {
235 // Enable ADC 162 // Enable ADC
236 T::regs().isr().modify(|reg| { 163 self.isr().modify(|reg| {
237 reg.set_adrdy(true); 164 reg.set_adrdy(true);
238 }); 165 });
239 T::regs().cr().modify(|reg| { 166 self.cr().modify(|reg| {
240 reg.set_aden(true); 167 reg.set_aden(true);
241 }); 168 });
242 169
243 while !T::regs().isr().read().adrdy() { 170 while !self.isr().read().adrdy() {
244 // spin 171 // spin
245 } 172 }
246 } 173 }
247 } 174 }
248 175
249 pub fn enable_vrefint(&self) -> VrefInt { 176 fn start(&self) {
177 self.cr().modify(|reg| {
178 reg.set_adstart(true);
179 });
180 }
181
182 fn stop(&self) {
183 // Ensure conversions are finished.
184 if self.cr().read().adstart() && !self.cr().read().addis() {
185 self.cr().modify(|reg| {
186 reg.set_adstp(true);
187 });
188 while self.cr().read().adstart() {}
189 }
190
191 // Reset configuration.
250 #[cfg(not(any(adc_g0, adc_u0)))] 192 #[cfg(not(any(adc_g0, adc_u0)))]
251 T::common_regs().ccr().modify(|reg| { 193 self.cfgr().modify(|reg| {
252 reg.set_vrefen(true); 194 reg.set_cont(false);
195 reg.set_dmaen(false);
253 }); 196 });
254 #[cfg(any(adc_g0, adc_u0))] 197 #[cfg(any(adc_g0, adc_u0))]
255 T::regs().ccr().modify(|reg| { 198 self.cfgr1().modify(|reg| {
256 reg.set_vrefen(true); 199 reg.set_cont(false);
200 reg.set_dmaen(false);
257 }); 201 });
202 }
258 203
259 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us 204 /// Perform a single conversion.
260 // to stabilize the internal voltage reference. 205 fn convert(&self) {
261 blocking_delay_us(15); 206 // Some models are affected by an erratum:
207 // If we perform conversions slower than 1 kHz, the first read ADC value can be
208 // corrupted, so we discard it and measure again.
209 //
210 // STM32L471xx: Section 2.7.3
211 // STM32G4: Section 2.7.3
212 #[cfg(any(rcc_l4, rcc_g4))]
213 let len = 2;
262 214
263 VrefInt {} 215 #[cfg(not(any(rcc_l4, rcc_g4)))]
264 } 216 let len = 1;
265 217
266 pub fn enable_temperature(&self) -> Temperature { 218 for _ in 0..len {
267 cfg_if! { 219 self.isr().modify(|reg| {
268 if #[cfg(any(adc_g0, adc_u0))] { 220 reg.set_eos(true);
269 T::regs().ccr().modify(|reg| { 221 reg.set_eoc(true);
270 reg.set_tsen(true); 222 });
271 });
272 } else if #[cfg(any(adc_h5, adc_h7rs))] {
273 T::common_regs().ccr().modify(|reg| {
274 reg.set_tsen(true);
275 });
276 } else {
277 T::common_regs().ccr().modify(|reg| {
278 reg.set_ch17sel(true);
279 });
280 }
281 }
282 223
283 Temperature {} 224 // Start conversion
284 } 225 self.cr().modify(|reg| {
226 reg.set_adstart(true);
227 });
285 228
286 pub fn enable_vbat(&self) -> Vbat { 229 while !self.isr().read().eos() {
287 cfg_if! { 230 // spin
288 if #[cfg(any(adc_g0, adc_u0))] {
289 T::regs().ccr().modify(|reg| {
290 reg.set_vbaten(true);
291 });
292 } else if #[cfg(any(adc_h5, adc_h7rs))] {
293 T::common_regs().ccr().modify(|reg| {
294 reg.set_vbaten(true);
295 });
296 } else {
297 T::common_regs().ccr().modify(|reg| {
298 reg.set_ch18sel(true);
299 });
300 } 231 }
301 } 232 }
302
303 Vbat {}
304 } 233 }
305 234
306 /// Set the ADC sample time. 235 fn configure_dma(&self, conversion_mode: ConversionMode) {
307 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 236 // Set continuous mode with oneshot dma.
308 self.sample_time = sample_time; 237 // Clear overrun flag before starting transfer.
309 } 238 self.isr().modify(|reg| {
310 239 reg.set_ovr(true);
311 /// Get the ADC sample time. 240 });
312 pub fn sample_time(&self) -> SampleTime {
313 self.sample_time
314 }
315 241
316 /// Set the ADC resolution.
317 pub fn set_resolution(&mut self, resolution: Resolution) {
318 #[cfg(not(any(adc_g0, adc_u0)))] 242 #[cfg(not(any(adc_g0, adc_u0)))]
319 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); 243 let regs = self.cfgr();
320 #[cfg(any(adc_g0, adc_u0))]
321 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
322 }
323 244
324 pub fn set_averaging(&mut self, averaging: Averaging) { 245 #[cfg(any(adc_g0, adc_u0))]
325 let (enable, samples, right_shift) = match averaging { 246 let regs = self.cfgr1();
326 Averaging::Disabled => (false, 0, 0),
327 Averaging::Samples2 => (true, 0, 1),
328 Averaging::Samples4 => (true, 1, 2),
329 Averaging::Samples8 => (true, 2, 3),
330 Averaging::Samples16 => (true, 3, 4),
331 Averaging::Samples32 => (true, 4, 5),
332 Averaging::Samples64 => (true, 5, 6),
333 Averaging::Samples128 => (true, 6, 7),
334 Averaging::Samples256 => (true, 7, 8),
335 };
336 T::regs().cfgr2().modify(|reg| {
337 #[cfg(not(any(adc_g0, adc_u0)))]
338 reg.set_rovse(enable);
339 #[cfg(any(adc_g0, adc_u0))]
340 reg.set_ovse(enable);
341 #[cfg(any(adc_h5, adc_h7rs))]
342 reg.set_ovsr(samples.into());
343 #[cfg(not(any(adc_h5, adc_h7rs)))]
344 reg.set_ovsr(samples.into());
345 reg.set_ovss(right_shift.into());
346 })
347 }
348 /*
349 /// Convert a raw sample from the `Temperature` to deg C
350 pub fn to_degrees_centigrade(sample: u16) -> f32 {
351 (130.0 - 30.0) / (VtempCal130::get().read() as f32 - VtempCal30::get().read() as f32)
352 * (sample as f32 - VtempCal30::get().read() as f32)
353 + 30.0
354 }
355 */
356
357 /// Perform a single conversion.
358 fn convert(&mut self) -> u16 {
359 T::regs().isr().modify(|reg| {
360 reg.set_eos(true);
361 reg.set_eoc(true);
362 });
363 247
364 // Start conversion 248 regs.modify(|reg| {
365 T::regs().cr().modify(|reg| { 249 reg.set_discen(false);
366 reg.set_adstart(true); 250 reg.set_cont(true);
251 reg.set_dmacfg(match conversion_mode {
252 ConversionMode::Singular => Dmacfg::ONE_SHOT,
253 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
254 ConversionMode::Repeated(_) => Dmacfg::CIRCULAR,
255 });
256 reg.set_dmaen(true);
367 }); 257 });
368
369 while !T::regs().isr().read().eos() {
370 // spin
371 }
372
373 T::regs().dr().read().0 as u16
374 } 258 }
375 259
376 /// Read an ADC channel. 260 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
377 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 261 #[cfg(adc_h5)]
378 self.read_channel(channel) 262 self.cr().modify(|w| w.set_aden(false));
379 }
380
381 /// Read one or multiple ADC channels using DMA.
382 ///
383 /// `readings` must have a length that is a multiple of the length of the
384 /// `sequence` iterator.
385 ///
386 /// Note: The order of values in `readings` is defined by the pin ADC
387 /// channel number and not the pin order in `sequence`.
388 ///
389 /// Example
390 /// ```rust,ignore
391 /// use embassy_stm32::adc::{Adc, AdcChannel}
392 ///
393 /// let mut adc = Adc::new(p.ADC1);
394 /// let mut adc_pin0 = p.PA0.degrade_adc();
395 /// let mut adc_pin1 = p.PA1.degrade_adc();
396 /// let mut measurements = [0u16; 2];
397 ///
398 /// adc.read(
399 /// p.DMA1_CH2.reborrow(),
400 /// [
401 /// (&mut *adc_pin0, SampleTime::CYCLES160_5),
402 /// (&mut *adc_pin1, SampleTime::CYCLES160_5),
403 /// ]
404 /// .into_iter(),
405 /// &mut measurements,
406 /// )
407 /// .await;
408 /// defmt::info!("measurements: {}", measurements);
409 /// ```
410 pub async fn read(
411 &mut self,
412 rx_dma: Peri<'_, impl RxDma<T>>,
413 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
414 readings: &mut [u16],
415 ) {
416 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
417 assert!(
418 readings.len() % sequence.len() == 0,
419 "Readings length must be a multiple of sequence length"
420 );
421 assert!(
422 sequence.len() <= 16,
423 "Asynchronous read sequence cannot be more than 16 in length"
424 );
425
426 // Ensure no conversions are ongoing and ADC is enabled.
427 Self::cancel_conversions();
428 self.enable();
429 263
430 // Set sequence length 264 // Set sequence length
431 #[cfg(not(any(adc_g0, adc_u0)))] 265 #[cfg(not(any(adc_g0, adc_u0)))]
432 T::regs().sqr1().modify(|w| { 266 self.sqr1().modify(|w| {
433 w.set_l(sequence.len() as u8 - 1); 267 w.set_l(sequence.len() as u8 - 1);
434 }); 268 });
435 269
@@ -437,12 +271,12 @@ impl<'d, T: Instance> Adc<'d, T> {
437 { 271 {
438 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new(); 272 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new();
439 273
440 T::regs().chselr().write(|chselr| { 274 self.chselr().write(|chselr| {
441 T::regs().smpr().write(|smpr| { 275 self.smpr().write(|smpr| {
442 for (channel, sample_time) in sequence { 276 for ((channel, _), sample_time) in sequence {
443 chselr.set_chsel(channel.channel.into(), true); 277 chselr.set_chsel(channel.into(), true);
444 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) { 278 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) {
445 smpr.set_smpsel(channel.channel.into(), (i as u8).into()); 279 smpr.set_smpsel(channel.into(), (i as u8).into());
446 } else { 280 } else {
447 smpr.set_sample_time(sample_times.len(), sample_time); 281 smpr.set_sample_time(sample_times.len(), sample_time);
448 if let Err(_) = sample_times.push(sample_time) { 282 if let Err(_) = sample_times.push(sample_time) {
@@ -461,225 +295,321 @@ impl<'d, T: Instance> Adc<'d, T> {
461 #[cfg(adc_u0)] 295 #[cfg(adc_u0)]
462 let mut channel_mask = 0; 296 let mut channel_mask = 0;
463 297
298 #[cfg(adc_h5)]
299 let mut difsel = 0u32;
300
464 // Configure channels and ranks 301 // Configure channels and ranks
465 for (_i, (channel, sample_time)) in sequence.enumerate() { 302 for (_i, ((channel, _is_differential), sample_time)) in sequence.enumerate() {
466 Self::configure_channel(channel, sample_time); 303 // RM0492, RM0481, etc.
304 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
305 #[cfg(any(adc_h5, adc_h7rs))]
306 if channel == 0 {
307 self.or().modify(|reg| reg.set_op0(true));
308 }
309
310 // Configure channel
311 cfg_if! {
312 if #[cfg(adc_u0)] {
313 // On G0 and U6 all channels use the same sampling time.
314 self.smpr().modify(|reg| reg.set_smp1(sample_time.into()));
315 } else if #[cfg(any(adc_h5, adc_h7rs))] {
316 match channel {
317 0..=9 => self.smpr1().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
318 _ => self.smpr2().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
319 }
320 } else {
321 let sample_time = sample_time.into();
322 self
323 .smpr(channel as usize / 10)
324 .modify(|reg| reg.set_smp(channel as usize % 10, sample_time));
325 }
326 }
327
328 #[cfg(stm32h7)]
329 {
330 use crate::pac::adc::vals::Pcsel;
331
332 self.cfgr2().modify(|w| w.set_lshift(0));
333 self.pcsel()
334 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
335 }
467 336
468 // Each channel is sampled according to sequence 337 // Each channel is sampled according to sequence
469 #[cfg(not(any(adc_g0, adc_u0)))] 338 #[cfg(not(any(adc_g0, adc_u0)))]
470 match _i { 339 match _i {
471 0..=3 => { 340 0..=3 => {
472 T::regs().sqr1().modify(|w| { 341 self.sqr1().modify(|w| {
473 w.set_sq(_i, channel.channel()); 342 w.set_sq(_i, channel);
474 }); 343 });
475 } 344 }
476 4..=8 => { 345 4..=8 => {
477 T::regs().sqr2().modify(|w| { 346 self.sqr2().modify(|w| {
478 w.set_sq(_i - 4, channel.channel()); 347 w.set_sq(_i - 4, channel);
479 }); 348 });
480 } 349 }
481 9..=13 => { 350 9..=13 => {
482 T::regs().sqr3().modify(|w| { 351 self.sqr3().modify(|w| {
483 w.set_sq(_i - 9, channel.channel()); 352 w.set_sq(_i - 9, channel);
484 }); 353 });
485 } 354 }
486 14..=15 => { 355 14..=15 => {
487 T::regs().sqr4().modify(|w| { 356 self.sqr4().modify(|w| {
488 w.set_sq(_i - 14, channel.channel()); 357 w.set_sq(_i - 14, channel);
489 }); 358 });
490 } 359 }
491 _ => unreachable!(), 360 _ => unreachable!(),
492 } 361 }
493 362
363 #[cfg(adc_h5)]
364 {
365 difsel |= (_is_differential as u32) << channel;
366 }
367
494 #[cfg(adc_u0)] 368 #[cfg(adc_u0)]
495 { 369 {
496 channel_mask |= 1 << channel.channel(); 370 channel_mask |= 1 << channel;
497 } 371 }
498 } 372 }
499 373
374 #[cfg(adc_h5)]
375 self.difsel().write(|w| w.set_difsel(difsel));
376
500 // On G0 and U0 enabled channels are sampled from 0 to last channel. 377 // On G0 and U0 enabled channels are sampled from 0 to last channel.
501 // It is possible to add up to 8 sequences if CHSELRMOD = 1. 378 // It is possible to add up to 8 sequences if CHSELRMOD = 1.
502 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used. 379 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used.
503 #[cfg(adc_u0)] 380 #[cfg(adc_u0)]
504 T::regs().chselr().modify(|reg| { 381 self.chselr().modify(|reg| {
505 reg.set_chsel(channel_mask); 382 reg.set_chsel(channel_mask);
506 }); 383 });
507 } 384 }
508 // Set continuous mode with oneshot dma. 385 }
509 // Clear overrun flag before starting transfer. 386}
510 T::regs().isr().modify(|reg| {
511 reg.set_ovr(true);
512 });
513 387
514 #[cfg(not(any(adc_g0, adc_u0)))] 388impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> {
515 T::regs().cfgr().modify(|reg| { 389 /// Enable the voltage regulator
516 reg.set_discen(false); 390 fn init_regulator() {
517 reg.set_cont(true); 391 rcc::enable_and_reset::<T>();
518 reg.set_dmacfg(Dmacfg::ONE_SHOT); 392 T::regs().cr().modify(|reg| {
519 reg.set_dmaen(true); 393 #[cfg(not(any(adc_g0, adc_u0)))]
394 reg.set_deeppwd(false);
395 reg.set_advregen(true);
520 }); 396 });
397
398 // If this is false then each ADC_CHSELR bit enables an input channel.
399 // This is the reset value, so has no effect.
521 #[cfg(any(adc_g0, adc_u0))] 400 #[cfg(any(adc_g0, adc_u0))]
522 T::regs().cfgr1().modify(|reg| { 401 T::regs().cfgr1().modify(|reg| {
523 reg.set_discen(false); 402 reg.set_chselrmod(false);
524 reg.set_cont(true);
525 reg.set_dmacfg(Dmacfg::ONE_SHOT);
526 reg.set_dmaen(true);
527 }); 403 });
528 404
529 let request = rx_dma.request(); 405 blocking_delay_us(20);
530 let transfer = unsafe { 406 }
531 Transfer::new_read(
532 rx_dma,
533 request,
534 T::regs().dr().as_ptr() as *mut u16,
535 readings,
536 Default::default(),
537 )
538 };
539 407
540 // Start conversion 408 /// Calibrate to remove conversion offset
409 fn init_calibrate() {
541 T::regs().cr().modify(|reg| { 410 T::regs().cr().modify(|reg| {
542 reg.set_adstart(true); 411 reg.set_adcal(true);
543 }); 412 });
544 413
545 // Wait for conversion sequence to finish. 414 while T::regs().cr().read().adcal() {
546 transfer.await; 415 // spin
547 416 }
548 // Ensure conversions are finished.
549 Self::cancel_conversions();
550 417
551 // Reset configuration. 418 blocking_delay_us(1);
552 #[cfg(not(any(adc_g0, adc_u0)))]
553 T::regs().cfgr().modify(|reg| {
554 reg.set_cont(false);
555 });
556 #[cfg(any(adc_g0, adc_u0))]
557 T::regs().cfgr1().modify(|reg| {
558 reg.set_cont(false);
559 });
560 } 419 }
561 420
562 #[cfg(not(adc_g0))] 421 /// Initialize the ADC leaving any analog clock at reset value.
563 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) { 422 /// For G0 and WL, this is the async clock without prescaler.
564 // RM0492, RM0481, etc. 423 pub fn new(adc: Peri<'d, T>) -> Self {
565 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected." 424 Self::init_regulator();
566 #[cfg(any(adc_h5, adc_h7rs))] 425 Self::init_calibrate();
567 if channel.channel() == 0 { 426 Self { adc }
568 T::regs().or().modify(|reg| reg.set_op0(true));
569 }
570
571 // Configure channel
572 Self::set_channel_sample_time(channel.channel(), sample_time);
573 } 427 }
574 428
575 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 429 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
576 self.enable();
577 #[cfg(not(adc_g0))] 430 #[cfg(not(adc_g0))]
578 Self::configure_channel(channel, self.sample_time); 431 let s = Self::new(adc);
432
579 #[cfg(adc_g0)] 433 #[cfg(adc_g0)]
580 T::regs().smpr().write(|reg| { 434 let s = match config.clock {
581 reg.set_sample_time(0, self.sample_time); 435 Some(clock) => Self::new_with_clock(adc, clock),
582 reg.set_smpsel(channel.channel().into(), Smpsel::SMP1); 436 None => Self::new(adc),
583 }); 437 };
584 // Select channel 438
585 #[cfg(not(any(adc_g0, adc_u0)))] 439 #[cfg(any(adc_g0, adc_u0, adc_v3))]
586 T::regs().sqr1().write(|reg| reg.set_sq(0, channel.channel())); 440 if let Some(shift) = config.oversampling_shift {
441 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
442 }
443
444 #[cfg(any(adc_g0, adc_u0, adc_v3))]
445 if let Some(ratio) = config.oversampling_ratio {
446 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
447 }
448
587 #[cfg(any(adc_g0, adc_u0))] 449 #[cfg(any(adc_g0, adc_u0))]
588 T::regs().chselr().write(|reg| { 450 if let Some(enable) = config.oversampling_enable {
589 #[cfg(adc_g0)] 451 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable));
590 reg.set_chsel(channel.channel().into(), true); 452 }
591 #[cfg(adc_u0)]
592 reg.set_chsel(1 << channel.channel());
593 });
594 453
595 // Some models are affected by an erratum: 454 #[cfg(adc_v3)]
596 // If we perform conversions slower than 1 kHz, the first read ADC value can be 455 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
597 // corrupted, so we discard it and measure again. 456 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
598 // 457 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
599 // STM32L471xx: Section 2.7.3 458 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
600 // STM32G4: Section 2.7.3 459 }
601 #[cfg(any(rcc_l4, rcc_g4))]
602 let _ = self.convert();
603 let val = self.convert();
604 460
605 T::regs().cr().modify(|reg| reg.set_addis(true)); 461 if let Some(resolution) = config.resolution {
462 #[cfg(not(any(adc_g0, adc_u0)))]
463 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
464 #[cfg(any(adc_g0, adc_u0))]
465 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
466 }
606 467
607 // RM0492, RM0481, etc. 468 if let Some(averaging) = config.averaging {
608 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected." 469 let (enable, samples, right_shift) = match averaging {
609 #[cfg(any(adc_h5, adc_h7rs))] 470 Averaging::Disabled => (false, 0, 0),
610 if channel.channel() == 0 { 471 Averaging::Samples2 => (true, 0, 1),
611 T::regs().or().modify(|reg| reg.set_op0(false)); 472 Averaging::Samples4 => (true, 1, 2),
473 Averaging::Samples8 => (true, 2, 3),
474 Averaging::Samples16 => (true, 3, 4),
475 Averaging::Samples32 => (true, 4, 5),
476 Averaging::Samples64 => (true, 5, 6),
477 Averaging::Samples128 => (true, 6, 7),
478 Averaging::Samples256 => (true, 7, 8),
479 };
480 T::regs().cfgr2().modify(|reg| {
481 #[cfg(not(any(adc_g0, adc_u0)))]
482 reg.set_rovse(enable);
483 #[cfg(any(adc_g0, adc_u0))]
484 reg.set_ovse(enable);
485 #[cfg(any(adc_h5, adc_h7rs))]
486 reg.set_ovsr(samples.into());
487 #[cfg(not(any(adc_h5, adc_h7rs)))]
488 reg.set_ovsr(samples.into());
489 reg.set_ovss(right_shift.into());
490 })
612 } 491 }
613 492
614 val 493 s
615 } 494 }
616 495
617 #[cfg(adc_g0)] 496 #[cfg(adc_g0)]
618 pub fn set_oversampling_shift(&mut self, shift: Ovss) { 497 /// Initialize ADC with explicit clock for the analog ADC
619 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift)); 498 pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self {
620 } 499 Self::init_regulator();
621 #[cfg(adc_u0)]
622 pub fn set_oversampling_shift(&mut self, shift: u8) {
623 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
624 }
625 500
626 #[cfg(adc_g0)] 501 #[cfg(any(stm32wl5x))]
627 pub fn set_oversampling_ratio(&mut self, ratio: Ovsr) { 502 {
628 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio)); 503 // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual
629 } 504 let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0;
630 #[cfg(adc_u0)] 505 match clock {
631 pub fn set_oversampling_ratio(&mut self, ratio: u8) { 506 Clock::Async { div: _ } => {
632 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio)); 507 assert!(async_clock_available);
633 } 508 }
509 Clock::Sync { div: _ } => {
510 if async_clock_available {
511 warn!("Not using configured ADC clock");
512 }
513 }
514 }
515 }
516 match clock {
517 Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div)),
518 Clock::Sync { div } => T::regs().cfgr2().modify(|reg| {
519 reg.set_ckmode(match div {
520 CkModePclk::DIV1 => Ckmode::PCLK,
521 CkModePclk::DIV2 => Ckmode::PCLK_DIV2,
522 CkModePclk::DIV4 => Ckmode::PCLK_DIV4,
523 })
524 }),
525 }
634 526
635 #[cfg(any(adc_g0, adc_u0))] 527 Self::init_calibrate();
636 pub fn oversampling_enable(&mut self, enable: bool) {
637 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable));
638 }
639 528
640 #[cfg(adc_v3)] 529 Self { adc }
641 pub fn enable_regular_oversampling_mode(&mut self, mode: Rovsm, trig_mode: Trovs, enable: bool) {
642 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
643 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
644 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
645 } 530 }
646 531
647 #[cfg(adc_v3)] 532 pub fn enable_vrefint(&self) -> VrefInt {
648 pub fn set_oversampling_ratio(&mut self, ratio: OversamplingRatio) { 533 #[cfg(not(any(adc_g0, adc_u0)))]
649 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio)); 534 T::common_regs().ccr().modify(|reg| {
535 reg.set_vrefen(true);
536 });
537 #[cfg(any(adc_g0, adc_u0))]
538 T::regs().ccr().modify(|reg| {
539 reg.set_vrefen(true);
540 });
541
542 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
543 // to stabilize the internal voltage reference.
544 blocking_delay_us(15);
545
546 VrefInt {}
650 } 547 }
651 548
652 #[cfg(adc_v3)] 549 pub fn enable_temperature(&self) -> Temperature {
653 pub fn set_oversampling_shift(&mut self, shift: OversamplingShift) { 550 cfg_if! {
654 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift)); 551 if #[cfg(any(adc_g0, adc_u0))] {
552 T::regs().ccr().modify(|reg| {
553 reg.set_tsen(true);
554 });
555 } else if #[cfg(any(adc_h5, adc_h7rs))] {
556 T::common_regs().ccr().modify(|reg| {
557 reg.set_tsen(true);
558 });
559 } else {
560 T::common_regs().ccr().modify(|reg| {
561 reg.set_ch17sel(true);
562 });
563 }
564 }
565
566 Temperature {}
655 } 567 }
656 568
657 #[cfg(not(adc_g0))] 569 pub fn enable_vbat(&self) -> Vbat {
658 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
659 cfg_if! { 570 cfg_if! {
660 if #[cfg(adc_u0)] { 571 if #[cfg(any(adc_g0, adc_u0))] {
661 // On G0 and U6 all channels use the same sampling time. 572 T::regs().ccr().modify(|reg| {
662 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 573 reg.set_vbaten(true);
574 });
663 } else if #[cfg(any(adc_h5, adc_h7rs))] { 575 } else if #[cfg(any(adc_h5, adc_h7rs))] {
664 match _ch { 576 T::common_regs().ccr().modify(|reg| {
665 0..=9 => T::regs().smpr1().modify(|w| w.set_smp(_ch as usize % 10, sample_time.into())), 577 reg.set_vbaten(true);
666 _ => T::regs().smpr2().modify(|w| w.set_smp(_ch as usize % 10, sample_time.into())), 578 });
667 }
668 } else { 579 } else {
669 let sample_time = sample_time.into(); 580 T::common_regs().ccr().modify(|reg| {
670 T::regs() 581 reg.set_ch18sel(true);
671 .smpr(_ch as usize / 10) 582 });
672 .modify(|reg| reg.set_smp(_ch as usize % 10, sample_time));
673 } 583 }
674 } 584 }
585
586 Vbat {}
675 } 587 }
676 588
677 fn cancel_conversions() { 589 pub fn disable_vbat(&self) {
678 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 590 cfg_if! {
679 T::regs().cr().modify(|reg| { 591 if #[cfg(any(adc_g0, adc_u0))] {
680 reg.set_adstp(true); 592 T::regs().ccr().modify(|reg| {
681 }); 593 reg.set_vbaten(false);
682 while T::regs().cr().read().adstart() {} 594 });
595 } else if #[cfg(any(adc_h5, adc_h7rs))] {
596 T::common_regs().ccr().modify(|reg| {
597 reg.set_vbaten(false);
598 });
599 } else {
600 T::common_regs().ccr().modify(|reg| {
601 reg.set_ch18sel(false);
602 });
603 }
683 } 604 }
684 } 605 }
606
607 /*
608 /// Convert a raw sample from the `Temperature` to deg C
609 pub fn to_degrees_centigrade(sample: u16) -> f32 {
610 (130.0 - 30.0) / (VtempCal130::get().read() as f32 - VtempCal30::get().read() as f32)
611 * (sample as f32 - VtempCal30::get().read() as f32)
612 + 30.0
613 }
614 */
685} 615}