#![macro_use]
#![allow(missing_docs)] #![cfg_attr(adc_f3v3, allow(unused))]
#[cfg(not(any(adc_f3v3, adc_wba)))]
#[cfg_attr(adc_f1, path = "f1.rs")]
#[cfg_attr(adc_f3v1, path = "f3.rs")]
#[cfg_attr(adc_f3v2, path = "f3_v1_1.rs")]
#[cfg_attr(adc_v1, path = "v1.rs")]
#[cfg_attr(adc_l0, path = "v1.rs")]
#[cfg_attr(adc_v2, path = "v2.rs")]
#[cfg_attr(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0), path = "v3.rs")]
#[cfg_attr(any(adc_v4, adc_u5, adc_u3), path = "v4.rs")]
#[cfg_attr(adc_g4, path = "g4.rs")]
#[cfg_attr(adc_c0, path = "c0.rs")]
mod _version;
#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0, adc_wba, adc_c0))]
mod ringbuffered;
use core::marker::PhantomData;
#[allow(unused)]
#[cfg(not(any(adc_f3v3, adc_wba)))]
pub use _version::*;
#[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, adc_wba, adc_c0))]
pub use ringbuffered::RingBufferedAdc;
#[cfg(adc_u5)]
use crate::pac::adc::vals::Adc4SampleTime;
#[cfg(adc_wba)]
use crate::pac::adc::vals::SampleTime as Adc4SampleTime;
#[cfg(any(adc_u5, adc_wba))]
#[path = "adc4.rs"]
pub mod adc4;
#[allow(unused)]
pub(self) use crate::block_for_us as blocking_delay_us;
pub use crate::pac::adc::vals;
#[cfg(any(adc_v2, adc_g4, adc_g0, adc_c0))]
pub use crate::pac::adc::vals::Exten;
#[cfg(not(any(adc_f1, adc_f3v3)))]
pub use crate::pac::adc::vals::Res as Resolution;
pub use crate::pac::adc::vals::SampleTime;
use crate::peripherals;
dma_trait!(RxDma, Instance);
pub struct CONTINUOUS;
impl<T: Instance> RegularTrigger<T> for CONTINUOUS {
fn signal(&self) -> u8 {
u8::MAX
}
}
pub struct Adc<'d, T: Instance> {
#[allow(unused)]
adc: crate::Peri<'d, T>,
}
#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
pub struct State {
pub waker: AtomicWaker,
}
#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
impl State {
pub const fn new() -> Self {
Self {
waker: AtomicWaker::new(),
}
}
}
#[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
trait_set::trait_set! {
pub trait DefaultInstance = Instance;
}
#[cfg(any(
adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_g4, adc_c0
))]
trait_set::trait_set! {
pub trait DefaultInstance = Instance<Regs = crate::pac::adc::Adc>;
}
#[cfg(adc_wba)]
trait_set::trait_set! {
pub trait DefaultInstance = Instance<Regs = crate::pac::adc::Adc4>;
}
pub trait BasicAdcRegs {
type SampleTime;
}
#[cfg(any(
adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba, adc_g4, adc_c0
))]
trait AdcRegs: BasicAdcRegs {
fn enable(&self);
fn start(&self);
fn stop(&self);
fn convert(&self);
fn configure_dma(&self, conversion_mode: ConversionMode);
fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>);
fn data(&self) -> *mut u16;
}
#[allow(private_bounds)]
pub trait BasicInstance {
#[cfg(any(
adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba, adc_g4, adc_c0
))]
type Regs: AdcRegs;
}
trait SealedInstance: BasicInstance {
#[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
fn regs() -> crate::pac::adc::Adc;
#[cfg(any(
adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba, adc_g4, adc_c0
))]
fn regs() -> Self::Regs;
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))]
#[allow(unused)]
fn common_regs() -> crate::pac::adccommon::AdcCommon;
#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
fn state() -> &'static State;
}
pub(crate) trait SealedAdcChannel<T> {
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_u3, adc_wba))]
fn setup(&mut self) {}
#[allow(unused)]
fn channel(&self) -> u8;
#[allow(unused)]
fn is_differential(&self) -> bool {
false
}
}
#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3))]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Averaging {
Disabled,
Samples2,
Samples4,
Samples8,
Samples16,
Samples32,
Samples64,
Samples128,
Samples256,
#[cfg(any(adc_c0, adc_v4, adc_u5, adc_u3))]
Samples512,
#[cfg(any(adc_c0, adc_v4, adc_u5, adc_u3))]
Samples1024,
}
#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0, adc_wba, adc_c0))]
pub(crate) struct Trigger {
#[cfg(any(adc_v2, adc_g4, adc_g0, adc_c0))]
signal: u8,
#[cfg(any(adc_v2, adc_g4, adc_g0, adc_c0))]
edge: Exten,
}
#[cfg(any(
adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3, adc_wba, adc_c0
))]
pub(crate) enum ConversionMode {
#[cfg(any(
adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3, adc_wba, adc_c0
))]
Singular,
#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0, adc_wba, adc_c0))]
Repeated(Trigger),
}
impl<'d, T: Instance> Adc<'d, T> {
#[cfg(any(
adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u3, adc_u5, adc_v3, adc_v4, adc_wba, adc_c0
))]
pub fn blocking_read(
&mut self,
channel: &mut impl AdcChannel<T>,
sample_time: <T::Regs as BasicAdcRegs>::SampleTime,
) -> u16 {
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba))]
channel.setup();
T::regs().stop();
#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u3, adc_u5, adc_wba))]
T::regs().enable();
T::regs().configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
#[cfg(any(adc_g4, adc_h5, adc_c0))]
T::regs().enable();
T::regs().convert();
unsafe { core::ptr::read_volatile(T::regs().data()) }
}
#[cfg(any(
adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3, adc_wba, adc_c0
))]
pub async fn read<'a, 'b: 'a, D: RxDma<T>>(
&mut self,
rx_dma: embassy_hal_internal::Peri<'a, D>,
irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'a,
sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
readings: &mut [u16],
) {
let _scoped_wake_guard = <T as crate::rcc::SealedRccPeripheral>::RCC_INFO.wake_guard();
assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
assert!(
readings.len() % sequence.len() == 0,
"Readings length must be a multiple of sequence length"
);
assert!(
sequence.len() <= 16,
"Asynchronous read sequence cannot be more than 16 in length"
);
T::regs().stop();
#[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba))]
T::regs().enable();
T::regs().configure_sequence(
sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
);
#[cfg(any(adc_g4, adc_h5, adc_c0))]
T::regs().enable();
T::regs().configure_dma(ConversionMode::Singular);
let request = rx_dma.request();
let mut dma_channel = crate::dma::Channel::new(rx_dma, irq);
let transfer = unsafe { dma_channel.read(request, T::regs().data(), readings, Default::default()) };
T::regs().start();
transfer.await;
T::regs().stop();
}
#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0, adc_wba, adc_c0))]
pub fn into_ring_buffered<'a, 'b, D: RxDma<T>>(
self,
dma: embassy_hal_internal::Peri<'a, D>,
dma_buf: &'a mut [u16],
irq: impl crate::interrupt::typelevel::Binding<D::Interrupt, crate::dma::InterruptHandler<D>> + 'a,
sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
_trigger: impl RegularTrigger<T>,
#[cfg(any(adc_v2, adc_g4, adc_g0, adc_c0))] edge: Exten,
) -> RingBufferedAdc<'a, T> {
let sequence_len = sequence.len();
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
assert!(sequence_len != 0, "Asynchronous read sequence cannot be empty");
assert!(
sequence_len <= 16,
"Asynchronous read sequence cannot be more than 16 in length"
);
assert!(
dma_buf.len() % sequence_len == 0,
"DMA buffer length must be a multiple of the scan sequence length"
);
T::regs().stop();
#[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
T::regs().enable();
T::regs().configure_sequence(
sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
);
#[cfg(any(adc_g4, adc_h5))]
T::regs().enable();
T::regs().configure_dma(ConversionMode::Repeated(Trigger {
#[cfg(any(adc_v2, adc_g4, adc_g0, adc_c0))]
signal: _trigger.signal(),
#[cfg(any(adc_v2, adc_g4, adc_g0, adc_c0))]
edge,
}));
core::mem::forget(self);
RingBufferedAdc::new(dma, irq, dma_buf, sequence_len)
}
}
pub(self) trait SpecialChannel {}
trait SealedSpecialConverter<T: SpecialChannel + Sized> {
const CHANNEL: u8;
}
#[allow(private_bounds)]
pub trait SpecialConverter<T: SpecialChannel + Sized>: SealedSpecialConverter<T> {}
impl<C: SpecialChannel + Sized, T: SealedSpecialConverter<C>> SpecialConverter<C> for T {}
impl<C: SpecialChannel, T: Instance + SealedSpecialConverter<C>> AdcChannel<T> for C {}
impl<C: SpecialChannel, T: Instance + SealedSpecialConverter<C>> SealedAdcChannel<T> for C {
fn channel(&self) -> u8 {
T::CHANNEL
}
}
pub struct VrefInt;
impl SpecialChannel for VrefInt {}
impl VrefInt {
#[cfg(any(
stm32f0,
stm32f3,
stm32f7,
stm32g0,
stm32g4,
stm32l0,
stm32l1,
stm32l4,
stm32l4_plus,
stm32l5,
stm32n6,
stm32l5,
stm32wb,
stm32wl
))]
pub fn calibrated_value(&self) -> u16 {
crate::pac::VREFINTCAL.data().read()
}
}
pub struct Temperature;
impl SpecialChannel for Temperature {}
pub struct Vbat;
impl SpecialChannel for Vbat {}
pub struct Vcore;
impl SpecialChannel for Vcore {}
pub struct Dac;
impl SpecialChannel for Dac {}
#[cfg(not(any(
adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs,
adc_u5, adc_u3, adc_c0, adc_wba,
)))]
#[allow(private_bounds)]
pub trait Instance: SealedInstance + crate::PeripheralType {
type Interrupt: crate::interrupt::typelevel::Interrupt;
}
#[cfg(any(
adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs,
adc_u5, adc_u3, adc_c0, adc_wba,
))]
#[allow(private_bounds)]
pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral {
type Interrupt: crate::interrupt::typelevel::Interrupt;
}
#[allow(private_bounds)]
pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
#[allow(unused_mut)]
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_u3, adc_u5, adc_wba))]
self.setup();
AnyAdcChannel {
channel: self.channel(),
is_differential: self.is_differential(),
_phantom: PhantomData,
}
}
}
pub struct AnyAdcChannel<'a, T> {
channel: u8,
is_differential: bool,
_phantom: PhantomData<&'a mut T>,
}
impl<T: Instance> AdcChannel<T> for AnyAdcChannel<'_, T> {}
impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<'_, T> {
fn channel(&self) -> u8 {
self.channel
}
fn is_differential(&self) -> bool {
self.is_differential
}
}
impl<T> AnyAdcChannel<'_, T> {
#[allow(unused)]
pub fn get_hw_channel(&self) -> u8 {
self.channel
}
}
#[cfg(not(adc_wba))]
impl BasicAdcRegs for crate::pac::adc::Adc {
type SampleTime = SampleTime;
}
#[cfg(any(adc_wba, adc_u5))]
impl BasicAdcRegs for crate::pac::adc::Adc4 {
type SampleTime = Adc4SampleTime;
}
trigger_trait!(RegularTrigger, Instance);
trigger_trait!(InjectedTrigger, Instance);
#[cfg(adc_wba)]
foreach_adc!(
(ADC4, $common_inst:ident, $clock:ident) => {
impl crate::adc::BasicInstance for peripherals::ADC4 {
type Regs = crate::pac::adc::Adc4;
}
impl crate::adc::SealedInstance for peripherals::ADC4 {
fn regs() -> Self::Regs {
crate::pac::ADC4
}
fn common_regs() -> crate::pac::adccommon::AdcCommon {
return crate::pac::$common_inst
}
}
impl crate::adc::Instance for peripherals::ADC4 {
type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
}
};
($inst:ident, $common_inst:ident, $clock:ident) => {
impl crate::adc::SealedInstance for peripherals::$inst {
fn regs() -> crate::pac::adc::Adc {
crate::pac::$inst
}
fn common_regs() -> crate::pac::adccommon::AdcCommon {
return crate::pac::$common_inst
}
}
impl crate::adc::Instance for peripherals::$inst {
type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
}
};
);
#[cfg(adc_u5)]
foreach_adc!(
(ADC4, $common_inst:ident, $clock:ident) => {
impl crate::adc::BasicInstance for peripherals::ADC4 {
type Regs = crate::pac::adc::Adc4;
}
impl crate::adc::SealedInstance for peripherals::ADC4 {
fn regs() -> Self::Regs {
crate::pac::ADC4
}
fn common_regs() -> crate::pac::adccommon::AdcCommon {
return crate::pac::$common_inst
}
}
impl crate::adc::Instance for peripherals::ADC4 {
type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
}
};
($inst:ident, $common_inst:ident, $clock:ident) => {
impl crate::adc::BasicInstance for peripherals::$inst {
type Regs = crate::pac::adc::Adc;
}
impl crate::adc::SealedInstance for peripherals::$inst {
fn regs() -> Self::Regs {
crate::pac::$inst
}
fn common_regs() -> crate::pac::adccommon::AdcCommon {
return crate::pac::$common_inst
}
}
impl crate::adc::Instance for peripherals::$inst {
type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
}
};
);
#[cfg(not(any(adc_u5, adc_wba)))]
foreach_adc!(
($inst:ident, $common_inst:ident, $clock:ident) => {
impl crate::adc::BasicInstance for peripherals::$inst {
#[cfg(any(
adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba, adc_g4, adc_c0
))]
type Regs = crate::pac::adc::Adc;
}
impl crate::adc::SealedInstance for peripherals::$inst {
#[cfg(any(
adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba, adc_g4, adc_c0
))]
fn regs() -> Self::Regs {
crate::pac::$inst
}
#[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
fn regs() -> crate::pac::adc::Adc {
crate::pac::$inst
}
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0, adc_u5, adc_wba)))]
fn common_regs() -> crate::pac::adccommon::AdcCommon {
return crate::pac::$common_inst
}
#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
fn state() -> &'static State {
static STATE: State = State::new();
&STATE
}
}
impl crate::adc::Instance for peripherals::$inst {
type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
}
};
);
macro_rules! impl_adc_pin {
($inst:ident, $pin:ident, $ch:expr) => {
impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {}
impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {
#[cfg(any(
adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba
))]
fn setup(&mut self) {
<crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
}
fn channel(&self) -> u8 {
$ch
}
}
};
}
#[allow(unused_macros)]
macro_rules! impl_adc_pair {
($inst:ident, $pin:ident, $npin:ident, $ch:expr) => {
impl crate::adc::AdcChannel<peripherals::$inst>
for (
crate::Peri<'_, crate::peripherals::$pin>,
crate::Peri<'_, crate::peripherals::$npin>,
)
{
}
impl crate::adc::SealedAdcChannel<peripherals::$inst>
for (
crate::Peri<'_, crate::peripherals::$pin>,
crate::Peri<'_, crate::peripherals::$npin>,
)
{
#[cfg(any(
adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba
))]
fn setup(&mut self) {
<crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(&mut self.0);
<crate::peripherals::$npin as crate::gpio::SealedPin>::set_as_analog(&mut self.1);
}
fn channel(&self) -> u8 {
$ch
}
fn is_differential(&self) -> bool {
true
}
}
};
}
#[cfg(not(any(adc_f1, adc_f3v3)))]
pub const fn resolution_to_max_count(res: Resolution) -> u32 {
match res {
#[cfg(adc_v4)]
Resolution::BITS16 => (1 << 16) - 1,
#[cfg(any(adc_v4, adc_u5))]
Resolution::BITS14 => (1 << 14) - 1,
#[cfg(adc_v4)]
Resolution::BITS14V => (1 << 14) - 1,
#[cfg(adc_v4)]
Resolution::BITS12V => (1 << 12) - 1,
Resolution::BITS12 => (1 << 12) - 1,
Resolution::BITS10 => (1 << 10) - 1,
Resolution::BITS8 => (1 << 8) - 1,
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_c0, adc_g0, adc_f3v1, adc_f3v2, adc_h5))]
Resolution::BITS6 => (1 << 6) - 1,
#[allow(unreachable_patterns)]
_ => core::unreachable!(),
}
}