Skip to content

Commit

Permalink
Add methods for checking for ADC overrun
Browse files Browse the repository at this point in the history
  • Loading branch information
usbalbin committed Nov 30, 2023
1 parent a616cb0 commit 4a0a11a
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/adc-continious-dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ fn main() -> ! {
loop {
let mut b = [0_u16; 4];
let r = transfer.read_exact(&mut b);
assert!(
!transfer.get_overrun_flag(),
"DMA did not have time to read the ADC value before ADC was done with a new conversion"
);

info!("read: {}", r);
assert!(r == b.len());
Expand Down
51 changes: 51 additions & 0 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ pub mod config {
pub(crate) subgroup_len: SubGroupLength,
pub(crate) dma: Dma,
pub(crate) end_of_conversion_interrupt: Eoc,
pub(crate) overrun_interrupt: bool,
pub(crate) default_sample_time: SampleTime,
pub(crate) vdda: Option<u32>,
pub(crate) auto_delay: bool,
Expand Down Expand Up @@ -853,6 +854,15 @@ pub mod config {
self.end_of_conversion_interrupt = end_of_conversion_interrupt;
self
}

/// Enable/disable overrun interrupt
///
/// This is triggered when the AD finishes a conversion before the last value was read by CPU/DMA
pub fn overrun_interrupt(mut self, enable: bool) -> Self {
self.overrun_interrupt = enable;
self
}

/// change the default_sample_time field
#[inline(always)]
pub fn default_sample_time(mut self, default_sample_time: SampleTime) -> Self {
Expand Down Expand Up @@ -932,6 +942,7 @@ pub mod config {
subgroup_len: SubGroupLength::One,
dma: Dma::Disabled,
end_of_conversion_interrupt: Eoc::Disabled,
overrun_interrupt: false,
default_sample_time: SampleTime::Cycles_640_5,
vdda: None,
difsel: DifferentialSelection::default(),
Expand Down Expand Up @@ -1525,6 +1536,7 @@ macro_rules! adc {
self.set_subgroup_len(config.subgroup_len);
self.set_dma(config.dma);
self.set_end_of_conversion_interrupt(config.end_of_conversion_interrupt);
self.set_overrun_interrupt(config.overrun_interrupt);
self.set_default_sample_time(config.default_sample_time);
self.set_channel_input_type(config.difsel);
self.set_auto_delay(config.auto_delay);
Expand Down Expand Up @@ -1636,6 +1648,13 @@ macro_rules! adc {
);
}

/// Enable/disable overrun interrupt
///
/// This is triggered when the AD finishes a conversion before the last value was read by CPU/DMA
pub fn set_overrun_interrupt(&mut self, enable: bool) {
self.adc_reg.ier.modify(|_, w| w.ovrie().bit(enable));
}

/// Sets the default sample time that is used for one-shot conversions.
/// [configure_channel](#method.configure_channel) and [start_conversion](#method.start_conversion) can be \
/// used for configurations where different sampling times are required per channel.
Expand Down Expand Up @@ -1919,6 +1938,18 @@ macro_rules! adc {
pub fn is_vref_enabled(&mut self, common: &stm32::$common_type) -> bool {
common.ccr.read().vrefen().bit_is_set()
}

/// Read overrun flag
#[inline(always)]
pub fn get_overrun_flag(&self) -> bool {
self.adc_reg.isr.read().ovr().bit()
}

/// Resets the overrun flag
#[inline(always)]
pub fn clear_overrun_flag(&mut self) {
self.adc_reg.isr.modify(|_, w| w.ovr().set_bit());
}
}

//TODO: claim now configures the clock for all ADCs in the group (12 and 345).
Expand Down Expand Up @@ -2156,6 +2187,14 @@ macro_rules! adc {
self.adc.set_end_of_conversion_interrupt(eoc)
}

/// Enable/disable overrun interrupt
///
/// This is triggered when the AD finishes a conversion before the last value was read by CPU/DMA
#[inline(always)]
pub fn set_overrun_interrupt(&mut self, enable: bool) {
self.adc.set_overrun_interrupt(enable)
}

/// Sets the default sample time that is used for one-shot conversions.
/// [configure_channel](#method.configure_channel) and [start_conversion](#method.start_conversion) can be \
/// used for configurations where different sampling times are required per channel.
Expand Down Expand Up @@ -2367,6 +2406,18 @@ macro_rules! adc {
_status: PhantomData,
}
}

/// Read overrun flag
#[inline(always)]
pub fn get_overrun_flag(&self) -> bool {
self.adc.get_overrun_flag()
}

/// Resets the overrun flag
#[inline(always)]
pub fn clear_overrun_flag(&mut self) {
self.adc.clear_overrun_flag();
}
}

unsafe impl TargetAddress<PeripheralToMemory> for Adc<stm32::$adc_type, DMA> {
Expand Down
51 changes: 51 additions & 0 deletions src/dma/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,57 @@ where
}
}

macro_rules! impl_adc_overrun {
($($adc:ident, )*) => {$(
impl<STREAM, CONFIG, BUF> CircTransfer<STREAM, crate::adc::Adc<crate::stm32::$adc, crate::adc::DMA>, BUF>
where
STREAM: Stream<Config = CONFIG>,
BUF: StaticWriteBuffer + Deref,
<BUF as Deref>::Target: Index<Range<usize>, Output = [u16]> {
/// This is set when the AD finishes a conversion before the DMA has hade time to transfer the previous value
pub fn get_overrun_flag(&self) -> bool {
self.transfer.peripheral.get_overrun_flag()
}

pub fn clear_overrun_flag(&mut self) {
self.transfer.peripheral.clear_overrun_flag();
}
}
)*};
}

#[cfg(any(
feature = "stm32g431",
feature = "stm32g441",
feature = "stm32g471",
feature = "stm32g473",
feature = "stm32g474",
feature = "stm32g483",
feature = "stm32g484",
feature = "stm32g491",
feature = "stm32g4a1",
))]
impl_adc_overrun!(ADC1, ADC2,);

#[cfg(any(
feature = "stm32g471",
feature = "stm32g473",
feature = "stm32g474",
feature = "stm32g483",
feature = "stm32g484",
feature = "stm32g491",
feature = "stm32g4a1",
))]
impl_adc_overrun!(ADC3,);

#[cfg(any(
feature = "stm32g473",
feature = "stm32g474",
feature = "stm32g483",
feature = "stm32g484",
))]
impl_adc_overrun!(ADC4, ADC5,);

pub trait TransferExt<STREAM>
where
STREAM: traits::Stream,
Expand Down

0 comments on commit 4a0a11a

Please sign in to comment.