diff options
| author | xoviat <[email protected]> | 2025-11-11 09:37:20 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-11 09:37:20 -0600 |
| commit | aecff11b662c8232e7c848962c6c9ccda0cd9bf3 (patch) | |
| tree | 39bfc1f0b8a1abcd720aa9512ca6241d300bbb6c /embassy-stm32/src/adc/g4.rs | |
| parent | 16f2aaca61df2e708e78a12051365034281c95a4 (diff) | |
adc: cleanup g4
Diffstat (limited to 'embassy-stm32/src/adc/g4.rs')
| -rw-r--r-- | embassy-stm32/src/adc/g4.rs | 125 |
1 files changed, 48 insertions, 77 deletions
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index c0fb7c733..e622e2a23 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs | |||
| @@ -241,35 +241,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 241 | super::Vbat {} | 241 | super::Vbat {} |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | /// Enable differential channel. | ||
| 245 | /// Caution: | ||
| 246 | /// : When configuring the channel āiā in differential input mode, its negative input voltage VINN[i] | ||
| 247 | /// is connected to another channel. As a consequence, this channel is no longer usable in | ||
| 248 | /// single-ended mode or in differential mode and must never be configured to be converted. | ||
| 249 | /// Some channels are shared between ADC1/ADC2/ADC3/ADC4/ADC5: this can make the | ||
| 250 | /// channel on the other ADC unusable. The only exception is when ADC master and the slave | ||
| 251 | /// operate in interleaved mode. | ||
| 252 | #[cfg(stm32g4)] | ||
| 253 | fn set_differential_channel(&mut self, ch: usize, enable: bool) { | ||
| 254 | T::regs().cr().modify(|w| w.set_aden(false)); // disable adc | ||
| 255 | T::regs().difsel().modify(|w| { | ||
| 256 | w.set_difsel( | ||
| 257 | ch, | ||
| 258 | if enable { | ||
| 259 | Difsel::DIFFERENTIAL | ||
| 260 | } else { | ||
| 261 | Difsel::SINGLE_ENDED | ||
| 262 | }, | ||
| 263 | ); | ||
| 264 | }); | ||
| 265 | T::regs().cr().modify(|w| w.set_aden(true)); | ||
| 266 | } | ||
| 267 | |||
| 268 | #[cfg(stm32g4)] | ||
| 269 | pub fn set_differential(&mut self, channel: &mut impl AdcChannel<T>, enable: bool) { | ||
| 270 | self.set_differential_channel(channel.channel() as usize, enable); | ||
| 271 | } | ||
| 272 | |||
| 273 | /// Set oversampling shift. | 244 | /// Set oversampling shift. |
| 274 | #[cfg(stm32g4)] | 245 | #[cfg(stm32g4)] |
| 275 | pub fn set_oversampling_shift(&mut self, shift: u8) { | 246 | pub fn set_oversampling_shift(&mut self, shift: u8) { |
| @@ -331,7 +302,17 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 331 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { | 302 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 332 | channel.setup(); | 303 | channel.setup(); |
| 333 | 304 | ||
| 334 | self.read_channel(channel, sample_time) | 305 | Self::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter()); |
| 306 | |||
| 307 | #[cfg(stm32h7)] | ||
| 308 | { | ||
| 309 | T::regs().cfgr2().modify(|w| w.set_lshift(0)); | ||
| 310 | T::regs() | ||
| 311 | .pcsel() | ||
| 312 | .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED)); | ||
| 313 | } | ||
| 314 | |||
| 315 | self.convert() | ||
| 335 | } | 316 | } |
| 336 | 317 | ||
| 337 | /// Start regular adc conversion | 318 | /// Start regular adc conversion |
| @@ -404,11 +385,9 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 404 | Self::stop_regular_conversions(); | 385 | Self::stop_regular_conversions(); |
| 405 | Self::enable(); | 386 | Self::enable(); |
| 406 | 387 | ||
| 407 | Self::configure_sequence(sequence.map(|(channel, sample_time)| { | 388 | Self::configure_sequence( |
| 408 | channel.setup(); | 389 | sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), |
| 409 | 390 | ); | |
| 410 | (channel.channel, sample_time) | ||
| 411 | })); | ||
| 412 | 391 | ||
| 413 | // Set continuous mode with oneshot dma. | 392 | // Set continuous mode with oneshot dma. |
| 414 | // Clear overrun flag before starting transfer. | 393 | // Clear overrun flag before starting transfer. |
| @@ -451,14 +430,14 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 451 | }); | 430 | }); |
| 452 | } | 431 | } |
| 453 | 432 | ||
| 454 | pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = (u8, SampleTime)>) { | 433 | pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { |
| 455 | // Set sequence length | 434 | // Set sequence length |
| 456 | T::regs().sqr1().modify(|w| { | 435 | T::regs().sqr1().modify(|w| { |
| 457 | w.set_l(sequence.len() as u8 - 1); | 436 | w.set_l(sequence.len() as u8 - 1); |
| 458 | }); | 437 | }); |
| 459 | 438 | ||
| 460 | // Configure channels and ranks | 439 | // Configure channels and ranks |
| 461 | for (_i, (ch, sample_time)) in sequence.enumerate() { | 440 | for (_i, ((ch, is_differential), sample_time)) in sequence.enumerate() { |
| 462 | let sample_time = sample_time.into(); | 441 | let sample_time = sample_time.into(); |
| 463 | if ch <= 9 { | 442 | if ch <= 9 { |
| 464 | T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time)); | 443 | T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time)); |
| @@ -489,6 +468,24 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 489 | } | 468 | } |
| 490 | _ => unreachable!(), | 469 | _ => unreachable!(), |
| 491 | } | 470 | } |
| 471 | |||
| 472 | #[cfg(stm32g4)] | ||
| 473 | { | ||
| 474 | T::regs().cr().modify(|w| w.set_aden(false)); // disable adc | ||
| 475 | |||
| 476 | T::regs().difsel().modify(|w| { | ||
| 477 | w.set_difsel( | ||
| 478 | ch.into(), | ||
| 479 | if is_differential { | ||
| 480 | Difsel::DIFFERENTIAL | ||
| 481 | } else { | ||
| 482 | Difsel::SINGLE_ENDED | ||
| 483 | }, | ||
| 484 | ); | ||
| 485 | }); | ||
| 486 | |||
| 487 | T::regs().cr().modify(|w| w.set_aden(true)); // enable adc | ||
| 488 | } | ||
| 492 | } | 489 | } |
| 493 | } | 490 | } |
| 494 | 491 | ||
| @@ -548,12 +545,9 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 548 | Self::enable(); | 545 | Self::enable(); |
| 549 | 546 | ||
| 550 | //adc side setup | 547 | //adc side setup |
| 551 | 548 | Self::configure_sequence( | |
| 552 | Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { | 549 | sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), |
| 553 | channel.setup(); | 550 | ); |
| 554 | |||
| 555 | (channel.channel, sample_time) | ||
| 556 | })); | ||
| 557 | 551 | ||
| 558 | // Clear overrun flag before starting transfer. | 552 | // Clear overrun flag before starting transfer. |
| 559 | T::regs().isr().modify(|reg| { | 553 | T::regs().isr().modify(|reg| { |
| @@ -630,8 +624,17 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 630 | 624 | ||
| 631 | T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); | 625 | T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); |
| 632 | 626 | ||
| 633 | for (n, (mut channel, sample_time)) in sequence.into_iter().enumerate() { | 627 | for (n, (channel, sample_time)) in sequence.into_iter().enumerate() { |
| 634 | Self::configure_channel(&mut channel, sample_time); | 628 | let sample_time = sample_time.into(); |
| 629 | if channel.channel() <= 9 { | ||
| 630 | T::regs() | ||
| 631 | .smpr() | ||
| 632 | .modify(|reg| reg.set_smp(channel.channel() as _, sample_time)); | ||
| 633 | } else { | ||
| 634 | T::regs() | ||
| 635 | .smpr2() | ||
| 636 | .modify(|reg| reg.set_smp((channel.channel() - 10) as _, sample_time)); | ||
| 637 | } | ||
| 635 | 638 | ||
| 636 | let idx = match n { | 639 | let idx = match n { |
| 637 | 0..=3 => n, | 640 | 0..=3 => n, |
| @@ -733,38 +736,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 733 | T::regs().ier().modify(|r| r.set_jeosie(enable)); | 736 | T::regs().ier().modify(|r| r.set_jeosie(enable)); |
| 734 | } | 737 | } |
| 735 | 738 | ||
| 736 | fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) { | ||
| 737 | // Configure channel | ||
| 738 | Self::set_channel_sample_time(channel.channel(), sample_time); | ||
| 739 | } | ||
| 740 | |||
| 741 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { | ||
| 742 | Self::configure_channel(channel, sample_time); | ||
| 743 | #[cfg(stm32h7)] | ||
| 744 | { | ||
| 745 | T::regs().cfgr2().modify(|w| w.set_lshift(0)); | ||
| 746 | T::regs() | ||
| 747 | .pcsel() | ||
| 748 | .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED)); | ||
| 749 | } | ||
| 750 | |||
| 751 | T::regs().sqr1().write(|reg| { | ||
| 752 | reg.set_sq(0, channel.channel()); | ||
| 753 | reg.set_l(0); | ||
| 754 | }); | ||
| 755 | |||
| 756 | self.convert() | ||
| 757 | } | ||
| 758 | |||
| 759 | fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | ||
| 760 | let sample_time = sample_time.into(); | ||
| 761 | if ch <= 9 { | ||
| 762 | T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time)); | ||
| 763 | } else { | ||
| 764 | T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); | ||
| 765 | } | ||
| 766 | } | ||
| 767 | |||
| 768 | // Stop regular conversions | 739 | // Stop regular conversions |
| 769 | fn stop_regular_conversions() { | 740 | fn stop_regular_conversions() { |
| 770 | if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { | 741 | if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { |
