mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-27 04:10:25 +00:00
Adds ADC4 for WBA
This commit is contained in:
parent
15c7526c0a
commit
08f3b45de6
@ -1490,6 +1490,10 @@ fn main() {
|
||||
signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
|
||||
}
|
||||
|
||||
if chip_name.starts_with("stm32wba") {
|
||||
signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4));
|
||||
}
|
||||
|
||||
if chip_name.starts_with("stm32g4") {
|
||||
let line_number = chip_name.chars().skip(8).next().unwrap();
|
||||
if line_number == '3' || line_number == '4' {
|
||||
|
@ -1,10 +1,19 @@
|
||||
#[cfg(stm32u5)]
|
||||
use pac::adc::vals::{Adc4Dmacfg as Dmacfg, Adc4Exten as Exten, Adc4OversamplingRatio as OversamplingRatio};
|
||||
#[allow(unused)]
|
||||
use pac::adc::vals::{Adc4Dmacfg, Adc4Exten, Adc4OversamplingRatio};
|
||||
#[cfg(stm32wba)]
|
||||
use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel};
|
||||
|
||||
use super::{blocking_delay_us, AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel};
|
||||
use crate::dma::Transfer;
|
||||
pub use crate::pac::adc::regs::Adc4Chselrmod0;
|
||||
#[cfg(stm32u5)]
|
||||
pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr;
|
||||
#[cfg(stm32wba)]
|
||||
pub use crate::pac::adc::regs::Chselr;
|
||||
#[cfg(stm32u5)]
|
||||
pub use crate::pac::adc::vals::{Adc4Presc as Presc, Adc4Res as Resolution, Adc4SampleTime as SampleTime};
|
||||
#[cfg(stm32wba)]
|
||||
pub use crate::pac::adc::vals::{Presc, Res as Resolution, SampleTime};
|
||||
use crate::time::Hertz;
|
||||
use crate::{pac, rcc, Peri};
|
||||
|
||||
@ -242,17 +251,28 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
fn configure(&mut self) {
|
||||
// single conversion mode, software trigger
|
||||
T::regs().cfgr1().modify(|w| {
|
||||
#[cfg(stm32u5)]
|
||||
w.set_cont(false);
|
||||
#[cfg(stm32wba)]
|
||||
w.set_cont(Cont::SINGLE);
|
||||
w.set_discen(false);
|
||||
w.set_exten(Adc4Exten::DISABLED);
|
||||
w.set_exten(Exten::DISABLED);
|
||||
#[cfg(stm32u5)]
|
||||
w.set_chselrmod(false);
|
||||
#[cfg(stm32wba)]
|
||||
w.set_chselrmod(Chselrmod::ENABLE_INPUT);
|
||||
});
|
||||
|
||||
// only use one channel at the moment
|
||||
T::regs().smpr().modify(|w| {
|
||||
#[cfg(stm32u5)]
|
||||
for i in 0..24 {
|
||||
w.set_smpsel(i, false);
|
||||
}
|
||||
#[cfg(stm32wba)]
|
||||
for i in 0..14 {
|
||||
w.set_smpsel(i, Smpsel::SMP1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -275,6 +295,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
}
|
||||
|
||||
/// Enable reading the vbat internal channel.
|
||||
#[cfg(stm32u5)]
|
||||
pub fn enable_vbat(&self) -> Vbat {
|
||||
T::regs().ccr().modify(|w| {
|
||||
w.set_vbaten(true);
|
||||
@ -289,6 +310,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
}
|
||||
|
||||
/// Enable reading the vbat internal channel.
|
||||
#[cfg(stm32u5)]
|
||||
pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac {
|
||||
let mux;
|
||||
match dac {
|
||||
@ -317,17 +339,38 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
}
|
||||
|
||||
/// Set hardware averaging.
|
||||
#[cfg(stm32u5)]
|
||||
pub fn set_averaging(&mut self, averaging: Averaging) {
|
||||
let (enable, samples, right_shift) = match averaging {
|
||||
Averaging::Disabled => (false, Adc4OversamplingRatio::OVERSAMPLE2X, 0),
|
||||
Averaging::Samples2 => (true, Adc4OversamplingRatio::OVERSAMPLE2X, 1),
|
||||
Averaging::Samples4 => (true, Adc4OversamplingRatio::OVERSAMPLE4X, 2),
|
||||
Averaging::Samples8 => (true, Adc4OversamplingRatio::OVERSAMPLE8X, 3),
|
||||
Averaging::Samples16 => (true, Adc4OversamplingRatio::OVERSAMPLE16X, 4),
|
||||
Averaging::Samples32 => (true, Adc4OversamplingRatio::OVERSAMPLE32X, 5),
|
||||
Averaging::Samples64 => (true, Adc4OversamplingRatio::OVERSAMPLE64X, 6),
|
||||
Averaging::Samples128 => (true, Adc4OversamplingRatio::OVERSAMPLE128X, 7),
|
||||
Averaging::Samples256 => (true, Adc4OversamplingRatio::OVERSAMPLE256X, 8),
|
||||
Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0),
|
||||
Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1),
|
||||
Averaging::Samples4 => (true, OversamplingRatio::OVERSAMPLE4X, 2),
|
||||
Averaging::Samples8 => (true, OversamplingRatio::OVERSAMPLE8X, 3),
|
||||
Averaging::Samples16 => (true, OversamplingRatio::OVERSAMPLE16X, 4),
|
||||
Averaging::Samples32 => (true, OversamplingRatio::OVERSAMPLE32X, 5),
|
||||
Averaging::Samples64 => (true, OversamplingRatio::OVERSAMPLE64X, 6),
|
||||
Averaging::Samples128 => (true, OversamplingRatio::OVERSAMPLE128X, 7),
|
||||
Averaging::Samples256 => (true, OversamplingRatio::OVERSAMPLE256X, 8),
|
||||
};
|
||||
|
||||
T::regs().cfgr2().modify(|w| {
|
||||
w.set_ovsr(samples);
|
||||
w.set_ovss(right_shift);
|
||||
w.set_ovse(enable)
|
||||
})
|
||||
}
|
||||
#[cfg(stm32wba)]
|
||||
pub fn set_averaging(&mut self, averaging: Averaging) {
|
||||
let (enable, samples, right_shift) = match averaging {
|
||||
Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0),
|
||||
Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1),
|
||||
Averaging::Samples4 => (true, OversamplingRatio::OVERSAMPLE4X, Ovss::SHIFT2),
|
||||
Averaging::Samples8 => (true, OversamplingRatio::OVERSAMPLE8X, Ovss::SHIFT3),
|
||||
Averaging::Samples16 => (true, OversamplingRatio::OVERSAMPLE16X, Ovss::SHIFT4),
|
||||
Averaging::Samples32 => (true, OversamplingRatio::OVERSAMPLE32X, Ovss::SHIFT5),
|
||||
Averaging::Samples64 => (true, OversamplingRatio::OVERSAMPLE64X, Ovss::SHIFT6),
|
||||
Averaging::Samples128 => (true, OversamplingRatio::OVERSAMPLE128X, Ovss::SHIFT7),
|
||||
Averaging::Samples256 => (true, OversamplingRatio::OVERSAMPLE256X, Ovss::SHIFT8),
|
||||
};
|
||||
|
||||
T::regs().cfgr2().modify(|w| {
|
||||
@ -342,10 +385,20 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
channel.setup();
|
||||
|
||||
// Select channel
|
||||
T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
|
||||
T::regs().chselrmod0().modify(|w| {
|
||||
w.set_chsel(channel.channel() as usize, true);
|
||||
});
|
||||
#[cfg(stm32wba)]
|
||||
{
|
||||
T::regs().chselr().write_value(Chselr(0_u32));
|
||||
T::regs().chselr().modify(|w| {
|
||||
w.set_chsel0(channel.channel() as usize, true);
|
||||
});
|
||||
}
|
||||
#[cfg(stm32u5)]
|
||||
{
|
||||
T::regs().chselrmod0().write_value(Chselr(0_u32));
|
||||
T::regs().chselrmod0().modify(|w| {
|
||||
w.set_chsel(channel.channel() as usize, true);
|
||||
});
|
||||
}
|
||||
|
||||
// Reset interrupts
|
||||
T::regs().isr().modify(|reg| {
|
||||
@ -415,13 +468,19 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
|
||||
T::regs().cfgr1().modify(|reg| {
|
||||
reg.set_dmaen(true);
|
||||
reg.set_dmacfg(Adc4Dmacfg::ONE_SHOT);
|
||||
reg.set_dmacfg(Dmacfg::ONE_SHOT);
|
||||
#[cfg(stm32u5)]
|
||||
reg.set_chselrmod(false);
|
||||
#[cfg(stm32wba)]
|
||||
reg.set_chselrmod(Chselrmod::ENABLE_INPUT)
|
||||
});
|
||||
|
||||
// Verify and activate sequence
|
||||
let mut prev_channel: i16 = -1;
|
||||
T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
|
||||
#[cfg(stm32wba)]
|
||||
T::regs().chselr().write_value(Chselr(0_u32));
|
||||
#[cfg(stm32u5)]
|
||||
T::regs().chselrmod0().write_value(Chselr(0_u32));
|
||||
for channel in sequence {
|
||||
let channel_num = channel.channel;
|
||||
if channel_num as i16 <= prev_channel {
|
||||
@ -429,6 +488,11 @@ impl<'d, T: Instance> Adc4<'d, T> {
|
||||
};
|
||||
prev_channel = channel_num as i16;
|
||||
|
||||
#[cfg(stm32wba)]
|
||||
T::regs().chselr().modify(|w| {
|
||||
w.set_chsel0(channel.channel as usize, true);
|
||||
});
|
||||
#[cfg(stm32u5)]
|
||||
T::regs().chselrmod0().modify(|w| {
|
||||
w.set_chsel(channel.channel as usize, true);
|
||||
});
|
@ -4,7 +4,7 @@
|
||||
#![allow(missing_docs)] // TODO
|
||||
#![cfg_attr(adc_f3_v2, allow(unused))]
|
||||
|
||||
#[cfg(not(any(adc_f3_v2)))]
|
||||
#[cfg(not(any(adc_f3_v2, adc_wba)))]
|
||||
#[cfg_attr(adc_f1, path = "f1.rs")]
|
||||
#[cfg_attr(adc_f3, path = "f3.rs")]
|
||||
#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")]
|
||||
@ -20,14 +20,14 @@ mod _version;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
#[allow(unused)]
|
||||
#[cfg(not(any(adc_f3_v2)))]
|
||||
#[cfg(not(any(adc_f3_v2, adc_wba)))]
|
||||
pub use _version::*;
|
||||
use embassy_hal_internal::{impl_peripheral, PeripheralType};
|
||||
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
#[cfg(adc_u5)]
|
||||
#[path = "u5_adc4.rs"]
|
||||
#[cfg(any(adc_u5, adc_wba))]
|
||||
#[path = "adc4.rs"]
|
||||
pub mod adc4;
|
||||
|
||||
pub use crate::pac::adc::vals;
|
||||
@ -36,15 +36,18 @@ pub use crate::pac::adc::vals::Res as Resolution;
|
||||
pub use crate::pac::adc::vals::SampleTime;
|
||||
use crate::peripherals;
|
||||
|
||||
#[cfg(not(adc_wba))]
|
||||
dma_trait!(RxDma, Instance);
|
||||
#[cfg(adc_u5)]
|
||||
dma_trait!(RxDma4, adc4::Instance);
|
||||
#[cfg(adc_wba)]
|
||||
dma_trait!(RxDma4, adc4::Instance);
|
||||
|
||||
/// Analog to Digital driver.
|
||||
pub struct Adc<'d, T: Instance> {
|
||||
#[allow(unused)]
|
||||
adc: crate::Peri<'d, T>,
|
||||
#[cfg(not(any(adc_f3_v2, adc_f3_v1_1)))]
|
||||
#[cfg(not(any(adc_f3_v2, adc_f3_v1_1, adc_wba)))]
|
||||
sample_time: SampleTime,
|
||||
}
|
||||
|
||||
@ -63,6 +66,7 @@ impl State {
|
||||
}
|
||||
|
||||
trait SealedInstance {
|
||||
#[cfg(not(adc_wba))]
|
||||
#[allow(unused)]
|
||||
fn regs() -> crate::pac::adc::Adc;
|
||||
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
|
||||
@ -73,7 +77,7 @@ trait SealedInstance {
|
||||
}
|
||||
|
||||
pub(crate) trait SealedAdcChannel<T> {
|
||||
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))]
|
||||
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
|
||||
fn setup(&mut self) {}
|
||||
|
||||
#[allow(unused)]
|
||||
@ -110,7 +114,8 @@ pub(crate) fn blocking_delay_us(us: u32) {
|
||||
adc_h5,
|
||||
adc_h7rs,
|
||||
adc_u5,
|
||||
adc_c0
|
||||
adc_c0,
|
||||
adc_wba,
|
||||
)))]
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + crate::PeripheralType {
|
||||
@ -132,7 +137,8 @@ pub trait Instance: SealedInstance + crate::PeripheralType {
|
||||
adc_h5,
|
||||
adc_h7rs,
|
||||
adc_u5,
|
||||
adc_c0
|
||||
adc_c0,
|
||||
adc_wba,
|
||||
))]
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral {
|
||||
@ -144,7 +150,7 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri
|
||||
pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
|
||||
#[allow(unused_mut)]
|
||||
fn degrade_adc(mut self) -> AnyAdcChannel<T> {
|
||||
#[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))]
|
||||
#[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
|
||||
self.setup();
|
||||
|
||||
AnyAdcChannel {
|
||||
@ -176,6 +182,36 @@ impl<T> AnyAdcChannel<T> {
|
||||
self.channel
|
||||
}
|
||||
}
|
||||
#[cfg(adc_wba)]
|
||||
foreach_adc!(
|
||||
(ADC4, $common_inst:ident, $clock:ident) => {
|
||||
impl crate::adc::adc4::SealedInstance for peripherals::ADC4 {
|
||||
fn regs() -> crate::pac::adc::Adc4 {
|
||||
crate::pac::ADC4
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::adc::adc4::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!(
|
||||
@ -208,15 +244,21 @@ foreach_adc!(
|
||||
};
|
||||
);
|
||||
|
||||
#[cfg(not(adc_u5))]
|
||||
#[cfg(not(any(adc_u5, adc_wba)))]
|
||||
foreach_adc!(
|
||||
($inst:ident, $common_inst:ident, $clock:ident) => {
|
||||
impl crate::adc::SealedInstance for peripherals::$inst {
|
||||
#[cfg(not(adc_wba))]
|
||||
fn regs() -> crate::pac::adc::Adc {
|
||||
crate::pac::$inst
|
||||
}
|
||||
|
||||
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
|
||||
#[cfg(adc_wba)]
|
||||
fn regs() -> crate::pac::adc::Adc4 {
|
||||
crate::pac::$inst
|
||||
}
|
||||
|
||||
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0, adc_u5, adc_wba)))]
|
||||
fn common_regs() -> crate::pac::adccommon::AdcCommon {
|
||||
return crate::pac::$common_inst
|
||||
}
|
||||
@ -238,7 +280,7 @@ 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_v4, adc_u5))]
|
||||
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
|
||||
fn setup(&mut self) {
|
||||
<crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
|
||||
}
|
||||
|
@ -176,6 +176,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
// TODO
|
||||
lse: None,
|
||||
lsi: None,
|
||||
pll1_p: None,
|
||||
pll1_q: None,
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user