aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/adc/v3.rs
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-06 12:17:00 -0600
committerxoviat <[email protected]>2025-12-06 12:17:00 -0600
commit4f66b2f2090e2fcfd7d92f9ebd07cc9048eb70d7 (patch)
tree8cc00b76c76aa08358e0959496cd7e1a77c6da76 /embassy-stm32/src/adc/v3.rs
parent4160184b314473c582ca8c4f50b880f4e42cf6e3 (diff)
adc: type-erase regs instance
Diffstat (limited to 'embassy-stm32/src/adc/v3.rs')
-rw-r--r--embassy-stm32/src/adc/v3.rs91
1 files changed, 44 insertions, 47 deletions
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index b270588c4..9cc44aa9a 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -146,63 +146,63 @@ pub struct AdcConfig {
146 pub averaging: Option<Averaging>, 146 pub averaging: Option<Averaging>,
147} 147}
148 148
149impl<T: Instance> super::SealedAnyInstance for T { 149impl super::AdcRegs for crate::pac::adc::Adc {
150 fn dr() -> *mut u16 { 150 fn data(&self) -> *mut u16 {
151 T::regs().dr().as_ptr() as *mut u16 151 crate::pac::adc::Adc::dr(*self).as_ptr() as *mut u16
152 } 152 }
153 153
154 // Enable ADC only when it is not already running. 154 // Enable ADC only when it is not already running.
155 fn enable() { 155 fn enable(&self) {
156 // Make sure bits are off 156 // Make sure bits are off
157 while T::regs().cr().read().addis() { 157 while self.cr().read().addis() {
158 // spin 158 // spin
159 } 159 }
160 160
161 if !T::regs().cr().read().aden() { 161 if !self.cr().read().aden() {
162 // Enable ADC 162 // Enable ADC
163 T::regs().isr().modify(|reg| { 163 self.isr().modify(|reg| {
164 reg.set_adrdy(true); 164 reg.set_adrdy(true);
165 }); 165 });
166 T::regs().cr().modify(|reg| { 166 self.cr().modify(|reg| {
167 reg.set_aden(true); 167 reg.set_aden(true);
168 }); 168 });
169 169
170 while !T::regs().isr().read().adrdy() { 170 while !self.isr().read().adrdy() {
171 // spin 171 // spin
172 } 172 }
173 } 173 }
174 } 174 }
175 175
176 fn start() { 176 fn start(&self) {
177 T::regs().cr().modify(|reg| { 177 self.cr().modify(|reg| {
178 reg.set_adstart(true); 178 reg.set_adstart(true);
179 }); 179 });
180 } 180 }
181 181
182 fn stop() { 182 fn stop(&self) {
183 // Ensure conversions are finished. 183 // Ensure conversions are finished.
184 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 184 if self.cr().read().adstart() && !self.cr().read().addis() {
185 T::regs().cr().modify(|reg| { 185 self.cr().modify(|reg| {
186 reg.set_adstp(true); 186 reg.set_adstp(true);
187 }); 187 });
188 while T::regs().cr().read().adstart() {} 188 while self.cr().read().adstart() {}
189 } 189 }
190 190
191 // Reset configuration. 191 // Reset configuration.
192 #[cfg(not(any(adc_g0, adc_u0)))] 192 #[cfg(not(any(adc_g0, adc_u0)))]
193 T::regs().cfgr().modify(|reg| { 193 self.cfgr().modify(|reg| {
194 reg.set_cont(false); 194 reg.set_cont(false);
195 reg.set_dmaen(false); 195 reg.set_dmaen(false);
196 }); 196 });
197 #[cfg(any(adc_g0, adc_u0))] 197 #[cfg(any(adc_g0, adc_u0))]
198 T::regs().cfgr1().modify(|reg| { 198 self.cfgr1().modify(|reg| {
199 reg.set_cont(false); 199 reg.set_cont(false);
200 reg.set_dmaen(false); 200 reg.set_dmaen(false);
201 }); 201 });
202 } 202 }
203 203
204 /// Perform a single conversion. 204 /// Perform a single conversion.
205 fn convert() -> u16 { 205 fn convert(&self) {
206 // Some models are affected by an erratum: 206 // Some models are affected by an erratum:
207 // If we perform conversions slower than 1 kHz, the first read ADC value can be 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. 208 // corrupted, so we discard it and measure again.
@@ -216,36 +216,34 @@ impl<T: Instance> super::SealedAnyInstance for T {
216 let len = 1; 216 let len = 1;
217 217
218 for _ in 0..len { 218 for _ in 0..len {
219 T::regs().isr().modify(|reg| { 219 self.isr().modify(|reg| {
220 reg.set_eos(true); 220 reg.set_eos(true);
221 reg.set_eoc(true); 221 reg.set_eoc(true);
222 }); 222 });
223 223
224 // Start conversion 224 // Start conversion
225 T::regs().cr().modify(|reg| { 225 self.cr().modify(|reg| {
226 reg.set_adstart(true); 226 reg.set_adstart(true);
227 }); 227 });
228 228
229 while !T::regs().isr().read().eos() { 229 while !self.isr().read().eos() {
230 // spin 230 // spin
231 } 231 }
232 } 232 }
233
234 T::regs().dr().read().0 as u16
235 } 233 }
236 234
237 fn configure_dma(conversion_mode: ConversionMode) { 235 fn configure_dma(&self, conversion_mode: ConversionMode) {
238 // Set continuous mode with oneshot dma. 236 // Set continuous mode with oneshot dma.
239 // Clear overrun flag before starting transfer. 237 // Clear overrun flag before starting transfer.
240 T::regs().isr().modify(|reg| { 238 self.isr().modify(|reg| {
241 reg.set_ovr(true); 239 reg.set_ovr(true);
242 }); 240 });
243 241
244 #[cfg(not(any(adc_g0, adc_u0)))] 242 #[cfg(not(any(adc_g0, adc_u0)))]
245 let regs = T::regs().cfgr(); 243 let regs = self.cfgr();
246 244
247 #[cfg(any(adc_g0, adc_u0))] 245 #[cfg(any(adc_g0, adc_u0))]
248 let regs = T::regs().cfgr1(); 246 let regs = self.cfgr1();
249 247
250 regs.modify(|reg| { 248 regs.modify(|reg| {
251 reg.set_discen(false); 249 reg.set_discen(false);
@@ -259,13 +257,13 @@ impl<T: Instance> super::SealedAnyInstance for T {
259 }); 257 });
260 } 258 }
261 259
262 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 260 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
263 #[cfg(adc_h5)] 261 #[cfg(adc_h5)]
264 T::regs().cr().modify(|w| w.set_aden(false)); 262 self.cr().modify(|w| w.set_aden(false));
265 263
266 // Set sequence length 264 // Set sequence length
267 #[cfg(not(any(adc_g0, adc_u0)))] 265 #[cfg(not(any(adc_g0, adc_u0)))]
268 T::regs().sqr1().modify(|w| { 266 self.sqr1().modify(|w| {
269 w.set_l(sequence.len() as u8 - 1); 267 w.set_l(sequence.len() as u8 - 1);
270 }); 268 });
271 269
@@ -273,8 +271,8 @@ impl<T: Instance> super::SealedAnyInstance for T {
273 { 271 {
274 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new(); 272 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new();
275 273
276 T::regs().chselr().write(|chselr| { 274 self.chselr().write(|chselr| {
277 T::regs().smpr().write(|smpr| { 275 self.smpr().write(|smpr| {
278 for ((channel, _), sample_time) in sequence { 276 for ((channel, _), sample_time) in sequence {
279 chselr.set_chsel(channel.into(), true); 277 chselr.set_chsel(channel.into(), true);
280 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) {
@@ -306,22 +304,22 @@ impl<T: Instance> super::SealedAnyInstance for T {
306 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected." 304 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
307 #[cfg(any(adc_h5, adc_h7rs))] 305 #[cfg(any(adc_h5, adc_h7rs))]
308 if channel == 0 { 306 if channel == 0 {
309 T::regs().or().modify(|reg| reg.set_op0(true)); 307 self.or().modify(|reg| reg.set_op0(true));
310 } 308 }
311 309
312 // Configure channel 310 // Configure channel
313 cfg_if! { 311 cfg_if! {
314 if #[cfg(adc_u0)] { 312 if #[cfg(adc_u0)] {
315 // On G0 and U6 all channels use the same sampling time. 313 // On G0 and U6 all channels use the same sampling time.
316 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 314 self.smpr().modify(|reg| reg.set_smp1(sample_time.into()));
317 } else if #[cfg(any(adc_h5, adc_h7rs))] { 315 } else if #[cfg(any(adc_h5, adc_h7rs))] {
318 match channel { 316 match channel {
319 0..=9 => T::regs().smpr1().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())), 317 0..=9 => self.smpr1().modify(|w| w.set_smp(channel as usize % 10, sample_time.into())),
320 _ => T::regs().smpr2().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())),
321 } 319 }
322 } else { 320 } else {
323 let sample_time = sample_time.into(); 321 let sample_time = sample_time.into();
324 T::regs() 322 self
325 .smpr(channel as usize / 10) 323 .smpr(channel as usize / 10)
326 .modify(|reg| reg.set_smp(channel as usize % 10, sample_time)); 324 .modify(|reg| reg.set_smp(channel as usize % 10, sample_time));
327 } 325 }
@@ -331,9 +329,8 @@ impl<T: Instance> super::SealedAnyInstance for T {
331 { 329 {
332 use crate::pac::adc::vals::Pcsel; 330 use crate::pac::adc::vals::Pcsel;
333 331
334 T::regs().cfgr2().modify(|w| w.set_lshift(0)); 332 self.cfgr2().modify(|w| w.set_lshift(0));
335 T::regs() 333 self.pcsel()
336 .pcsel()
337 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED)); 334 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
338 } 335 }
339 336
@@ -341,22 +338,22 @@ impl<T: Instance> super::SealedAnyInstance for T {
341 #[cfg(not(any(adc_g0, adc_u0)))] 338 #[cfg(not(any(adc_g0, adc_u0)))]
342 match _i { 339 match _i {
343 0..=3 => { 340 0..=3 => {
344 T::regs().sqr1().modify(|w| { 341 self.sqr1().modify(|w| {
345 w.set_sq(_i, channel); 342 w.set_sq(_i, channel);
346 }); 343 });
347 } 344 }
348 4..=8 => { 345 4..=8 => {
349 T::regs().sqr2().modify(|w| { 346 self.sqr2().modify(|w| {
350 w.set_sq(_i - 4, channel); 347 w.set_sq(_i - 4, channel);
351 }); 348 });
352 } 349 }
353 9..=13 => { 350 9..=13 => {
354 T::regs().sqr3().modify(|w| { 351 self.sqr3().modify(|w| {
355 w.set_sq(_i - 9, channel); 352 w.set_sq(_i - 9, channel);
356 }); 353 });
357 } 354 }
358 14..=15 => { 355 14..=15 => {
359 T::regs().sqr4().modify(|w| { 356 self.sqr4().modify(|w| {
360 w.set_sq(_i - 14, channel); 357 w.set_sq(_i - 14, channel);
361 }); 358 });
362 } 359 }
@@ -375,20 +372,20 @@ impl<T: Instance> super::SealedAnyInstance for T {
375 } 372 }
376 373
377 #[cfg(adc_h5)] 374 #[cfg(adc_h5)]
378 T::regs().difsel().write(|w| w.set_difsel(difsel)); 375 self.difsel().write(|w| w.set_difsel(difsel));
379 376
380 // 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.
381 // 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.
382 // 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.
383 #[cfg(adc_u0)] 380 #[cfg(adc_u0)]
384 T::regs().chselr().modify(|reg| { 381 self.chselr().modify(|reg| {
385 reg.set_chsel(channel_mask); 382 reg.set_chsel(channel_mask);
386 }); 383 });
387 } 384 }
388 } 385 }
389} 386}
390 387
391impl<'d, T: Instance> Adc<'d, T> { 388impl<'d, T: Instance<Regs = crate::pac::adc::Adc>> Adc<'d, T> {
392 /// Enable the voltage regulator 389 /// Enable the voltage regulator
393 fn init_regulator() { 390 fn init_regulator() {
394 rcc::enable_and_reset::<T>(); 391 rcc::enable_and_reset::<T>();