aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/adc/v4.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/adc/v4.rs')
-rw-r--r--embassy-stm32/src/adc/v4.rs558
1 files changed, 193 insertions, 365 deletions
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index b66437e6e..962816194 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -4,12 +4,12 @@ use pac::adc::vals::{Adcaldif, Boost};
4use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel}; 4use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel};
5use pac::adccommon::vals::Presc; 5use pac::adccommon::vals::Presc;
6 6
7use super::{ 7use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us};
8 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, 8#[cfg(stm32u5)]
9}; 9use crate::adc::DefaultInstance;
10use crate::dma::Transfer; 10use crate::adc::{AdcRegs, ConversionMode};
11use crate::time::Hertz; 11use crate::time::Hertz;
12use crate::{pac, rcc, Peri}; 12use crate::{Peri, pac, rcc};
13 13
14/// Default VREF voltage used for sample conversion to millivolts. 14/// Default VREF voltage used for sample conversion to millivolts.
15pub const VREF_DEFAULT_MV: u32 = 3300; 15pub const VREF_DEFAULT_MV: u32 = 3300;
@@ -25,153 +25,228 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); 25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55);
26 26
27#[cfg(stm32g4)] 27#[cfg(stm32g4)]
28const VREF_CHANNEL: u8 = 18; 28impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
29 const CHANNEL: u8 = 18;
30}
29#[cfg(stm32g4)] 31#[cfg(stm32g4)]
30const TEMP_CHANNEL: u8 = 16; 32impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
33 const CHANNEL: u8 = 16;
34}
31 35
32#[cfg(stm32h7)] 36#[cfg(stm32h7)]
33const VREF_CHANNEL: u8 = 19; 37impl<T: Instance> super::SealedSpecialConverter<super::VrefInt> for T {
38 const CHANNEL: u8 = 19;
39}
34#[cfg(stm32h7)] 40#[cfg(stm32h7)]
35const TEMP_CHANNEL: u8 = 18; 41impl<T: Instance> super::SealedSpecialConverter<super::Temperature> for T {
42 const CHANNEL: u8 = 18;
43}
36 44
37// TODO this should be 14 for H7a/b/35 45// TODO this should be 14 for H7a/b/35
38#[cfg(not(stm32u5))] 46#[cfg(not(stm32u5))]
39const VBAT_CHANNEL: u8 = 17; 47impl<T: Instance> super::SealedSpecialConverter<super::Vbat> for T {
48 const CHANNEL: u8 = 17;
49}
40 50
41#[cfg(stm32u5)] 51#[cfg(stm32u5)]
42const VREF_CHANNEL: u8 = 0; 52impl<T: DefaultInstance> super::SealedSpecialConverter<super::VrefInt> for T {
53 const CHANNEL: u8 = 0;
54}
43#[cfg(stm32u5)] 55#[cfg(stm32u5)]
44const TEMP_CHANNEL: u8 = 19; 56impl<T: DefaultInstance> super::SealedSpecialConverter<super::Temperature> for T {
57 const CHANNEL: u8 = 19;
58}
45#[cfg(stm32u5)] 59#[cfg(stm32u5)]
46const VBAT_CHANNEL: u8 = 18; 60impl<T: DefaultInstance> super::SealedSpecialConverter<super::Vbat> for T {
47 61 const CHANNEL: u8 = 18;
48// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
49/// Internal voltage reference channel.
50pub 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} 62}
57 63
58/// Internal temperature channel. 64fn from_ker_ck(frequency: Hertz) -> Presc {
59pub struct Temperature; 65 let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0);
60impl<T: Instance> AdcChannel<T> for Temperature {} 66 match raw_prescaler {
61impl<T: Instance> SealedAdcChannel<T> for Temperature { 67 0 => Presc::DIV1,
62 fn channel(&self) -> u8 { 68 1 => Presc::DIV2,
63 TEMP_CHANNEL 69 2..=3 => Presc::DIV4,
70 4..=5 => Presc::DIV6,
71 6..=7 => Presc::DIV8,
72 8..=9 => Presc::DIV10,
73 10..=11 => Presc::DIV12,
74 _ => unimplemented!(),
64 } 75 }
65} 76}
66 77
67/// Internal battery voltage channel. 78/// Adc configuration
68pub struct Vbat; 79#[derive(Default)]
69impl<T: Instance> AdcChannel<T> for Vbat {} 80pub struct AdcConfig {
70impl<T: Instance> SealedAdcChannel<T> for Vbat { 81 pub resolution: Option<Resolution>,
71 fn channel(&self) -> u8 { 82 pub averaging: Option<Averaging>,
72 VBAT_CHANNEL
73 }
74} 83}
75 84
76// NOTE (unused): The prescaler enum closely copies the hardware capabilities, 85impl AdcRegs for crate::pac::adc::Adc {
77// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. 86 fn data(&self) -> *mut u16 {
78#[allow(unused)] 87 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
79enum Prescaler { 88 }
80 NotDivided, 89
81 DividedBy2, 90 fn enable(&self) {
82 DividedBy4, 91 self.isr().write(|w| w.set_adrdy(true));
83 DividedBy6, 92 self.cr().modify(|w| w.set_aden(true));
84 DividedBy8, 93 while !self.isr().read().adrdy() {}
85 DividedBy10, 94 self.isr().write(|w| w.set_adrdy(true));
86 DividedBy12, 95 }
87 DividedBy16,
88 DividedBy32,
89 DividedBy64,
90 DividedBy128,
91 DividedBy256,
92}
93 96
94impl Prescaler { 97 fn start(&self) {
95 fn from_ker_ck(frequency: Hertz) -> Self { 98 // Start conversion
96 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0; 99 self.cr().modify(|reg| {
97 match raw_prescaler { 100 reg.set_adstart(true);
98 0 => Self::NotDivided, 101 });
99 1 => Self::DividedBy2, 102 }
100 2..=3 => Self::DividedBy4, 103
101 4..=5 => Self::DividedBy6, 104 fn stop(&self) {
102 6..=7 => Self::DividedBy8, 105 if self.cr().read().adstart() && !self.cr().read().addis() {
103 8..=9 => Self::DividedBy10, 106 self.cr().modify(|reg| {
104 10..=11 => Self::DividedBy12, 107 reg.set_adstp(Adstp::STOP);
105 _ => unimplemented!(), 108 });
109 while self.cr().read().adstart() {}
106 } 110 }
111
112 // Reset configuration.
113 self.cfgr().modify(|reg| {
114 reg.set_cont(false);
115 reg.set_dmngt(Dmngt::from_bits(0));
116 });
107 } 117 }
108 118
109 fn divisor(&self) -> u32 { 119 fn convert(&self) {
110 match self { 120 self.isr().modify(|reg| {
111 Prescaler::NotDivided => 1, 121 reg.set_eos(true);
112 Prescaler::DividedBy2 => 2, 122 reg.set_eoc(true);
113 Prescaler::DividedBy4 => 4, 123 });
114 Prescaler::DividedBy6 => 6, 124
115 Prescaler::DividedBy8 => 8, 125 // Start conversion
116 Prescaler::DividedBy10 => 10, 126 self.cr().modify(|reg| {
117 Prescaler::DividedBy12 => 12, 127 reg.set_adstart(true);
118 Prescaler::DividedBy16 => 16, 128 });
119 Prescaler::DividedBy32 => 32, 129
120 Prescaler::DividedBy64 => 64, 130 while !self.isr().read().eos() {
121 Prescaler::DividedBy128 => 128, 131 // spin
122 Prescaler::DividedBy256 => 256,
123 } 132 }
124 } 133 }
125 134
126 fn presc(&self) -> Presc { 135 fn configure_dma(&self, conversion_mode: ConversionMode) {
127 match self { 136 match conversion_mode {
128 Prescaler::NotDivided => Presc::DIV1, 137 ConversionMode::Singular => {
129 Prescaler::DividedBy2 => Presc::DIV2, 138 self.isr().modify(|reg| {
130 Prescaler::DividedBy4 => Presc::DIV4, 139 reg.set_ovr(true);
131 Prescaler::DividedBy6 => Presc::DIV6, 140 });
132 Prescaler::DividedBy8 => Presc::DIV8, 141 self.cfgr().modify(|reg| {
133 Prescaler::DividedBy10 => Presc::DIV10, 142 reg.set_cont(true);
134 Prescaler::DividedBy12 => Presc::DIV12, 143 reg.set_dmngt(Dmngt::DMA_ONE_SHOT);
135 Prescaler::DividedBy16 => Presc::DIV16, 144 });
136 Prescaler::DividedBy32 => Presc::DIV32, 145 }
137 Prescaler::DividedBy64 => Presc::DIV64, 146 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
138 Prescaler::DividedBy128 => Presc::DIV128, 147 _ => unreachable!(),
139 Prescaler::DividedBy256 => Presc::DIV256,
140 } 148 }
141 } 149 }
142}
143 150
144/// Number of samples used for averaging. 151 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
145#[derive(Copy, Clone, Debug)] 152 // Set sequence length
146#[cfg_attr(feature = "defmt", derive(defmt::Format))] 153 self.sqr1().modify(|w| {
147pub enum Averaging { 154 w.set_l(sequence.len() as u8 - 1);
148 Disabled, 155 });
149 Samples2, 156
150 Samples4, 157 // Configure channels and ranks
151 Samples8, 158 for (i, ((channel, _), sample_time)) in sequence.enumerate() {
152 Samples16, 159 let sample_time = sample_time.into();
153 Samples32, 160 if channel <= 9 {
154 Samples64, 161 self.smpr(0).modify(|reg| reg.set_smp(channel as _, sample_time));
155 Samples128, 162 } else {
156 Samples256, 163 self.smpr(1).modify(|reg| reg.set_smp((channel - 10) as _, sample_time));
157 Samples512, 164 }
158 Samples1024, 165
166 #[cfg(any(stm32h7, stm32u5))]
167 {
168 self.cfgr2().modify(|w| w.set_lshift(0));
169 self.pcsel().modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
170 }
171
172 match i {
173 0..=3 => {
174 self.sqr1().modify(|w| {
175 w.set_sq(i, channel);
176 });
177 }
178 4..=8 => {
179 self.sqr2().modify(|w| {
180 w.set_sq(i - 4, channel);
181 });
182 }
183 9..=13 => {
184 self.sqr3().modify(|w| {
185 w.set_sq(i - 9, channel);
186 });
187 }
188 14..=15 => {
189 self.sqr4().modify(|w| {
190 w.set_sq(i - 14, channel);
191 });
192 }
193 _ => unreachable!(),
194 }
195 }
196 }
159} 197}
160 198
161impl<'d, T: Instance> Adc<'d, T> { 199impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> {
200 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
201 let s = Self::new(adc);
202
203 // Set the ADC resolution.
204 if let Some(resolution) = config.resolution {
205 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
206 }
207
208 // Set hardware averaging.
209 if let Some(averaging) = config.averaging {
210 let (enable, samples, right_shift) = match averaging {
211 Averaging::Disabled => (false, 0, 0),
212 Averaging::Samples2 => (true, 1, 1),
213 Averaging::Samples4 => (true, 3, 2),
214 Averaging::Samples8 => (true, 7, 3),
215 Averaging::Samples16 => (true, 15, 4),
216 Averaging::Samples32 => (true, 31, 5),
217 Averaging::Samples64 => (true, 63, 6),
218 Averaging::Samples128 => (true, 127, 7),
219 Averaging::Samples256 => (true, 255, 8),
220 Averaging::Samples512 => (true, 511, 9),
221 Averaging::Samples1024 => (true, 1023, 10),
222 };
223
224 T::regs().cfgr2().modify(|reg| {
225 reg.set_rovse(enable);
226 reg.set_ovsr(samples);
227 reg.set_ovss(right_shift);
228 })
229 }
230
231 s
232 }
233
162 /// Create a new ADC driver. 234 /// Create a new ADC driver.
163 pub fn new(adc: Peri<'d, T>) -> Self { 235 pub fn new(adc: Peri<'d, T>) -> Self {
164 rcc::enable_and_reset::<T>(); 236 rcc::enable_and_reset::<T>();
165 237
166 let prescaler = Prescaler::from_ker_ck(T::frequency()); 238 let prescaler = from_ker_ck(T::frequency());
167 239
168 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc())); 240 T::common_regs().ccr().modify(|w| w.set_presc(prescaler));
169 241
170 let frequency = Hertz(T::frequency().0 / prescaler.divisor()); 242 let frequency = T::frequency() / prescaler;
171 info!("ADC frequency set to {}", frequency); 243 info!("ADC frequency set to {}", frequency);
172 244
173 if frequency > MAX_ADC_CLK_FREQ { 245 if frequency > MAX_ADC_CLK_FREQ {
174 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 ); 246 panic!(
247 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
248 MAX_ADC_CLK_FREQ.0 / 1_000_000
249 );
175 } 250 }
176 251
177 #[cfg(stm32h7)] 252 #[cfg(stm32h7)]
@@ -187,40 +262,20 @@ impl<'d, T: Instance> Adc<'d, T> {
187 }; 262 };
188 T::regs().cr().modify(|w| w.set_boost(boost)); 263 T::regs().cr().modify(|w| w.set_boost(boost));
189 } 264 }
190 let mut s = Self {
191 adc,
192 sample_time: SampleTime::from_bits(0),
193 };
194 s.power_up();
195 s.configure_differential_inputs();
196
197 s.calibrate();
198 blocking_delay_us(1);
199 265
200 s.enable();
201 s.configure();
202
203 s
204 }
205
206 fn power_up(&mut self) {
207 T::regs().cr().modify(|reg| { 266 T::regs().cr().modify(|reg| {
208 reg.set_deeppwd(false); 267 reg.set_deeppwd(false);
209 reg.set_advregen(true); 268 reg.set_advregen(true);
210 }); 269 });
211 270
212 blocking_delay_us(10); 271 blocking_delay_us(10);
213 }
214 272
215 fn configure_differential_inputs(&mut self) {
216 T::regs().difsel().modify(|w| { 273 T::regs().difsel().modify(|w| {
217 for n in 0..20 { 274 for n in 0..20 {
218 w.set_difsel(n, Difsel::SINGLE_ENDED); 275 w.set_difsel(n, Difsel::SINGLE_ENDED);
219 } 276 }
220 }); 277 });
221 }
222 278
223 fn calibrate(&mut self) {
224 T::regs().cr().modify(|w| { 279 T::regs().cr().modify(|w| {
225 #[cfg(not(adc_u5))] 280 #[cfg(not(adc_u5))]
226 w.set_adcaldif(Adcaldif::SINGLE_ENDED); 281 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
@@ -230,21 +285,18 @@ impl<'d, T: Instance> Adc<'d, T> {
230 T::regs().cr().modify(|w| w.set_adcal(true)); 285 T::regs().cr().modify(|w| w.set_adcal(true));
231 286
232 while T::regs().cr().read().adcal() {} 287 while T::regs().cr().read().adcal() {}
233 }
234 288
235 fn enable(&mut self) { 289 blocking_delay_us(1);
236 T::regs().isr().write(|w| w.set_adrdy(true)); 290
237 T::regs().cr().modify(|w| w.set_aden(true)); 291 T::regs().enable();
238 while !T::regs().isr().read().adrdy() {}
239 T::regs().isr().write(|w| w.set_adrdy(true));
240 }
241 292
242 fn configure(&mut self) {
243 // single conversion mode, software trigger 293 // single conversion mode, software trigger
244 T::regs().cfgr().modify(|w| { 294 T::regs().cfgr().modify(|w| {
245 w.set_cont(false); 295 w.set_cont(false);
246 w.set_exten(Exten::DISABLED); 296 w.set_exten(Exten::DISABLED);
247 }); 297 });
298
299 Self { adc }
248 } 300 }
249 301
250 /// Enable reading the voltage reference internal channel. 302 /// Enable reading the voltage reference internal channel.
@@ -273,228 +325,4 @@ impl<'d, T: Instance> Adc<'d, T> {
273 325
274 Vbat {} 326 Vbat {}
275 } 327 }
276
277 /// Set the ADC sample time.
278 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
279 self.sample_time = sample_time;
280 }
281
282 /// Get the ADC sample time.
283 pub fn sample_time(&self) -> SampleTime {
284 self.sample_time
285 }
286
287 /// Set the ADC resolution.
288 pub fn set_resolution(&mut self, resolution: Resolution) {
289 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
290 }
291
292 /// Set hardware averaging.
293 pub fn set_averaging(&mut self, averaging: Averaging) {
294 let (enable, samples, right_shift) = match averaging {
295 Averaging::Disabled => (false, 0, 0),
296 Averaging::Samples2 => (true, 1, 1),
297 Averaging::Samples4 => (true, 3, 2),
298 Averaging::Samples8 => (true, 7, 3),
299 Averaging::Samples16 => (true, 15, 4),
300 Averaging::Samples32 => (true, 31, 5),
301 Averaging::Samples64 => (true, 63, 6),
302 Averaging::Samples128 => (true, 127, 7),
303 Averaging::Samples256 => (true, 255, 8),
304 Averaging::Samples512 => (true, 511, 9),
305 Averaging::Samples1024 => (true, 1023, 10),
306 };
307
308 T::regs().cfgr2().modify(|reg| {
309 reg.set_rovse(enable);
310 reg.set_ovsr(samples);
311 reg.set_ovss(right_shift);
312 })
313 }
314
315 /// Perform a single conversion.
316 fn convert(&mut self) -> u16 {
317 T::regs().isr().modify(|reg| {
318 reg.set_eos(true);
319 reg.set_eoc(true);
320 });
321
322 // Start conversion
323 T::regs().cr().modify(|reg| {
324 reg.set_adstart(true);
325 });
326
327 while !T::regs().isr().read().eos() {
328 // spin
329 }
330
331 T::regs().dr().read().0 as u16
332 }
333
334 /// Read an ADC channel.
335 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
336 self.read_channel(channel)
337 }
338
339 /// Read one or multiple ADC channels using DMA.
340 ///
341 /// `sequence` iterator and `readings` must have the same length.
342 ///
343 /// Example
344 /// ```rust,ignore
345 /// use embassy_stm32::adc::{Adc, AdcChannel}
346 ///
347 /// let mut adc = Adc::new(p.ADC1);
348 /// let mut adc_pin0 = p.PA0.into();
349 /// let mut adc_pin2 = p.PA2.into();
350 /// let mut measurements = [0u16; 2];
351 ///
352 /// adc.read(
353 /// p.DMA2_CH0.reborrow(),
354 /// [
355 /// (&mut *adc_pin0, SampleTime::CYCLES112),
356 /// (&mut *adc_pin2, SampleTime::CYCLES112),
357 /// ]
358 /// .into_iter(),
359 /// &mut measurements,
360 /// )
361 /// .await;
362 /// defmt::info!("measurements: {}", measurements);
363 /// ```
364 pub async fn read(
365 &mut self,
366 rx_dma: Peri<'_, impl RxDma<T>>,
367 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
368 readings: &mut [u16],
369 ) {
370 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
371 assert!(
372 sequence.len() == readings.len(),
373 "Sequence length must be equal to readings length"
374 );
375 assert!(
376 sequence.len() <= 16,
377 "Asynchronous read sequence cannot be more than 16 in length"
378 );
379
380 // Ensure no conversions are ongoing
381 Self::cancel_conversions();
382
383 // Set sequence length
384 T::regs().sqr1().modify(|w| {
385 w.set_l(sequence.len() as u8 - 1);
386 });
387
388 // Configure channels and ranks
389 for (i, (channel, sample_time)) in sequence.enumerate() {
390 Self::configure_channel(channel, sample_time);
391 match i {
392 0..=3 => {
393 T::regs().sqr1().modify(|w| {
394 w.set_sq(i, channel.channel());
395 });
396 }
397 4..=8 => {
398 T::regs().sqr2().modify(|w| {
399 w.set_sq(i - 4, channel.channel());
400 });
401 }
402 9..=13 => {
403 T::regs().sqr3().modify(|w| {
404 w.set_sq(i - 9, channel.channel());
405 });
406 }
407 14..=15 => {
408 T::regs().sqr4().modify(|w| {
409 w.set_sq(i - 14, channel.channel());
410 });
411 }
412 _ => unreachable!(),
413 }
414 }
415
416 // Set continuous mode with oneshot dma.
417 // Clear overrun flag before starting transfer.
418
419 T::regs().isr().modify(|reg| {
420 reg.set_ovr(true);
421 });
422 T::regs().cfgr().modify(|reg| {
423 reg.set_cont(true);
424 reg.set_dmngt(Dmngt::DMA_ONE_SHOT);
425 });
426
427 let request = rx_dma.request();
428 let transfer = unsafe {
429 Transfer::new_read(
430 rx_dma,
431 request,
432 T::regs().dr().as_ptr() as *mut u16,
433 readings,
434 Default::default(),
435 )
436 };
437
438 // Start conversion
439 T::regs().cr().modify(|reg| {
440 reg.set_adstart(true);
441 });
442
443 // Wait for conversion sequence to finish.
444 transfer.await;
445
446 // Ensure conversions are finished.
447 Self::cancel_conversions();
448
449 // Reset configuration.
450 T::regs().cfgr().modify(|reg| {
451 reg.set_cont(false);
452 reg.set_dmngt(Dmngt::from_bits(0));
453 });
454 }
455
456 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
457 channel.setup();
458
459 let channel = channel.channel();
460
461 Self::set_channel_sample_time(channel, sample_time);
462
463 #[cfg(any(stm32h7, stm32u5))]
464 {
465 T::regs().cfgr2().modify(|w| w.set_lshift(0));
466 T::regs()
467 .pcsel()
468 .modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
469 }
470 }
471
472 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
473 Self::configure_channel(channel, self.sample_time);
474
475 T::regs().sqr1().modify(|reg| {
476 reg.set_sq(0, channel.channel());
477 reg.set_l(0);
478 });
479
480 self.convert()
481 }
482
483 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
484 let sample_time = sample_time.into();
485 if ch <= 9 {
486 T::regs().smpr(0).modify(|reg| reg.set_smp(ch as _, sample_time));
487 } else {
488 T::regs().smpr(1).modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
489 }
490 }
491
492 fn cancel_conversions() {
493 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
494 T::regs().cr().modify(|reg| {
495 reg.set_adstp(Adstp::STOP);
496 });
497 while T::regs().cr().read().adstart() {}
498 }
499 }
500} 328}