From 49ba9c3da2b6929c5ec1fb17d8c43c271a70eb34 Mon Sep 17 00:00:00 2001 From: Daehyeok Mun Date: Sun, 20 Aug 2023 19:31:47 -0700 Subject: [PATCH 1/6] initial support for STM32G4 ADC --- embassy-stm32/Cargo.toml | 5 +- embassy-stm32/src/adc/v4.rs | 247 +++++++++++++++----------------- embassy-stm32/src/rcc/g4.rs | 54 ++++++- embassy-stm32/src/rcc/mod.rs | 6 + examples/stm32g4/Cargo.toml | 2 + examples/stm32g4/src/bin/adc.rs | 41 ++++++ 6 files changed, 219 insertions(+), 136 deletions(-) create mode 100644 examples/stm32g4/src/bin/adc.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index d169107d..712996f2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9a61a1f090462df8bd1751f89951f04934fdceb3" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7e2310f49fa123fbc3225b91be73522b212703f0" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -70,6 +70,7 @@ embedded-io-async = { version = "0.5.0", optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" document-features = "0.2.7" +paste = "1.0" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } @@ -77,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9a61a1f090462df8bd1751f89951f04934fdceb3", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7e2310f49fa123fbc3225b91be73522b212703f0", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 64d0f0c7..d03f2550 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -1,8 +1,10 @@ use core::sync::atomic::{AtomicU8, Ordering}; use embedded_hal_02::blocking::delay::DelayUs; +#[allow(unused)] use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; use pac::adccommon::vals::Presc; +use paste::paste; use super::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime}; use crate::time::Hertz; @@ -13,12 +15,31 @@ pub const VREF_DEFAULT_MV: u32 = 3300; /// VREF voltage used for factory calibration of VREFINTCAL register. pub const VREF_CALIB_MV: u32 = 3300; -// NOTE: Vrefint/Temperature/Vbat are only available on ADC3 on H7, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs +/// Max single ADC operation clock frequency +#[cfg(stm32g4)] +const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); +#[cfg(stm32h7)] +const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); + +#[cfg(stm32g4)] +const VREF_CHANNEL: u8 = 18; +#[cfg(stm32g4)] +const TEMP_CHANNEL: u8 = 16; + +#[cfg(stm32h7)] +const VREF_CHANNEL: u8 = 19; +#[cfg(stm32h7)] +const TEMP_CHANNEL: u8 = 18; + +// TODO this should be 14 for H7a/b/35 +const VBAT_CHANNEL: u8 = 17; + +// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs pub struct VrefInt; impl InternalChannel for VrefInt {} impl super::sealed::InternalChannel for VrefInt { fn channel(&self) -> u8 { - 19 + VREF_CHANNEL } } @@ -26,7 +47,7 @@ pub struct Temperature; impl InternalChannel for Temperature {} impl super::sealed::InternalChannel for Temperature { fn channel(&self) -> u8 { - 18 + TEMP_CHANNEL } } @@ -34,126 +55,79 @@ pub struct Vbat; impl InternalChannel for Vbat {} impl super::sealed::InternalChannel for Vbat { fn channel(&self) -> u8 { - // TODO this should be 14 for H7a/b/35 - 17 + VBAT_CHANNEL } } static ADC12_ENABLE_COUNTER: AtomicU8 = AtomicU8::new(0); +#[cfg(any(stm32g4x3, stm32g4x4))] +static ADC345_ENABLE_COUNTER: AtomicU8 = AtomicU8::new(0); + +macro_rules! rcc_peripheral { + ($adc_name:ident, $freqs:ident, $ahb:ident, $reg:ident $(, $counter:ident )? ) => { + impl crate::rcc::sealed::RccPeripheral for crate::peripherals::$adc_name { + fn frequency() -> crate::time::Hertz { + critical_section::with(|_| { + match unsafe { crate::rcc::get_freqs() }.$freqs { + Some(ck) => ck, + None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") + } + }) + } + + fn enable() { + critical_section::with(|_| { + paste!{crate::pac::RCC.[< $ahb enr >]().modify(|w| w.[< set_ $reg en >](true))} + }); + $ ( $counter.fetch_add(1, Ordering::SeqCst); )? + } + + fn disable() { + $ ( if $counter.load(Ordering::SeqCst) == 1 )? { + critical_section::with(|_| { + paste!{crate::pac::RCC.[< $ahb enr >]().modify(|w| w.[< set_ $reg en >](false))} + }) + } + $ ( $counter.fetch_sub(1, Ordering::SeqCst); )? + } + + fn reset() { + $ ( if $counter.load(Ordering::SeqCst) == 1 )? { + critical_section::with(|_| { + paste!{crate::pac::RCC.[< $ahb rstr >]().modify(|w| w.[< set_ $reg rst >](true))} + paste!{crate::pac::RCC.[< $ahb rstr >]().modify(|w| w.[< set_ $reg rst >](false))} + }); + } + } + } + + impl crate::rcc::RccPeripheral for crate::peripherals::$adc_name {} + }; +} + +#[cfg(stm32g4)] +foreach_peripheral!( + (adc, ADC1) => { rcc_peripheral!(ADC1, adc12, ahb2, adc12, ADC12_ENABLE_COUNTER); }; + (adc, ADC2) => { rcc_peripheral!(ADC2, adc12, ahb2, adc12, ADC12_ENABLE_COUNTER); }; +); + +#[cfg(stm32g4x1)] +foreach_peripheral!( + (adc, ADC3) => { rcc_peripheral!(ADC3, adc345, ahb2, adc345); }; +); + +#[cfg(any(stm32g4x3, stm32g4x4))] +foreach_peripheral!( + (adc, ADC3) => { rcc_peripheral!(ADC3, adc345, ahb2, adc345, ADC345_ENABLE_COUNTER); }; + (adc, ADC4) => { rcc_peripheral!(ADC4, adc345, ahb2, adc345, ADC345_ENABLE_COUNTER); }; + (adc, ADC5) => { rcc_peripheral!(ADC5, adc345, ahb2, adc345, ADC345_ENABLE_COUNTER); }; +); #[cfg(stm32h7)] foreach_peripheral!( - (adc, ADC1) => { - impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 { - fn frequency() -> crate::time::Hertz { - critical_section::with(|_| { - match unsafe { crate::rcc::get_freqs() }.adc { - Some(ck) => ck, - None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") - } - }) - } - - fn enable() { - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) - }); - ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); - } - - fn disable() { - if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); - }) - } - ADC12_ENABLE_COUNTER.fetch_sub(1, Ordering::SeqCst); - } - - fn reset() { - if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| { - crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); - crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); - }); - } - } - } - - impl crate::rcc::RccPeripheral for crate::peripherals::ADC1 {} - }; - (adc, ADC2) => { - impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 { - fn frequency() -> crate::time::Hertz { - critical_section::with(|_| { - match unsafe { crate::rcc::get_freqs() }.adc { - Some(ck) => ck, - None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") - } - }) - } - - fn enable() { - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true)) - }); - ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst); - } - - fn disable() { - if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| { - crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false)); - }) - } - ADC12_ENABLE_COUNTER.fetch_sub(1, Ordering::SeqCst); - } - - fn reset() { - if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 { - critical_section::with(|_| { - crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true)); - crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false)); - }); - } - } - } - - impl crate::rcc::RccPeripheral for crate::peripherals::ADC2 {} - }; - (adc, ADC3) => { - impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 { - fn frequency() -> crate::time::Hertz { - critical_section::with(|_| { - match unsafe { crate::rcc::get_freqs() }.adc { - Some(ck) => ck, - None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") - } - }) - } - - fn enable() { - critical_section::with(|_| { - crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true)) - }); - } - - fn disable() { - critical_section::with(|_| { - crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false)); - }) - } - - fn reset() { - critical_section::with(|_| { - crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true)); - crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false)); - }); - } - } - - impl crate::rcc::RccPeripheral for crate::peripherals::ADC3 {} - }; + (adc, ADC1) => { rcc_peripheral!(ADC1, adc, ahb1, adc12, ADC12_ENABLE_COUNTER); }; + (adc, ADC2) => { rcc_peripheral!(ADC2, adc, ahb1, adc12, ADC12_ENABLE_COUNTER); }; + (adc, ADC3) => { rcc_peripheral!(ADC3, adc, ahb4, adc3); }; ); // NOTE (unused): The prescaler enum closely copies the hardware capabilities, @@ -176,7 +150,7 @@ enum Prescaler { impl Prescaler { fn from_ker_ck(frequency: Hertz) -> Self { - let raw_prescaler = frequency.0 / 50_000_000; + let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0; match raw_prescaler { 0 => Self::NotDivided, 1 => Self::DividedBy2, @@ -237,20 +211,23 @@ impl<'d, T: Instance> Adc<'d, T> { let frequency = Hertz(T::frequency().0 / prescaler.divisor()); info!("ADC frequency set to {} Hz", frequency.0); - if frequency > Hertz::mhz(50) { - panic!("Maximal allowed frequency for the ADC is 50 MHz and it varies with different packages, refer to ST docs for more information."); + if frequency > MAX_ADC_CLK_FREQ { + panic!("Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 ); } - let boost = if frequency < Hertz::khz(6_250) { - Boost::LT6_25 - } else if frequency < Hertz::khz(12_500) { - Boost::LT12_5 - } else if frequency < Hertz::mhz(25) { - Boost::LT25 - } else { - Boost::LT50 - }; - T::regs().cr().modify(|w| w.set_boost(boost)); + #[cfg(stm32h7)] + { + let boost = if frequency < Hertz::khz(6_250) { + Boost::LT6_25 + } else if frequency < Hertz::khz(12_500) { + Boost::LT12_5 + } else if frequency < Hertz::mhz(25) { + Boost::LT25 + } else { + Boost::LT50 + }; + T::regs().cr().modify(|w| w.set_boost(boost)); + } let mut s = Self { adc, sample_time: Default::default(), @@ -379,10 +356,14 @@ impl<'d, T: Instance> Adc<'d, T> { // Configure channel Self::set_channel_sample_time(channel, self.sample_time); - T::regs().cfgr2().modify(|w| w.set_lshift(0)); - T::regs() - .pcsel() - .write(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED)); + #[cfg(stm32h7)] + { + T::regs().cfgr2().modify(|w| w.set_lshift(0)); + T::regs() + .pcsel() + .write(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED)); + } + T::regs().sqr1().write(|reg| { reg.set_sq(0, channel); reg.set_l(0); diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 3b044cd1..4c95bb15 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -1,5 +1,5 @@ use stm32_metapac::flash::vals::Latency; -use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; +use stm32_metapac::rcc::vals::{Adcsel, Hpre, Pllsrc, Ppre, Sw}; use stm32_metapac::FLASH; pub use super::bus::{AHBPrescaler, APBPrescaler}; @@ -14,6 +14,29 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); +#[derive(Clone, Copy)] +pub enum AdcClockSource { + NoClk, + SysClk, + PllP, +} + +impl AdcClockSource { + pub fn adcsel(&self) -> Adcsel { + match self { + AdcClockSource::NoClk => Adcsel::NOCLK, + AdcClockSource::SysClk => Adcsel::SYSCLK, + AdcClockSource::PllP => Adcsel::PLLP, + } + } +} + +impl Default for AdcClockSource { + fn default() -> Self { + Self::NoClk + } +} + /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -327,6 +350,8 @@ pub struct Config { pub pll: Option, /// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals. pub clock_48mhz_src: Option, + pub adc12_clock_source: AdcClockSource, + pub adc345_clock_source: AdcClockSource, } /// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator. @@ -346,6 +371,8 @@ impl Default for Config { low_power_run: false, pll: None, clock_48mhz_src: None, + adc12_clock_source: Default::default(), + adc345_clock_source: Default::default(), } } } @@ -549,6 +576,29 @@ pub(crate) unsafe fn init(config: Config) { RCC.ccipr().modify(|w| w.set_clk48sel(source)); } + RCC.ccipr() + .modify(|w| w.set_adc12sel(config.adc12_clock_source.adcsel())); + RCC.ccipr() + .modify(|w| w.set_adc345sel(config.adc345_clock_source.adcsel())); + + let adc12_ck = match config.adc12_clock_source { + AdcClockSource::NoClk => None, + AdcClockSource::PllP => match &pll_freq { + Some(pll) => pll.pll_p, + None => None, + }, + AdcClockSource::SysClk => Some(Hertz(sys_clk)), + }; + + let adc345_ck = match config.adc345_clock_source { + AdcClockSource::NoClk => None, + AdcClockSource::PllP => match &pll_freq { + Some(pll) => pll.pll_p, + None => None, + }, + AdcClockSource::SysClk => Some(Hertz(sys_clk)), + }; + if config.low_power_run { assert!(sys_clk <= 2_000_000); PWR.cr1().modify(|w| w.set_lpr(true)); @@ -562,5 +612,7 @@ pub(crate) unsafe fn init(config: Config) { apb1_tim: Hertz(apb1_tim_freq), apb2: Hertz(apb2_freq), apb2_tim: Hertz(apb2_tim_freq), + adc12: adc12_ck, + adc345: adc345_ck, }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 0430e4a7..ecabe23a 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -77,6 +77,12 @@ pub struct Clocks { #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] pub adc: Option, + #[cfg(any(rcc_g4))] + pub adc12: Option, + + #[cfg(any(rcc_g4))] + pub adc345: Option, + #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] /// Set only if the lsi or lse is configured, indicates stop is supported pub rtc: Option, diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 0c1cdd67..2e81d206 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -11,6 +11,8 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +usbd-hid = "0.6.0" defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs new file mode 100644 index 00000000..a792748b --- /dev/null +++ b/examples/stm32g4/src/bin/adc.rs @@ -0,0 +1,41 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::adc::{Adc, SampleTime}; +use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSrc}; +use embassy_stm32::Config; +use embassy_time::{Delay, Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + + config.rcc.pll = Some(Pll { + source: PllSrc::HSI16, + prediv_m: PllM::Div4, + mul_n: PllN::Mul85, + div_p: None, + div_q: None, + // Main system clock at 170 MHz + div_r: Some(PllR::Div2), + }); + + config.rcc.adc12_clock_source = AdcClockSource::SysClk; + config.rcc.mux = ClockSrc::PLL; + + let mut p = embassy_stm32::init(config); + info!("Hello World!"); + + let mut adc = Adc::new(p.ADC2, &mut Delay); + adc.set_sample_time(SampleTime::Cycles32_5); + + loop { + let measured = adc.read(&mut p.PA7); + info!("measured: {}", measured); + Timer::after(Duration::from_millis(500)).await; + } +} From 7622d2eb61c030972756a962fee65e3ab66cfa10 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 5 Sep 2023 17:10:15 -0500 Subject: [PATCH 2/6] stm32: fix merge issues --- embassy-stm32/src/adc/v4.rs | 12 ++++++------ embassy-stm32/src/rcc/g4.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index d03f2550..2ff5c8f9 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -107,20 +107,20 @@ macro_rules! rcc_peripheral { #[cfg(stm32g4)] foreach_peripheral!( - (adc, ADC1) => { rcc_peripheral!(ADC1, adc12, ahb2, adc12, ADC12_ENABLE_COUNTER); }; - (adc, ADC2) => { rcc_peripheral!(ADC2, adc12, ahb2, adc12, ADC12_ENABLE_COUNTER); }; + (adc, ADC1) => { rcc_peripheral!(ADC1, adc, ahb2, adc12, ADC12_ENABLE_COUNTER); }; + (adc, ADC2) => { rcc_peripheral!(ADC2, adc, ahb2, adc12, ADC12_ENABLE_COUNTER); }; ); #[cfg(stm32g4x1)] foreach_peripheral!( - (adc, ADC3) => { rcc_peripheral!(ADC3, adc345, ahb2, adc345); }; + (adc, ADC3) => { rcc_peripheral!(ADC3, adc34, ahb2, adc345); }; ); #[cfg(any(stm32g4x3, stm32g4x4))] foreach_peripheral!( - (adc, ADC3) => { rcc_peripheral!(ADC3, adc345, ahb2, adc345, ADC345_ENABLE_COUNTER); }; - (adc, ADC4) => { rcc_peripheral!(ADC4, adc345, ahb2, adc345, ADC345_ENABLE_COUNTER); }; - (adc, ADC5) => { rcc_peripheral!(ADC5, adc345, ahb2, adc345, ADC345_ENABLE_COUNTER); }; + (adc, ADC3) => { rcc_peripheral!(ADC3, adc34, ahb2, adc345, ADC345_ENABLE_COUNTER); }; + (adc, ADC4) => { rcc_peripheral!(ADC4, adc34, ahb2, adc345, ADC345_ENABLE_COUNTER); }; + (adc, ADC5) => { rcc_peripheral!(ADC5, adc34, ahb2, adc345, ADC345_ENABLE_COUNTER); }; ); #[cfg(stm32h7)] diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 4c95bb15..2359f39c 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -612,7 +612,7 @@ pub(crate) unsafe fn init(config: Config) { apb1_tim: Hertz(apb1_tim_freq), apb2: Hertz(apb2_freq), apb2_tim: Hertz(apb2_tim_freq), - adc12: adc12_ck, - adc345: adc345_ck, + adc: adc12_ck, + adc34: adc345_ck, }); } From fd22f4fac5da01c8c171f2f3ed92f701bb0421d7 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 5 Sep 2023 17:45:52 -0500 Subject: [PATCH 3/6] stm32: remove paste and use refcount statics --- embassy-stm32/build.rs | 17 +++------ embassy-stm32/src/adc/mod.rs | 6 ++- embassy-stm32/src/adc/v4.rs | 74 ------------------------------------ 3 files changed, 10 insertions(+), 87 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index d3bfd24f..bb81736b 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -308,20 +308,11 @@ fn main() { // ======== // Generate RccPeripheral impls - // TODO: maybe get this from peripheral kind? Not sure - let mut refcounted_peripherals = HashSet::from(["usart"]); + let refcounted_peripherals = HashSet::from(["usart", "adc"]); let mut refcount_statics = HashSet::new(); - if chip_name.starts_with("stm32f3") { - refcounted_peripherals.insert("adc"); - } - for p in METADATA.peripherals { - // generating RccPeripheral impl for H7 ADC3 would result in bad frequency - if !singletons.contains(&p.name.to_string()) - || (p.name == "ADC3" && METADATA.line.starts_with("STM32H7")) - || (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "v4")) - { + if !singletons.contains(&p.name.to_string()) { continue; } @@ -711,6 +702,10 @@ fn main() { // ADC is special if regs.kind == "adc" { + if p.rcc.is_none() { + continue; + } + let peri = format_ident!("{}", p.name); let pin_name = format_ident!("{}", pin.pin); diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index a127445d..023a94f2 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -56,7 +56,7 @@ pub trait Instance: sealed::Instance + crate::Peripheral

+ crate::rcc: pub trait AdcPin: sealed::AdcPin {} pub trait InternalChannel: sealed::InternalChannel {} -#[cfg(not(any(stm32h7, adc_f3)))] +#[cfg(not(any(stm32h7, adc_f3, adc_v4)))] foreach_peripheral!( (adc, $inst:ident) => { impl crate::adc::sealed::Instance for peripherals::$inst { @@ -77,9 +77,10 @@ foreach_peripheral!( }; ); -#[cfg(any(stm32h7, adc_f3))] +#[cfg(any(stm32h7, adc_f3, adc_v4))] foreach_peripheral!( (adc, ADC3) => { + #[cfg(not(any(stm32g4x1, stm32g4x2, stm32g4x3, stm32g4x4)))] impl crate::adc::sealed::Instance for peripherals::ADC3 { fn regs() -> crate::pac::adc::Adc { crate::pac::ADC3 @@ -99,6 +100,7 @@ foreach_peripheral!( } } + #[cfg(not(any(stm32g4x1, stm32g4x2, stm32g4x3, stm32g4x4)))] impl crate::adc::Instance for peripherals::ADC3 {} }; (adc, ADC4) => { diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 2ff5c8f9..655c0cb6 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -1,10 +1,7 @@ -use core::sync::atomic::{AtomicU8, Ordering}; - use embedded_hal_02::blocking::delay::DelayUs; #[allow(unused)] use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; use pac::adccommon::vals::Presc; -use paste::paste; use super::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime}; use crate::time::Hertz; @@ -59,77 +56,6 @@ impl super::sealed::InternalChannel for Vbat { } } -static ADC12_ENABLE_COUNTER: AtomicU8 = AtomicU8::new(0); -#[cfg(any(stm32g4x3, stm32g4x4))] -static ADC345_ENABLE_COUNTER: AtomicU8 = AtomicU8::new(0); - -macro_rules! rcc_peripheral { - ($adc_name:ident, $freqs:ident, $ahb:ident, $reg:ident $(, $counter:ident )? ) => { - impl crate::rcc::sealed::RccPeripheral for crate::peripherals::$adc_name { - fn frequency() -> crate::time::Hertz { - critical_section::with(|_| { - match unsafe { crate::rcc::get_freqs() }.$freqs { - Some(ck) => ck, - None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.") - } - }) - } - - fn enable() { - critical_section::with(|_| { - paste!{crate::pac::RCC.[< $ahb enr >]().modify(|w| w.[< set_ $reg en >](true))} - }); - $ ( $counter.fetch_add(1, Ordering::SeqCst); )? - } - - fn disable() { - $ ( if $counter.load(Ordering::SeqCst) == 1 )? { - critical_section::with(|_| { - paste!{crate::pac::RCC.[< $ahb enr >]().modify(|w| w.[< set_ $reg en >](false))} - }) - } - $ ( $counter.fetch_sub(1, Ordering::SeqCst); )? - } - - fn reset() { - $ ( if $counter.load(Ordering::SeqCst) == 1 )? { - critical_section::with(|_| { - paste!{crate::pac::RCC.[< $ahb rstr >]().modify(|w| w.[< set_ $reg rst >](true))} - paste!{crate::pac::RCC.[< $ahb rstr >]().modify(|w| w.[< set_ $reg rst >](false))} - }); - } - } - } - - impl crate::rcc::RccPeripheral for crate::peripherals::$adc_name {} - }; -} - -#[cfg(stm32g4)] -foreach_peripheral!( - (adc, ADC1) => { rcc_peripheral!(ADC1, adc, ahb2, adc12, ADC12_ENABLE_COUNTER); }; - (adc, ADC2) => { rcc_peripheral!(ADC2, adc, ahb2, adc12, ADC12_ENABLE_COUNTER); }; -); - -#[cfg(stm32g4x1)] -foreach_peripheral!( - (adc, ADC3) => { rcc_peripheral!(ADC3, adc34, ahb2, adc345); }; -); - -#[cfg(any(stm32g4x3, stm32g4x4))] -foreach_peripheral!( - (adc, ADC3) => { rcc_peripheral!(ADC3, adc34, ahb2, adc345, ADC345_ENABLE_COUNTER); }; - (adc, ADC4) => { rcc_peripheral!(ADC4, adc34, ahb2, adc345, ADC345_ENABLE_COUNTER); }; - (adc, ADC5) => { rcc_peripheral!(ADC5, adc34, ahb2, adc345, ADC345_ENABLE_COUNTER); }; -); - -#[cfg(stm32h7)] -foreach_peripheral!( - (adc, ADC1) => { rcc_peripheral!(ADC1, adc, ahb1, adc12, ADC12_ENABLE_COUNTER); }; - (adc, ADC2) => { rcc_peripheral!(ADC2, adc, ahb1, adc12, ADC12_ENABLE_COUNTER); }; - (adc, ADC3) => { rcc_peripheral!(ADC3, adc, ahb4, adc3); }; -); - // NOTE (unused): The prescaler enum closely copies the hardware capabilities, // but high prescaling doesn't make a lot of sense in the current implementation and is ommited. #[allow(unused)] From f4601af2a4bbedc32a3c270696a8de2ed743b6d6 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 5 Sep 2023 17:48:20 -0500 Subject: [PATCH 4/6] stm32: don't generate adc4 for g4 --- embassy-stm32/src/adc/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 023a94f2..bdb1ab8a 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -104,6 +104,7 @@ foreach_peripheral!( impl crate::adc::Instance for peripherals::ADC3 {} }; (adc, ADC4) => { + #[cfg(not(any(stm32g4x1, stm32g4x2, stm32g4x3, stm32g4x4)))] impl crate::adc::sealed::Instance for peripherals::ADC4 { fn regs() -> crate::pac::adc::Adc { crate::pac::ADC4 @@ -123,6 +124,7 @@ foreach_peripheral!( } } + #[cfg(not(any(stm32g4x1, stm32g4x2, stm32g4x3, stm32g4x4)))] impl crate::adc::Instance for peripherals::ADC4 {} }; (adc, $inst:ident) => { From 73070987804023f50fcc4a264de8371fbba723d2 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 5 Sep 2023 17:50:45 -0500 Subject: [PATCH 5/6] stm32: don't generate adc5 --- embassy-stm32/src/adc/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index bdb1ab8a..0eeadfa9 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -126,6 +126,9 @@ foreach_peripheral!( #[cfg(not(any(stm32g4x1, stm32g4x2, stm32g4x3, stm32g4x4)))] impl crate::adc::Instance for peripherals::ADC4 {} + }; + (adc, ADC5) => { + }; (adc, $inst:ident) => { impl crate::adc::sealed::Instance for peripherals::$inst { From 50116e5b27c6b685cecfcdb4bf668a71664a770c Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 5 Sep 2023 18:20:17 -0500 Subject: [PATCH 6/6] remove paste dependency --- embassy-stm32/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 712996f2..30694596 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -70,7 +70,6 @@ embedded-io-async = { version = "0.5.0", optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" document-features = "0.2.7" -paste = "1.0" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] }