aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/v3.rs109
1 files changed, 67 insertions, 42 deletions
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 39f9ee463..0b9b80db2 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -13,10 +13,10 @@ use super::{
13 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, 13 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel,
14}; 14};
15 15
16#[cfg(any(adc_v3, adc_g0))] 16#[cfg(any(adc_v3, adc_g0, adc_u0))]
17mod ringbuffered_v3; 17mod ringbuffered_v3;
18 18
19#[cfg(any(adc_v3, adc_g0))] 19#[cfg(any(adc_v3, adc_g0, adc_u0))]
20use ringbuffered_v3::RingBufferedAdc; 20use ringbuffered_v3::RingBufferedAdc;
21 21
22use crate::dma::Transfer; 22use crate::dma::Transfer;
@@ -601,53 +601,78 @@ impl<'d, T: Instance> Adc<'d, T> {
601 w.set_l(sequence.len() as u8 - 1); 601 w.set_l(sequence.len() as u8 - 1);
602 }); 602 });
603 603
604 #[cfg(any(adc_g0, adc_u0))] 604 #[cfg(adc_g0)]
605 let mut channel_mask = 0; 605 {
606 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new();
607
608 T::regs().chselr().write(|chselr| {
609 T::regs().smpr().write(|smpr| {
610 for (channel, sample_time) in sequence {
611 chselr.set_chsel(channel.channel.into(), true);
612 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) {
613 smpr.set_smpsel(channel.channel.into(), (i as u8).into());
614 } else {
615 smpr.set_sample_time(sample_times.len(), sample_time);
616 if let Err(_) = sample_times.push(sample_time) {
617 panic!(
618 "Implementation is limited to {} unique sample times among all channels.",
619 SAMPLE_TIMES_CAPACITY
620 );
621 }
622 }
623 }
624 })
625 });
626 }
627 #[cfg(not(adc_g0))]
628 {
629 #[cfg(adc_u0)]
630 let mut channel_mask = 0;
606 631
607 // Configure channels and ranks 632 // Configure channels and ranks
608 for (_i, (channel, sample_time)) in sequence.enumerate() { 633 for (_i, (channel, sample_time)) in sequence.enumerate() {
609 Self::configure_channel(channel, sample_time); 634 Self::configure_channel(channel, sample_time);
610 635
611 // Each channel is sampled according to sequence 636 // Each channel is sampled according to sequence
612 #[cfg(not(any(adc_g0, adc_u0)))] 637 #[cfg(not(any(adc_g0, adc_u0)))]
613 match _i { 638 match _i {
614 0..=3 => { 639 0..=3 => {
615 T::regs().sqr1().modify(|w| { 640 T::regs().sqr1().modify(|w| {
616 w.set_sq(_i, channel.channel()); 641 w.set_sq(_i, channel.channel());
617 }); 642 });
618 } 643 }
619 4..=8 => { 644 4..=8 => {
620 T::regs().sqr2().modify(|w| { 645 T::regs().sqr2().modify(|w| {
621 w.set_sq(_i - 4, channel.channel()); 646 w.set_sq(_i - 4, channel.channel());
622 }); 647 });
623 } 648 }
624 9..=13 => { 649 9..=13 => {
625 T::regs().sqr3().modify(|w| { 650 T::regs().sqr3().modify(|w| {
626 w.set_sq(_i - 9, channel.channel()); 651 w.set_sq(_i - 9, channel.channel());
627 }); 652 });
653 }
654 14..=15 => {
655 T::regs().sqr4().modify(|w| {
656 w.set_sq(_i - 14, channel.channel());
657 });
658 }
659 _ => unreachable!(),
628 } 660 }
629 14..=15 => { 661
630 T::regs().sqr4().modify(|w| { 662 #[cfg(adc_u0)]
631 w.set_sq(_i - 14, channel.channel()); 663 {
632 }); 664 channel_mask |= 1 << channel.channel();
633 } 665 }
634 _ => unreachable!(),
635 } 666 }
636 667
637 #[cfg(any(adc_g0, adc_u0))] 668 // On G0 and U0 enabled channels are sampled from 0 to last channel.
638 { 669 // It is possible to add up to 8 sequences if CHSELRMOD = 1.
639 channel_mask |= 1 << channel.channel(); 670 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used.
640 } 671 #[cfg(adc_u0)]
672 T::regs().chselr().modify(|reg| {
673 reg.set_chsel(channel_mask);
674 });
641 } 675 }
642
643 // On G0 and U0 enabled channels are sampled from 0 to last channel.
644 // It is possible to add up to 8 sequences if CHSELRMOD = 1.
645 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used.
646 #[cfg(any(adc_g0, adc_u0))]
647 T::regs().chselr().modify(|reg| {
648 reg.set_chsel(channel_mask);
649 });
650
651 // Set continuous mode with Circular dma. 676 // Set continuous mode with Circular dma.
652 // Clear overrun flag before starting transfer. 677 // Clear overrun flag before starting transfer.
653 T::regs().isr().modify(|reg| { 678 T::regs().isr().modify(|reg| {