From e98694606d556d611400dcaf96844343bed2c5f7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 4 Dec 2025 02:11:16 +0100 Subject: stm32/adc: add lifetime to AnyAdcChannel. --- embassy-stm32/src/adc/g4.rs | 18 +++++++++--------- embassy-stm32/src/adc/injected.rs | 10 +++++----- embassy-stm32/src/adc/mod.rs | 27 +++++++++++++++------------ 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 1767a3bb3..d4e526061 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -409,10 +409,10 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> { /// `InjectedAdc` to enforce bounds at compile time. pub fn setup_injected_conversions<'a, const N: usize>( self, - sequence: [(AnyAdcChannel, SampleTime); N], + sequence: [(AnyAdcChannel<'a, T>, SampleTime); N], trigger: ConversionTrigger, interrupt: bool, - ) -> InjectedAdc { + ) -> InjectedAdc<'a, T, N> { assert!(N != 0, "Read sequence cannot be empty"); assert!( N <= NR_INJECTED_RANKS, @@ -424,8 +424,8 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> { T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); - for (n, (channel, sample_time)) in sequence.into_iter().enumerate() { - let sample_time = sample_time.into(); + for (n, (channel, sample_time)) in sequence.iter().enumerate() { + let sample_time = sample_time.clone().into(); if channel.channel() <= 9 { T::regs() .smpr() @@ -487,16 +487,16 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> { /// This function is `unsafe` because it clones the ADC peripheral handle unchecked. Both the /// `RingBufferedAdc` and `InjectedAdc` take ownership of the handle and drop it independently. /// Ensure no other code concurrently accesses the same ADC instance in a conflicting way. - pub fn into_ring_buffered_and_injected<'a, const N: usize>( + pub fn into_ring_buffered_and_injected<'a, 'b, const N: usize>( self, dma: Peri<'a, impl RxDma>, dma_buf: &'a mut [u16], - regular_sequence: impl ExactSizeIterator, T::SampleTime)>, + regular_sequence: impl ExactSizeIterator, T::SampleTime)>, regular_conversion_mode: RegularConversionMode, - injected_sequence: [(AnyAdcChannel, SampleTime); N], + injected_sequence: [(AnyAdcChannel<'b, T>, SampleTime); N], injected_trigger: ConversionTrigger, injected_interrupt: bool, - ) -> (super::RingBufferedAdc<'a, T>, InjectedAdc) { + ) -> (super::RingBufferedAdc<'a, T>, InjectedAdc<'b, T, N>) { unsafe { ( Self { @@ -531,7 +531,7 @@ impl<'d, T: Instance + AnyInstance> Adc<'d, T> { } } -impl InjectedAdc { +impl<'a, T: Instance, const N: usize> InjectedAdc<'a, T, N> { /// Read sampled data from all injected ADC injected ranks /// Clear the JEOS flag to allow a new injected sequence pub(super) fn read_injected_data() -> [u16; N] { diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs index ccaa5d1b2..1af055644 100644 --- a/embassy-stm32/src/adc/injected.rs +++ b/embassy-stm32/src/adc/injected.rs @@ -10,13 +10,13 @@ use crate::adc::Instance; use crate::adc::{Adc, AnyInstance}; /// Injected ADC sequence with owned channels. -pub struct InjectedAdc { - _channels: [(AnyAdcChannel, SampleTime); N], +pub struct InjectedAdc<'a, T: Instance, const N: usize> { + _channels: [(AnyAdcChannel<'a, T>, SampleTime); N], _phantom: PhantomData, } -impl InjectedAdc { - pub(crate) fn new(channels: [(AnyAdcChannel, SampleTime); N]) -> Self { +impl<'a, T: Instance, const N: usize> InjectedAdc<'a, T, N> { + pub(crate) fn new(channels: [(AnyAdcChannel<'a, T>, SampleTime); N]) -> Self { Self { _channels: channels, _phantom: PhantomData, @@ -36,7 +36,7 @@ impl InjectedAdc { } } -impl Drop for InjectedAdc { +impl<'a, T: Instance + AnyInstance, const N: usize> Drop for InjectedAdc<'a, T, N> { fn drop(&mut self) { T::stop(); compiler_fence(Ordering::SeqCst); diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index a55b99e6a..9040eefe5 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -25,7 +25,8 @@ use core::marker::PhantomData; #[allow(unused)] #[cfg(not(any(adc_f3v3, adc_wba)))] pub use _version::*; -use embassy_hal_internal::{PeripheralType, impl_peripheral}; +#[allow(unused)] +use embassy_hal_internal::PeripheralType; #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] use embassy_sync::waitqueue::AtomicWaker; #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] @@ -241,10 +242,10 @@ impl<'d, T: AnyInstance> Adc<'d, T> { /// in order or require the sequence to have the same sample time for all channnels, depending /// on the number and properties of the channels in the sequence. This method will panic if /// the hardware cannot deliver the requested configuration. - pub async fn read( + pub async fn read<'a, 'b: 'a>( &mut self, rx_dma: embassy_hal_internal::Peri<'_, impl RxDma>, - sequence: impl ExactSizeIterator, T::SampleTime)>, + sequence: impl ExactSizeIterator, T::SampleTime)>, readings: &mut [u16], ) { assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); @@ -313,11 +314,11 @@ impl<'d, T: AnyInstance> Adc<'d, T> { /// in order or require the sequence to have the same sample time for all channnels, depending /// on the number and properties of the channels in the sequence. This method will panic if /// the hardware cannot deliver the requested configuration. - pub fn into_ring_buffered<'a>( + pub fn into_ring_buffered<'a, 'b>( self, dma: embassy_hal_internal::Peri<'a, impl RxDma>, dma_buf: &'a mut [u16], - sequence: impl ExactSizeIterator, T::SampleTime)>, + sequence: impl ExactSizeIterator, T::SampleTime)>, mode: RegularConversionMode, ) -> RingBufferedAdc<'a, T> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); @@ -417,7 +418,10 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri #[allow(private_bounds)] pub trait AdcChannel: SealedAdcChannel + Sized { #[allow(unused_mut)] - fn degrade_adc(mut self) -> AnyAdcChannel { + fn degrade_adc<'a>(mut self) -> AnyAdcChannel<'a, T> + where + Self: 'a, + { #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))] self.setup(); @@ -433,14 +437,13 @@ pub trait AdcChannel: SealedAdcChannel + Sized { /// /// This is useful in scenarios where you need the ADC channels to have the same type, such as /// storing them in an array. -pub struct AnyAdcChannel { +pub struct AnyAdcChannel<'a, T> { channel: u8, is_differential: bool, - _phantom: PhantomData, + _phantom: PhantomData<&'a mut T>, } -impl_peripheral!(AnyAdcChannel); -impl AdcChannel for AnyAdcChannel {} -impl SealedAdcChannel for AnyAdcChannel { +impl AdcChannel for AnyAdcChannel<'_, T> {} +impl SealedAdcChannel for AnyAdcChannel<'_, T> { fn channel(&self) -> u8 { self.channel } @@ -450,7 +453,7 @@ impl SealedAdcChannel for AnyAdcChannel { } } -impl AnyAdcChannel { +impl AnyAdcChannel<'_, T> { #[allow(unused)] pub fn get_hw_channel(&self) -> u8 { self.channel -- cgit