From c501b162fc5a7aa1219689132537471b8826a638 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 25 May 2021 17:09:01 +0200 Subject: [PATCH 01/11] Enable clock by default for stm32l0 Modify init function to return a Clock instance defined by a per-chip SystemClock type and use this in macro setup A proof of concept implementation for STM32 L0 chips. This allows using embassy::main macros for STM32 devices that have the clock setup logic. --- embassy-macros/src/chip/stm32.rs | 15 +- embassy-macros/src/lib.rs | 7 + embassy-stm32/src/clock.rs | 9 +- embassy-stm32/src/lib.rs | 13 +- embassy-stm32/src/rcc/h7/mod.rs | 6 +- embassy-stm32/src/rcc/l0/mod.rs | 585 ++++++++++++++++++++++++++++++- embassy-stm32/src/rcc/mod.rs | 4 +- 7 files changed, 614 insertions(+), 25 deletions(-) diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs index a1ceadd55..71eb98905 100644 --- a/embassy-macros/src/chip/stm32.rs +++ b/embassy-macros/src/chip/stm32.rs @@ -7,20 +7,17 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream let embassy_stm32_path = embassy_prefix.append("embassy_stm32").path(); quote!( - use #embassy_stm32_path::{clock::Clock}; + use #embassy_stm32_path::{interrupt, peripherals, clock::Clock, time::Hertz}; - let p = #embassy_stm32_path::init(#config); + let (p, mut c) = #embassy_stm32_path::init(#config); - /* - let mut rtc = #embass::RTC::new(unsafe { ::steal() }, interrupt::take!(TIM2)); - let rtc = unsafe { make_static(&mut rtc) }; - rtc.start(); - let mut alarm = rtc.alarm0(); + let clock = unsafe { make_static(&mut c) }; + clock.start(); - unsafe { #embassy_path::time::set_clock(rtc) }; + let mut alarm = clock.alarm1(); + unsafe { #embassy_path::time::set_clock(clock) }; let alarm = unsafe { make_static(&mut alarm) }; executor.set_alarm(alarm); - */ ) } diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index 3dc295fc1..f69c39701 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -350,6 +350,13 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { #[cortex_m_rt::entry] fn main() -> ! { + rtt_init_print!(); + unsafe { + log::set_logger_racy(&LOGGER).unwrap(); + } + + log::set_max_level(log::LevelFilter::Trace); + log::info!("Hello World!"); unsafe fn make_static(t: &mut T) -> &'static mut T { ::core::mem::transmute(t) } diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs index 709a2d36c..2ae0a3ba0 100644 --- a/embassy-stm32/src/clock.rs +++ b/embassy-stm32/src/clock.rs @@ -59,6 +59,8 @@ const ALARM_COUNT: usize = 3; pub struct Clock { _inner: T, irq: T::Interrupt, + /// Clock frequency + frequency: Hertz, /// Number of 2^23 periods elapsed since boot. period: AtomicU32, /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. @@ -66,22 +68,23 @@ pub struct Clock { } impl Clock { - pub fn new(peripheral: T, irq: T::Interrupt) -> Self { + pub fn new(peripheral: T, irq: T::Interrupt, frequency: Hertz) -> Self { Self { _inner: peripheral, irq, + frequency, period: AtomicU32::new(0), alarms: Mutex::new([AlarmState::new(), AlarmState::new(), AlarmState::new()]), } } - pub fn start(&'static self, timer_freq: Hertz) { + pub fn start(&'static self) { let inner = T::inner(); // NOTE(unsafe) Critical section to use the unsafe methods critical_section::with(|_| { unsafe { - inner.prepare(timer_freq); + inner.prepare(self.frequency); } self.irq.set_handler_context(self as *const _ as *mut _); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 250281f88..a1fa22111 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -36,6 +36,7 @@ pub mod time; pub use embassy_macros::interrupt; pub use pac::{interrupt, peripherals, Peripherals}; +pub use rcc::SystemClock; // workaround for svd2rust-generated code using `use crate::generic::*;` pub(crate) use pac::regs::generic; @@ -45,6 +46,12 @@ pub struct Config { rcc: rcc::Config, } +impl Config { + pub fn new(rcc: rcc::Config) -> Self { + Self { rcc } + } +} + impl Default for Config { fn default() -> Self { Self { @@ -54,14 +61,12 @@ impl Default for Config { } /// Initialize embassy. -pub fn init(config: Config) -> Peripherals { +pub fn init(config: Config) -> (Peripherals, SystemClock) { let p = Peripherals::take(); unsafe { dma::init(); pac::init_exti(); - rcc::init(config.rcc); + (p, rcc::init(config.rcc)) } - - p } diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7/mod.rs index 85e1cd00f..9a9c7ef0f 100644 --- a/embassy-stm32/src/rcc/h7/mod.rs +++ b/embassy-stm32/src/rcc/h7/mod.rs @@ -528,6 +528,6 @@ impl<'d> Rcc<'d> { } } -pub unsafe fn init(config: Config) { - // TODO -} +// TODO +pub type SystemClock = (); +pub unsafe fn init(_config: Config) -> SystemClock {} diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index 000aaa9e0..6c89022b8 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -1,11 +1,574 @@ +use crate::clock::Clock; +use crate::interrupt; use crate::pac; -use embassy::util::Steal; -use pac::rcc::{self, vals}; +use crate::pac::peripherals::{self, TIM2}; +use crate::time::Hertz; +use crate::time::U32Ext; +use pac::rcc::vals; +use vals::{Hpre, Lptimen, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw}; -#[derive(Default)] -pub struct Config {} +/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, +/// and with the addition of the init function to configure a system clock. -pub unsafe fn init(config: Config) { +/// System clock mux source +#[derive(Clone, Copy)] +pub enum ClockSrc { + MSI(MSIRange), + PLL(PLLSource, PLLMul, PLLDiv), + HSE(Hertz), + HSI16, +} + +/// MSI Clock Range +/// +/// These ranges control the frequency of the MSI. Internally, these ranges map +/// to the `MSIRANGE` bits in the `RCC_ICSCR` register. +#[derive(Clone, Copy)] +pub enum MSIRange { + /// Around 65.536 kHz + Range0, + /// Around 131.072 kHz + Range1, + /// Around 262.144 kHz + Range2, + /// Around 524.288 kHz + Range3, + /// Around 1.048 MHz + Range4, + /// Around 2.097 MHz (reset value) + Range5, + /// Around 4.194 MHz + Range6, +} + +impl Default for MSIRange { + fn default() -> MSIRange { + MSIRange::Range5 + } +} + +/// PLL divider +#[derive(Clone, Copy)] +pub enum PLLDiv { + Div2, + Div3, + Div4, +} + +/// PLL multiplier +#[derive(Clone, Copy)] +pub enum PLLMul { + Mul3, + Mul4, + Mul6, + Mul8, + Mul12, + Mul16, + Mul24, + Mul32, + Mul48, +} + +/// AHB prescaler +#[derive(Clone, Copy)] +pub enum AHBPrescaler { + NotDivided, + Div2, + Div4, + Div8, + Div16, + Div64, + Div128, + Div256, + Div512, +} + +/// APB prescaler +#[derive(Clone, Copy)] +pub enum APBPrescaler { + NotDivided, + Div2, + Div4, + Div8, + Div16, +} + +/// PLL clock input source +#[derive(Clone, Copy)] +pub enum PLLSource { + HSI16, + HSE(Hertz), +} + +/// HSI speed +pub const HSI_FREQ: u32 = 16_000_000; + +/// Clocks configutation +pub struct Config { + mux: ClockSrc, + ahb_pre: AHBPrescaler, + apb1_pre: APBPrescaler, + apb2_pre: APBPrescaler, +} + +impl Default for Config { + #[inline] + fn default() -> Config { + Config { + mux: ClockSrc::MSI(MSIRange::default()), + ahb_pre: AHBPrescaler::NotDivided, + apb1_pre: APBPrescaler::NotDivided, + apb2_pre: APBPrescaler::NotDivided, + } + } +} + +impl Config { + #[inline] + pub fn clock_src(mut self, mux: ClockSrc) -> Self { + self.mux = mux; + self + } + + #[inline] + pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self { + self.ahb_pre = pre; + self + } + + #[inline] + pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self { + self.apb1_pre = pre; + self + } + + #[inline] + pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self { + self.apb2_pre = pre; + self + } + + #[inline] + pub fn hsi16() -> Config { + Config { + mux: ClockSrc::HSI16, + ahb_pre: AHBPrescaler::NotDivided, + apb1_pre: APBPrescaler::NotDivided, + apb2_pre: APBPrescaler::NotDivided, + } + } + + #[inline] + pub fn msi(range: MSIRange) -> Config { + Config { + mux: ClockSrc::MSI(range), + ahb_pre: AHBPrescaler::NotDivided, + apb1_pre: APBPrescaler::NotDivided, + apb2_pre: APBPrescaler::NotDivided, + } + } + + #[inline] + pub fn pll(pll_src: PLLSource, pll_mul: PLLMul, pll_div: PLLDiv) -> Config { + Config { + mux: ClockSrc::PLL(pll_src, pll_mul, pll_div), + ahb_pre: AHBPrescaler::NotDivided, + apb1_pre: APBPrescaler::NotDivided, + apb2_pre: APBPrescaler::NotDivided, + } + } + + #[inline] + pub fn hse(freq: T) -> Config + where + T: Into, + { + Config { + mux: ClockSrc::HSE(freq.into()), + ahb_pre: AHBPrescaler::NotDivided, + apb1_pre: APBPrescaler::NotDivided, + apb2_pre: APBPrescaler::NotDivided, + } + } +} + +/// RCC peripheral +pub struct Rcc { + clocks: Clocks, + rb: pac::rcc::Rcc, +} + +/* +impl Rcc { + pub fn enable_lse(&mut self, _: &PWR) -> LSE { + self.rb.csr.modify(|_, w| { + // Enable LSE clock + w.lseon().set_bit() + }); + while self.rb.csr.read().lserdy().bit_is_clear() {} + LSE(()) + } +} +impl Rcc { + pub fn enable_hsi48(&mut self, syscfg: &mut SYSCFG, crs: CRS) -> HSI48 { + // Reset CRS peripheral + self.rb.apb1rstr.modify(|_, w| w.crsrst().set_bit()); + self.rb.apb1rstr.modify(|_, w| w.crsrst().clear_bit()); + + // Enable CRS peripheral + self.rb.apb1enr.modify(|_, w| w.crsen().set_bit()); + + // Initialize CRS + crs.cfgr.write(|w| + // Select LSE as synchronization source + unsafe { w.syncsrc().bits(0b01) }); + crs.cr + .modify(|_, w| w.autotrimen().set_bit().cen().set_bit()); + + // Enable VREFINT reference for HSI48 oscillator + syscfg + .syscfg + .cfgr3 + .modify(|_, w| w.enref_hsi48().set_bit().en_vrefint().set_bit()); + + // Select HSI48 as USB clock + self.rb.ccipr.modify(|_, w| w.hsi48msel().set_bit()); + + // Enable dedicated USB clock + self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit()); + while self.rb.crrcr.read().hsi48rdy().bit_is_clear() {} + + HSI48(()) + } +} + +impl Rcc { + /// Configure MCO (Microcontroller Clock Output). + pub fn configure_mco

( + &mut self, + source: MCOSEL_A, + prescaler: MCOPRE_A, + output_pin: P, + ) -> MCOEnabled + where + P: mco::Pin, + { + output_pin.into_mco(); + + self.rb.cfgr.modify(|_, w| { + w.mcosel().variant(source); + w.mcopre().variant(prescaler) + }); + + MCOEnabled(()) + } +} +*/ + +/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration +pub trait RccExt { + unsafe fn freeze(self, config: Config) -> Rcc; +} + +impl RccExt for pac::rcc::Rcc { + // `cfgr` is almost always a constant, so make sure it can be constant-propagated properly by + // marking this function and all `Config` constructors and setters as `#[inline]`. + // This saves ~900 Bytes for the `pwr.rs` example. + #[inline] + unsafe fn freeze(self, cfgr: Config) -> Rcc { + let (sys_clk, sw) = match cfgr.mux { + ClockSrc::MSI(range) => { + // Set MSI range + self.icscr().write(|w| w.set_msirange(range.into())); + + // Enable MSI + self.cr().write(|w| w.set_msion(Pllon::ENABLED)); + while !self.cr().read().msirdy() {} + + let freq = 32_768 * (1 << (range as u8 + 1)); + (freq, Sw::MSI) + } + ClockSrc::HSI16 => { + // Enable HSI16 + self.cr().write(|w| w.set_hsi16on(Pllon::ENABLED)); + while !self.cr().read().hsi16rdyf() {} + + (HSI_FREQ, Sw::HSI16) + } + ClockSrc::HSE(freq) => { + // Enable HSE + self.cr().write(|w| w.set_hseon(Pllon::ENABLED)); + while !self.cr().read().hserdy() {} + + (freq.0, Sw::HSE) + } + ClockSrc::PLL(src, mul, div) => { + let freq = match src { + PLLSource::HSE(freq) => { + // Enable HSE + self.cr().write(|w| w.set_hseon(Pllon::ENABLED)); + while !self.cr().read().hserdy() {} + freq.0 + } + PLLSource::HSI16 => { + // Enable HSI + self.cr().write(|w| w.set_hsi16on(Pllon::ENABLED)); + while !self.cr().read().hsi16rdyf() {} + HSI_FREQ + } + }; + + // Disable PLL + self.cr().modify(|w| w.set_pllon(Pllon::DISABLED)); + while self.cr().read().pllrdy() {} + + let freq = match mul { + PLLMul::Mul3 => freq * 3, + PLLMul::Mul4 => freq * 4, + PLLMul::Mul6 => freq * 6, + PLLMul::Mul8 => freq * 8, + PLLMul::Mul12 => freq * 12, + PLLMul::Mul16 => freq * 16, + PLLMul::Mul24 => freq * 24, + PLLMul::Mul32 => freq * 32, + PLLMul::Mul48 => freq * 48, + }; + + let freq = match div { + PLLDiv::Div2 => freq / 2, + PLLDiv::Div3 => freq / 3, + PLLDiv::Div4 => freq / 4, + }; + assert!(freq <= 32_u32.mhz().0); + + self.cfgr().write(move |w| { + w.set_pllmul(mul.into()); + w.set_plldiv(div.into()); + w.set_pllsrc(src.into()); + }); + + // Enable PLL + self.cr().modify(|w| w.set_pllon(Pllon::ENABLED)); + while !self.cr().read().pllrdy() {} + + (freq, Sw::PLL) + } + }; + + self.cfgr().modify(|w| { + w.set_sw(sw.into()); + w.set_hpre(cfgr.ahb_pre.into()); + w.set_ppre(0, cfgr.apb1_pre.into()); + w.set_ppre(1, cfgr.apb2_pre.into()); + }); + + let ahb_freq: u32 = match cfgr.ahb_pre { + AHBPrescaler::NotDivided => sys_clk, + pre => { + let pre: Hpre = pre.into(); + let pre = 1 << (pre.0 as u32 - 7); + sys_clk / pre + } + }; + + let (apb1_freq, apb1_tim_freq, apb1_pre) = match cfgr.apb1_pre { + APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), + pre => { + let pre: Ppre = pre.into(); + let pre: u8 = 1 << (pre.0 - 3); + let freq = ahb_freq / pre as u32; + (freq, freq * 2, pre as u8) + } + }; + + let (apb2_freq, apb2_tim_freq, apb2_pre) = match cfgr.apb2_pre { + APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), + pre => { + let pre: Ppre = pre.into(); + let pre: u8 = 1 << (pre.0 - 3); + let freq = ahb_freq / (1 << (pre as u8 - 3)); + (freq, freq * 2, pre as u8) + } + }; + + let clocks = Clocks { + source: cfgr.mux, + sys_clk: sys_clk.hz(), + ahb_clk: ahb_freq.hz(), + apb1_clk: apb1_freq.hz(), + apb2_clk: apb2_freq.hz(), + apb1_tim_clk: apb1_tim_freq.hz(), + apb2_tim_clk: apb2_tim_freq.hz(), + apb1_pre, + apb2_pre, + }; + + Rcc { rb: self, clocks } + } +} + +/// Frozen clock frequencies +/// +/// The existence of this value indicates that the clock configuration can no longer be changed +#[derive(Clone, Copy)] +pub struct Clocks { + source: ClockSrc, + sys_clk: Hertz, + ahb_clk: Hertz, + apb1_clk: Hertz, + apb1_tim_clk: Hertz, + apb2_clk: Hertz, + apb2_tim_clk: Hertz, + apb1_pre: u8, + apb2_pre: u8, +} + +impl Clocks { + /// Returns the clock source + pub fn source(&self) -> &ClockSrc { + &self.source + } + + /// Returns the system (core) frequency + pub fn sys_clk(&self) -> Hertz { + self.sys_clk + } + + /// Returns the frequency of the AHB + pub fn ahb_clk(&self) -> Hertz { + self.ahb_clk + } + + /// Returns the frequency of the APB1 + pub fn apb1_clk(&self) -> Hertz { + self.apb1_clk + } + + /// Returns the frequency of the APB1 timers + pub fn apb1_tim_clk(&self) -> Hertz { + self.apb1_tim_clk + } + + /// Returns the prescaler of the APB1 + pub fn apb1_pre(&self) -> u8 { + self.apb1_pre + } + + /// Returns the frequency of the APB2 + pub fn apb2_clk(&self) -> Hertz { + self.apb2_clk + } + + /// Returns the frequency of the APB2 timers + pub fn apb2_tim_clk(&self) -> Hertz { + self.apb2_tim_clk + } + + /// Returns the prescaler of the APB2 + pub fn apb2_pre(&self) -> u8 { + self.apb2_pre + } +} + +/// Token that exists only, if the HSI48 clock has been enabled +/// +/// You can get an instance of this struct by calling [`Rcc::enable_hsi48`]. +#[derive(Clone, Copy)] +pub struct HSI48(()); + +/// Token that exists only if MCO (Microcontroller Clock Out) has been enabled. +/// +/// You can get an instance of this struct by calling [`Rcc::configure_mco`]. +#[derive(Clone, Copy)] +pub struct MCOEnabled(()); + +/// Token that exists only, if the LSE clock has been enabled +/// +/// You can get an instance of this struct by calling [`Rcc::enable_lse`]. +#[derive(Clone, Copy)] +pub struct LSE(()); + +impl Into for PLLMul { + fn into(self) -> Pllmul { + match self { + PLLMul::Mul3 => Pllmul::MUL3, + PLLMul::Mul4 => Pllmul::MUL4, + PLLMul::Mul6 => Pllmul::MUL6, + PLLMul::Mul8 => Pllmul::MUL8, + PLLMul::Mul12 => Pllmul::MUL12, + PLLMul::Mul16 => Pllmul::MUL16, + PLLMul::Mul24 => Pllmul::MUL24, + PLLMul::Mul32 => Pllmul::MUL32, + PLLMul::Mul48 => Pllmul::MUL48, + } + } +} + +impl Into for PLLDiv { + fn into(self) -> Plldiv { + match self { + PLLDiv::Div2 => Plldiv::DIV2, + PLLDiv::Div3 => Plldiv::DIV3, + PLLDiv::Div4 => Plldiv::DIV4, + } + } +} + +impl Into for PLLSource { + fn into(self) -> Pllsrc { + match self { + PLLSource::HSI16 => Pllsrc::HSI16, + PLLSource::HSE(_) => Pllsrc::HSE, + } + } +} + +impl Into for APBPrescaler { + fn into(self) -> Ppre { + match self { + APBPrescaler::NotDivided => Ppre::DIV1, + APBPrescaler::Div2 => Ppre::DIV2, + APBPrescaler::Div4 => Ppre::DIV4, + APBPrescaler::Div8 => Ppre::DIV8, + APBPrescaler::Div16 => Ppre::DIV16, + } + } +} + +impl Into for AHBPrescaler { + fn into(self) -> Hpre { + match self { + AHBPrescaler::NotDivided => Hpre::DIV1, + AHBPrescaler::Div2 => Hpre::DIV2, + AHBPrescaler::Div4 => Hpre::DIV4, + AHBPrescaler::Div8 => Hpre::DIV8, + AHBPrescaler::Div16 => Hpre::DIV16, + AHBPrescaler::Div64 => Hpre::DIV64, + AHBPrescaler::Div128 => Hpre::DIV128, + AHBPrescaler::Div256 => Hpre::DIV256, + AHBPrescaler::Div512 => Hpre::DIV512, + } + } +} + +impl Into for MSIRange { + fn into(self) -> Msirange { + match self { + MSIRange::Range0 => Msirange::RANGE0, + MSIRange::Range1 => Msirange::RANGE1, + MSIRange::Range2 => Msirange::RANGE2, + MSIRange::Range3 => Msirange::RANGE3, + MSIRange::Range4 => Msirange::RANGE4, + MSIRange::Range5 => Msirange::RANGE5, + MSIRange::Range6 => Msirange::RANGE6, + } + } +} + +// We use TIM2 as SystemClock +pub type SystemClock = Clock; + +pub unsafe fn init(config: Config) -> SystemClock { let rcc = pac::RCC; let enabled = vals::Iophen::ENABLED; @@ -17,4 +580,16 @@ pub unsafe fn init(config: Config) { w.set_iopeen(enabled); w.set_iophen(enabled); }); + + let r = rcc.freeze(config); + + rcc.apb1enr().modify(|w| w.set_tim2en(Lptimen::ENABLED)); + rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); + rcc.apb1rstr().modify(|w| w.set_tim2rst(false)); + + Clock::new( + ::steal(), + interrupt::take!(TIM2), + r.clocks.apb1_clk(), + ) } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 59938e7bf..9b8c66331 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -6,8 +6,10 @@ cfg_if::cfg_if! { mod l0; pub use l0::*; } else { + pub type SystemClock = (); #[derive(Default)] pub struct Config {} - pub fn init(_config: Config) {} + pub unsafe fn init(_config: Config) -> SystemClock { + } } } From ea67940743733bbef1d758934bb01b4e8b0be136 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 13:08:14 +0200 Subject: [PATCH 02/11] Refactor --- embassy-stm32/src/rcc/l0/mod.rs | 88 ++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index 6c89022b8..8fbd6038e 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -1,7 +1,7 @@ use crate::clock::Clock; use crate::interrupt; use crate::pac; -use crate::pac::peripherals::{self, TIM2}; +use crate::pac::peripherals::{self, RCC, TIM2}; use crate::time::Hertz; use crate::time::U32Ext; use pac::rcc::vals; @@ -195,7 +195,6 @@ impl Config { /// RCC peripheral pub struct Rcc { clocks: Clocks, - rb: pac::rcc::Rcc, } /* @@ -267,38 +266,47 @@ impl Rcc { /// Extension trait that freezes the `RCC` peripheral with provided clocks configuration pub trait RccExt { - unsafe fn freeze(self, config: Config) -> Rcc; + fn freeze(self, config: Config) -> Rcc; } -impl RccExt for pac::rcc::Rcc { +impl RccExt for RCC { // `cfgr` is almost always a constant, so make sure it can be constant-propagated properly by // marking this function and all `Config` constructors and setters as `#[inline]`. // This saves ~900 Bytes for the `pwr.rs` example. #[inline] - unsafe fn freeze(self, cfgr: Config) -> Rcc { + fn freeze(self, cfgr: Config) -> Rcc { + let rcc = pac::RCC; let (sys_clk, sw) = match cfgr.mux { ClockSrc::MSI(range) => { // Set MSI range - self.icscr().write(|w| w.set_msirange(range.into())); + unsafe { + rcc.icscr().write(|w| w.set_msirange(range.into())); + } // Enable MSI - self.cr().write(|w| w.set_msion(Pllon::ENABLED)); - while !self.cr().read().msirdy() {} + unsafe { + rcc.cr().write(|w| w.set_msion(Pllon::ENABLED)); + while !rcc.cr().read().msirdy() {} + } let freq = 32_768 * (1 << (range as u8 + 1)); (freq, Sw::MSI) } ClockSrc::HSI16 => { // Enable HSI16 - self.cr().write(|w| w.set_hsi16on(Pllon::ENABLED)); - while !self.cr().read().hsi16rdyf() {} + unsafe { + rcc.cr().write(|w| w.set_hsi16on(Pllon::ENABLED)); + while !rcc.cr().read().hsi16rdyf() {} + } (HSI_FREQ, Sw::HSI16) } ClockSrc::HSE(freq) => { // Enable HSE - self.cr().write(|w| w.set_hseon(Pllon::ENABLED)); - while !self.cr().read().hserdy() {} + unsafe { + rcc.cr().write(|w| w.set_hseon(Pllon::ENABLED)); + while !rcc.cr().read().hserdy() {} + } (freq.0, Sw::HSE) } @@ -306,21 +314,27 @@ impl RccExt for pac::rcc::Rcc { let freq = match src { PLLSource::HSE(freq) => { // Enable HSE - self.cr().write(|w| w.set_hseon(Pllon::ENABLED)); - while !self.cr().read().hserdy() {} + unsafe { + rcc.cr().write(|w| w.set_hseon(Pllon::ENABLED)); + while !rcc.cr().read().hserdy() {} + } freq.0 } PLLSource::HSI16 => { // Enable HSI - self.cr().write(|w| w.set_hsi16on(Pllon::ENABLED)); - while !self.cr().read().hsi16rdyf() {} + unsafe { + rcc.cr().write(|w| w.set_hsi16on(Pllon::ENABLED)); + while !rcc.cr().read().hsi16rdyf() {} + } HSI_FREQ } }; // Disable PLL - self.cr().modify(|w| w.set_pllon(Pllon::DISABLED)); - while self.cr().read().pllrdy() {} + unsafe { + rcc.cr().modify(|w| w.set_pllon(Pllon::DISABLED)); + while rcc.cr().read().pllrdy() {} + } let freq = match mul { PLLMul::Mul3 => freq * 3, @@ -341,26 +355,30 @@ impl RccExt for pac::rcc::Rcc { }; assert!(freq <= 32_u32.mhz().0); - self.cfgr().write(move |w| { - w.set_pllmul(mul.into()); - w.set_plldiv(div.into()); - w.set_pllsrc(src.into()); - }); + unsafe { + rcc.cfgr().write(move |w| { + w.set_pllmul(mul.into()); + w.set_plldiv(div.into()); + w.set_pllsrc(src.into()); + }); - // Enable PLL - self.cr().modify(|w| w.set_pllon(Pllon::ENABLED)); - while !self.cr().read().pllrdy() {} + // Enable PLL + rcc.cr().modify(|w| w.set_pllon(Pllon::ENABLED)); + while !rcc.cr().read().pllrdy() {} + } (freq, Sw::PLL) } }; - self.cfgr().modify(|w| { - w.set_sw(sw.into()); - w.set_hpre(cfgr.ahb_pre.into()); - w.set_ppre(0, cfgr.apb1_pre.into()); - w.set_ppre(1, cfgr.apb2_pre.into()); - }); + unsafe { + rcc.cfgr().modify(|w| { + w.set_sw(sw.into()); + w.set_hpre(cfgr.ahb_pre.into()); + w.set_ppre(0, cfgr.apb1_pre.into()); + w.set_ppre(1, cfgr.apb2_pre.into()); + }); + } let ahb_freq: u32 = match cfgr.ahb_pre { AHBPrescaler::NotDivided => sys_clk, @@ -403,7 +421,7 @@ impl RccExt for pac::rcc::Rcc { apb2_pre, }; - Rcc { rb: self, clocks } + Rcc { clocks } } } @@ -570,7 +588,6 @@ pub type SystemClock = Clock; pub unsafe fn init(config: Config) -> SystemClock { let rcc = pac::RCC; - let enabled = vals::Iophen::ENABLED; rcc.iopenr().write(|w| { w.set_iopaen(enabled); @@ -581,7 +598,8 @@ pub unsafe fn init(config: Config) -> SystemClock { w.set_iophen(enabled); }); - let r = rcc.freeze(config); + let r = ::steal(); + let r = r.freeze(config); rcc.apb1enr().modify(|w| w.set_tim2en(Lptimen::ENABLED)); rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); From 9a21d742734a225f08762c6367b24af364de23c4 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 13:08:55 +0200 Subject: [PATCH 03/11] Remove debug code --- embassy-macros/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index f69c39701..3dc295fc1 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -350,13 +350,6 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { #[cortex_m_rt::entry] fn main() -> ! { - rtt_init_print!(); - unsafe { - log::set_logger_racy(&LOGGER).unwrap(); - } - - log::set_max_level(log::LevelFilter::Trace); - log::info!("Hello World!"); unsafe fn make_static(t: &mut T) -> &'static mut T { ::core::mem::transmute(t) } From 9743c59ad48996c4c53f0bfdfc8070b67e513ff0 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 13:29:11 +0200 Subject: [PATCH 04/11] Simplify --- embassy-stm32/src/rcc/l0/mod.rs | 175 +++++++++++++++----------------- 1 file changed, 84 insertions(+), 91 deletions(-) diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index 8fbd6038e..c756fad10 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -103,6 +103,83 @@ pub enum PLLSource { /// HSI speed pub const HSI_FREQ: u32 = 16_000_000; +impl Into for PLLMul { + fn into(self) -> Pllmul { + match self { + PLLMul::Mul3 => Pllmul::MUL3, + PLLMul::Mul4 => Pllmul::MUL4, + PLLMul::Mul6 => Pllmul::MUL6, + PLLMul::Mul8 => Pllmul::MUL8, + PLLMul::Mul12 => Pllmul::MUL12, + PLLMul::Mul16 => Pllmul::MUL16, + PLLMul::Mul24 => Pllmul::MUL24, + PLLMul::Mul32 => Pllmul::MUL32, + PLLMul::Mul48 => Pllmul::MUL48, + } + } +} + +impl Into for PLLDiv { + fn into(self) -> Plldiv { + match self { + PLLDiv::Div2 => Plldiv::DIV2, + PLLDiv::Div3 => Plldiv::DIV3, + PLLDiv::Div4 => Plldiv::DIV4, + } + } +} + +impl Into for PLLSource { + fn into(self) -> Pllsrc { + match self { + PLLSource::HSI16 => Pllsrc::HSI16, + PLLSource::HSE(_) => Pllsrc::HSE, + } + } +} + +impl Into for APBPrescaler { + fn into(self) -> Ppre { + match self { + APBPrescaler::NotDivided => Ppre::DIV1, + APBPrescaler::Div2 => Ppre::DIV2, + APBPrescaler::Div4 => Ppre::DIV4, + APBPrescaler::Div8 => Ppre::DIV8, + APBPrescaler::Div16 => Ppre::DIV16, + } + } +} + +impl Into for AHBPrescaler { + fn into(self) -> Hpre { + match self { + AHBPrescaler::NotDivided => Hpre::DIV1, + AHBPrescaler::Div2 => Hpre::DIV2, + AHBPrescaler::Div4 => Hpre::DIV4, + AHBPrescaler::Div8 => Hpre::DIV8, + AHBPrescaler::Div16 => Hpre::DIV16, + AHBPrescaler::Div64 => Hpre::DIV64, + AHBPrescaler::Div128 => Hpre::DIV128, + AHBPrescaler::Div256 => Hpre::DIV256, + AHBPrescaler::Div512 => Hpre::DIV512, + } + } +} + +impl Into for MSIRange { + fn into(self) -> Msirange { + match self { + MSIRange::Range0 => Msirange::RANGE0, + MSIRange::Range1 => Msirange::RANGE1, + MSIRange::Range2 => Msirange::RANGE2, + MSIRange::Range3 => Msirange::RANGE3, + MSIRange::Range4 => Msirange::RANGE4, + MSIRange::Range5 => Msirange::RANGE5, + MSIRange::Range6 => Msirange::RANGE6, + } + } +} + /// Clocks configutation pub struct Config { mux: ClockSrc, @@ -192,11 +269,6 @@ impl Config { } } -/// RCC peripheral -pub struct Rcc { - clocks: Clocks, -} - /* impl Rcc { pub fn enable_lse(&mut self, _: &PWR) -> LSE { @@ -266,7 +338,7 @@ impl Rcc { /// Extension trait that freezes the `RCC` peripheral with provided clocks configuration pub trait RccExt { - fn freeze(self, config: Config) -> Rcc; + fn freeze(&mut self, config: Config) -> Clocks; } impl RccExt for RCC { @@ -274,7 +346,7 @@ impl RccExt for RCC { // marking this function and all `Config` constructors and setters as `#[inline]`. // This saves ~900 Bytes for the `pwr.rs` example. #[inline] - fn freeze(self, cfgr: Config) -> Rcc { + fn freeze(&mut self, cfgr: Config) -> Clocks { let rcc = pac::RCC; let (sys_clk, sw) = match cfgr.mux { ClockSrc::MSI(range) => { @@ -409,7 +481,7 @@ impl RccExt for RCC { } }; - let clocks = Clocks { + Clocks { source: cfgr.mux, sys_clk: sys_clk.hz(), ahb_clk: ahb_freq.hz(), @@ -419,9 +491,7 @@ impl RccExt for RCC { apb2_tim_clk: apb2_tim_freq.hz(), apb1_pre, apb2_pre, - }; - - Rcc { clocks } + } } } @@ -506,83 +576,6 @@ pub struct MCOEnabled(()); #[derive(Clone, Copy)] pub struct LSE(()); -impl Into for PLLMul { - fn into(self) -> Pllmul { - match self { - PLLMul::Mul3 => Pllmul::MUL3, - PLLMul::Mul4 => Pllmul::MUL4, - PLLMul::Mul6 => Pllmul::MUL6, - PLLMul::Mul8 => Pllmul::MUL8, - PLLMul::Mul12 => Pllmul::MUL12, - PLLMul::Mul16 => Pllmul::MUL16, - PLLMul::Mul24 => Pllmul::MUL24, - PLLMul::Mul32 => Pllmul::MUL32, - PLLMul::Mul48 => Pllmul::MUL48, - } - } -} - -impl Into for PLLDiv { - fn into(self) -> Plldiv { - match self { - PLLDiv::Div2 => Plldiv::DIV2, - PLLDiv::Div3 => Plldiv::DIV3, - PLLDiv::Div4 => Plldiv::DIV4, - } - } -} - -impl Into for PLLSource { - fn into(self) -> Pllsrc { - match self { - PLLSource::HSI16 => Pllsrc::HSI16, - PLLSource::HSE(_) => Pllsrc::HSE, - } - } -} - -impl Into for APBPrescaler { - fn into(self) -> Ppre { - match self { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> Hpre { - match self { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - -impl Into for MSIRange { - fn into(self) -> Msirange { - match self { - MSIRange::Range0 => Msirange::RANGE0, - MSIRange::Range1 => Msirange::RANGE1, - MSIRange::Range2 => Msirange::RANGE2, - MSIRange::Range3 => Msirange::RANGE3, - MSIRange::Range4 => Msirange::RANGE4, - MSIRange::Range5 => Msirange::RANGE5, - MSIRange::Range6 => Msirange::RANGE6, - } - } -} - // We use TIM2 as SystemClock pub type SystemClock = Clock; @@ -598,8 +591,8 @@ pub unsafe fn init(config: Config) -> SystemClock { w.set_iophen(enabled); }); - let r = ::steal(); - let r = r.freeze(config); + let mut r = ::steal(); + let clocks = r.freeze(config); rcc.apb1enr().modify(|w| w.set_tim2en(Lptimen::ENABLED)); rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); @@ -608,6 +601,6 @@ pub unsafe fn init(config: Config) -> SystemClock { Clock::new( ::steal(), interrupt::take!(TIM2), - r.clocks.apb1_clk(), + clocks.apb1_clk(), ) } From f960f5b105977b78c7900b0992b97da4c190f8fa Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 13:55:25 +0200 Subject: [PATCH 05/11] Rework --- embassy-stm32/src/rcc/l0/mod.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index c756fad10..daa8431a6 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -4,6 +4,7 @@ use crate::pac; use crate::pac::peripherals::{self, RCC, TIM2}; use crate::time::Hertz; use crate::time::U32Ext; +use embassy::util::Unborrow; use pac::rcc::vals; use vals::{Hpre, Lptimen, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw}; @@ -269,8 +270,16 @@ impl Config { } } -/* +/// RCC peripheral +pub struct Rcc {} + impl Rcc { + pub fn new(_rcc: impl Unborrow + 'static) -> Self { + Self {} + } +} + +/* pub fn enable_lse(&mut self, _: &PWR) -> LSE { self.rb.csr.modify(|_, w| { // Enable LSE clock @@ -338,7 +347,7 @@ impl Rcc { /// Extension trait that freezes the `RCC` peripheral with provided clocks configuration pub trait RccExt { - fn freeze(&mut self, config: Config) -> Clocks; + fn freeze(self, config: Config) -> Clocks; } impl RccExt for RCC { @@ -346,7 +355,7 @@ impl RccExt for RCC { // marking this function and all `Config` constructors and setters as `#[inline]`. // This saves ~900 Bytes for the `pwr.rs` example. #[inline] - fn freeze(&mut self, cfgr: Config) -> Clocks { + fn freeze(self, cfgr: Config) -> Clocks { let rcc = pac::RCC; let (sys_clk, sw) = match cfgr.mux { ClockSrc::MSI(range) => { From a06664bd3e5a5085c80aafe151cd437aa5d3e251 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 20:12:54 +0200 Subject: [PATCH 06/11] Update init use --- embassy-stm32-examples/src/bin/blinky.rs | 2 +- embassy-stm32-examples/src/bin/button.rs | 2 +- embassy-stm32-examples/src/bin/button_exti.rs | 2 +- embassy-stm32-examples/src/bin/spi.rs | 2 +- embassy-stm32-examples/src/bin/usart.rs | 2 +- embassy-stm32-examples/src/bin/usart_dma.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32-examples/src/bin/blinky.rs b/embassy-stm32-examples/src/bin/blinky.rs index 7590764d8..5b46be14b 100644 --- a/embassy-stm32-examples/src/bin/blinky.rs +++ b/embassy-stm32-examples/src/bin/blinky.rs @@ -38,7 +38,7 @@ fn main() -> ! { w }); - let p = embassy_stm32::init(Default::default()); + let (p, _) = embassy_stm32::init(Default::default()); let mut led = Output::new(p.PB7, Level::High); diff --git a/embassy-stm32-examples/src/bin/button.rs b/embassy-stm32-examples/src/bin/button.rs index 1ee99f527..db67b13c3 100644 --- a/embassy-stm32-examples/src/bin/button.rs +++ b/embassy-stm32-examples/src/bin/button.rs @@ -38,7 +38,7 @@ fn main() -> ! { w }); - let p = embassy_stm32::init(Default::default()); + let (p, _) = embassy_stm32::init(Default::default()); let button = Input::new(p.PC13, Pull::Down); let mut led1 = Output::new(p.PB0, Level::High); diff --git a/embassy-stm32-examples/src/bin/button_exti.rs b/embassy-stm32-examples/src/bin/button_exti.rs index 8fc889dad..8276f1c4f 100644 --- a/embassy-stm32-examples/src/bin/button_exti.rs +++ b/embassy-stm32-examples/src/bin/button_exti.rs @@ -21,7 +21,7 @@ use stm32f4::stm32f429 as pac; #[embassy::task] async fn main_task() { - let p = embassy_stm32::init(Default::default()); + let (p, _) = embassy_stm32::init(Default::default()); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/embassy-stm32-examples/src/bin/spi.rs b/embassy-stm32-examples/src/bin/spi.rs index af0d57412..5fd37beaf 100644 --- a/embassy-stm32-examples/src/bin/spi.rs +++ b/embassy-stm32-examples/src/bin/spi.rs @@ -47,7 +47,7 @@ fn main() -> ! { w }); - let p = embassy_stm32::init(Default::default()); + let (p, _) = embassy_stm32::init(Default::default()); let mut spi = Spi::new( Hertz(16_000_000), diff --git a/embassy-stm32-examples/src/bin/usart.rs b/embassy-stm32-examples/src/bin/usart.rs index f7b66f86b..8b135d2aa 100644 --- a/embassy-stm32-examples/src/bin/usart.rs +++ b/embassy-stm32-examples/src/bin/usart.rs @@ -20,7 +20,7 @@ use stm32f4::stm32f429 as pac; #[embassy::task] async fn main_task() { - let p = embassy_stm32::init(Default::default()); + let (p, _) = embassy_stm32::init(Default::default()); let config = Config::default(); let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); diff --git a/embassy-stm32-examples/src/bin/usart_dma.rs b/embassy-stm32-examples/src/bin/usart_dma.rs index dc065e044..0127e9a00 100644 --- a/embassy-stm32-examples/src/bin/usart_dma.rs +++ b/embassy-stm32-examples/src/bin/usart_dma.rs @@ -20,7 +20,7 @@ use stm32f4::stm32f429 as pac; #[embassy::task] async fn main_task() { - let mut p = embassy_stm32::init(Default::default()); + let (mut p, _) = embassy_stm32::init(Default::default()); let config = Config::default(); let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); From aaab7d87a555a590ff72ff34af9901b8837900e4 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 20:42:11 +0200 Subject: [PATCH 07/11] Revert "Update init use" This reverts commit a06664bd3e5a5085c80aafe151cd437aa5d3e251. --- embassy-stm32-examples/src/bin/blinky.rs | 2 +- embassy-stm32-examples/src/bin/button.rs | 2 +- embassy-stm32-examples/src/bin/button_exti.rs | 2 +- embassy-stm32-examples/src/bin/spi.rs | 2 +- embassy-stm32-examples/src/bin/usart.rs | 2 +- embassy-stm32-examples/src/bin/usart_dma.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32-examples/src/bin/blinky.rs b/embassy-stm32-examples/src/bin/blinky.rs index 5b46be14b..7590764d8 100644 --- a/embassy-stm32-examples/src/bin/blinky.rs +++ b/embassy-stm32-examples/src/bin/blinky.rs @@ -38,7 +38,7 @@ fn main() -> ! { w }); - let (p, _) = embassy_stm32::init(Default::default()); + let p = embassy_stm32::init(Default::default()); let mut led = Output::new(p.PB7, Level::High); diff --git a/embassy-stm32-examples/src/bin/button.rs b/embassy-stm32-examples/src/bin/button.rs index db67b13c3..1ee99f527 100644 --- a/embassy-stm32-examples/src/bin/button.rs +++ b/embassy-stm32-examples/src/bin/button.rs @@ -38,7 +38,7 @@ fn main() -> ! { w }); - let (p, _) = embassy_stm32::init(Default::default()); + let p = embassy_stm32::init(Default::default()); let button = Input::new(p.PC13, Pull::Down); let mut led1 = Output::new(p.PB0, Level::High); diff --git a/embassy-stm32-examples/src/bin/button_exti.rs b/embassy-stm32-examples/src/bin/button_exti.rs index 8276f1c4f..8fc889dad 100644 --- a/embassy-stm32-examples/src/bin/button_exti.rs +++ b/embassy-stm32-examples/src/bin/button_exti.rs @@ -21,7 +21,7 @@ use stm32f4::stm32f429 as pac; #[embassy::task] async fn main_task() { - let (p, _) = embassy_stm32::init(Default::default()); + let p = embassy_stm32::init(Default::default()); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/embassy-stm32-examples/src/bin/spi.rs b/embassy-stm32-examples/src/bin/spi.rs index 5fd37beaf..af0d57412 100644 --- a/embassy-stm32-examples/src/bin/spi.rs +++ b/embassy-stm32-examples/src/bin/spi.rs @@ -47,7 +47,7 @@ fn main() -> ! { w }); - let (p, _) = embassy_stm32::init(Default::default()); + let p = embassy_stm32::init(Default::default()); let mut spi = Spi::new( Hertz(16_000_000), diff --git a/embassy-stm32-examples/src/bin/usart.rs b/embassy-stm32-examples/src/bin/usart.rs index 8b135d2aa..f7b66f86b 100644 --- a/embassy-stm32-examples/src/bin/usart.rs +++ b/embassy-stm32-examples/src/bin/usart.rs @@ -20,7 +20,7 @@ use stm32f4::stm32f429 as pac; #[embassy::task] async fn main_task() { - let (p, _) = embassy_stm32::init(Default::default()); + let p = embassy_stm32::init(Default::default()); let config = Config::default(); let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); diff --git a/embassy-stm32-examples/src/bin/usart_dma.rs b/embassy-stm32-examples/src/bin/usart_dma.rs index 0127e9a00..dc065e044 100644 --- a/embassy-stm32-examples/src/bin/usart_dma.rs +++ b/embassy-stm32-examples/src/bin/usart_dma.rs @@ -20,7 +20,7 @@ use stm32f4::stm32f429 as pac; #[embassy::task] async fn main_task() { - let (mut p, _) = embassy_stm32::init(Default::default()); + let mut p = embassy_stm32::init(Default::default()); let config = Config::default(); let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); From bfa999a2e0e9ef7ef8984ac213d73bda004320cd Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 21:42:07 +0200 Subject: [PATCH 08/11] Assume tim2 in macro and remove clock setup in chip specific rcc init Add temporary start_tim2() fn to Clock to assist macro in starting embassy clock --- embassy-macros/src/chip/stm32.rs | 8 +++++-- embassy-stm32/src/clock.rs | 38 +++++++++++++++++++++++++++----- embassy-stm32/src/lib.rs | 7 +++--- embassy-stm32/src/rcc/h7/mod.rs | 3 +-- embassy-stm32/src/rcc/l0/mod.rs | 19 +++++----------- embassy-stm32/src/rcc/mod.rs | 1 - 6 files changed, 48 insertions(+), 28 deletions(-) diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs index 71eb98905..274560a03 100644 --- a/embassy-macros/src/chip/stm32.rs +++ b/embassy-macros/src/chip/stm32.rs @@ -9,10 +9,14 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream quote!( use #embassy_stm32_path::{interrupt, peripherals, clock::Clock, time::Hertz}; - let (p, mut c) = #embassy_stm32_path::init(#config); + let p = #embassy_stm32_path::init(#config); + let mut c = Clock::new( + unsafe { ::steal() }, + interrupt::take!(TIM2), + ); let clock = unsafe { make_static(&mut c) }; - clock.start(); + clock.start_tim2(); let mut alarm = clock.alarm1(); unsafe { #embassy_path::time::set_clock(clock) }; diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs index 2ae0a3ba0..70679c141 100644 --- a/embassy-stm32/src/clock.rs +++ b/embassy-stm32/src/clock.rs @@ -33,6 +33,20 @@ fn calc_now(period: u32, counter: u16) -> u64 { ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) } +static mut CLOCK_FREQS: Option = None; + +#[derive(Copy, Clone)] +pub struct ClockFreqs { + pub tim2: Hertz, +} + +/// Sets the clock frequencies +/// +/// Safety: Sets a mutable global. +pub unsafe fn set_freqs(freqs: ClockFreqs) { + CLOCK_FREQS.replace(freqs); +} + struct AlarmState { timestamp: Cell, #[allow(clippy::type_complexity)] @@ -59,8 +73,6 @@ const ALARM_COUNT: usize = 3; pub struct Clock { _inner: T, irq: T::Interrupt, - /// Clock frequency - frequency: Hertz, /// Number of 2^23 periods elapsed since boot. period: AtomicU32, /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. @@ -68,23 +80,37 @@ pub struct Clock { } impl Clock { - pub fn new(peripheral: T, irq: T::Interrupt, frequency: Hertz) -> Self { + pub fn new(peripheral: T, irq: T::Interrupt) -> Self { Self { _inner: peripheral, irq, - frequency, period: AtomicU32::new(0), alarms: Mutex::new([AlarmState::new(), AlarmState::new(), AlarmState::new()]), } } - pub fn start(&'static self) { + // TODO: Temporary until clock code generation is in place + pub fn start_tim2(&'static self) { + #[cfg(feature = "_stm32l0")] + unsafe { + let rcc = crate::pac::RCC; + rcc.apb1enr() + .modify(|w| w.set_tim2en(crate::pac::rcc::vals::Lptimen::ENABLED)); + rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); + rcc.apb1rstr().modify(|w| w.set_tim2rst(false)); + } + + let timer_freq = unsafe { CLOCK_FREQS.unwrap().tim2 }; + self.start(timer_freq); + } + + pub fn start(&'static self, timer_freq: Hertz) { let inner = T::inner(); // NOTE(unsafe) Critical section to use the unsafe methods critical_section::with(|_| { unsafe { - inner.prepare(self.frequency); + inner.prepare(timer_freq); } self.irq.set_handler_context(self as *const _ as *mut _); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index a1fa22111..49ead8506 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -36,7 +36,6 @@ pub mod time; pub use embassy_macros::interrupt; pub use pac::{interrupt, peripherals, Peripherals}; -pub use rcc::SystemClock; // workaround for svd2rust-generated code using `use crate::generic::*;` pub(crate) use pac::regs::generic; @@ -61,12 +60,14 @@ impl Default for Config { } /// Initialize embassy. -pub fn init(config: Config) -> (Peripherals, SystemClock) { +pub fn init(config: Config) -> Peripherals { let p = Peripherals::take(); unsafe { dma::init(); pac::init_exti(); - (p, rcc::init(config.rcc)) + rcc::init(config.rcc); } + + p } diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7/mod.rs index 9a9c7ef0f..26d9f0bb9 100644 --- a/embassy-stm32/src/rcc/h7/mod.rs +++ b/embassy-stm32/src/rcc/h7/mod.rs @@ -529,5 +529,4 @@ impl<'d> Rcc<'d> { } // TODO -pub type SystemClock = (); -pub unsafe fn init(_config: Config) -> SystemClock {} +pub unsafe fn init(_config: Config) {} diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index daa8431a6..44e88d365 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -1,4 +1,5 @@ use crate::clock::Clock; +use crate::clock::{set_freqs, ClockFreqs}; use crate::interrupt; use crate::pac; use crate::pac::peripherals::{self, RCC, TIM2}; @@ -585,10 +586,7 @@ pub struct MCOEnabled(()); #[derive(Clone, Copy)] pub struct LSE(()); -// We use TIM2 as SystemClock -pub type SystemClock = Clock; - -pub unsafe fn init(config: Config) -> SystemClock { +pub unsafe fn init(config: Config) { let rcc = pac::RCC; let enabled = vals::Iophen::ENABLED; rcc.iopenr().write(|w| { @@ -602,14 +600,7 @@ pub unsafe fn init(config: Config) -> SystemClock { let mut r = ::steal(); let clocks = r.freeze(config); - - rcc.apb1enr().modify(|w| w.set_tim2en(Lptimen::ENABLED)); - rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); - rcc.apb1rstr().modify(|w| w.set_tim2rst(false)); - - Clock::new( - ::steal(), - interrupt::take!(TIM2), - clocks.apb1_clk(), - ) + set_freqs(ClockFreqs { + tim2: clocks.apb1_clk(), + }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 9b8c66331..2ede725a1 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -6,7 +6,6 @@ cfg_if::cfg_if! { mod l0; pub use l0::*; } else { - pub type SystemClock = (); #[derive(Default)] pub struct Config {} pub unsafe fn init(_config: Config) -> SystemClock { From 6eaf224fec205171019fa31407ea42cfd71ae5a1 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 26 May 2021 21:46:57 +0200 Subject: [PATCH 09/11] No more systemclock --- embassy-stm32/src/rcc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 2ede725a1..f15cee7f6 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -8,7 +8,7 @@ cfg_if::cfg_if! { } else { #[derive(Default)] pub struct Config {} - pub unsafe fn init(_config: Config) -> SystemClock { + pub unsafe fn init(_config: Config) { } } } From a41a8123456f29b00220ea474594255cc07f2ecf Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 27 May 2021 09:50:11 +0200 Subject: [PATCH 10/11] Move clocks to rcc mod --- embassy-stm32/src/clock.rs | 38 ++++++---------- embassy-stm32/src/rcc/l0/mod.rs | 78 +++------------------------------ embassy-stm32/src/rcc/mod.rs | 32 ++++++++++++++ 3 files changed, 51 insertions(+), 97 deletions(-) diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs index 70679c141..3ae83bbb0 100644 --- a/embassy-stm32/src/clock.rs +++ b/embassy-stm32/src/clock.rs @@ -10,6 +10,7 @@ use embassy::time::{Clock as EmbassyClock, TICKS_PER_SECOND}; use crate::interrupt::{CriticalSection, Interrupt, Mutex}; use crate::pac::timer::TimGp16; +use crate::rcc::get_freqs; use crate::time::Hertz; // Clock timekeeping works with something we call "periods", which are time intervals @@ -33,20 +34,6 @@ fn calc_now(period: u32, counter: u16) -> u64 { ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) } -static mut CLOCK_FREQS: Option = None; - -#[derive(Copy, Clone)] -pub struct ClockFreqs { - pub tim2: Hertz, -} - -/// Sets the clock frequencies -/// -/// Safety: Sets a mutable global. -pub unsafe fn set_freqs(freqs: ClockFreqs) { - CLOCK_FREQS.replace(freqs); -} - struct AlarmState { timestamp: Cell, #[allow(clippy::type_complexity)] @@ -91,17 +78,20 @@ impl Clock { // TODO: Temporary until clock code generation is in place pub fn start_tim2(&'static self) { - #[cfg(feature = "_stm32l0")] - unsafe { - let rcc = crate::pac::RCC; - rcc.apb1enr() - .modify(|w| w.set_tim2en(crate::pac::rcc::vals::Lptimen::ENABLED)); - rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); - rcc.apb1rstr().modify(|w| w.set_tim2rst(false)); - } + cfg_if::cfg_if! { + if #[cfg(feature = "_stm32l0")] { + unsafe { + let rcc = crate::pac::RCC; + rcc.apb1enr() + .modify(|w| w.set_tim2en(crate::pac::rcc::vals::Lptimen::ENABLED)); + rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); + rcc.apb1rstr().modify(|w| w.set_tim2rst(false)); + } - let timer_freq = unsafe { CLOCK_FREQS.unwrap().tim2 }; - self.start(timer_freq); + let timer_freq = unsafe { crate::rcc::get_freqs().apb1_clk }; + self.start(timer_freq); + } + } } pub fn start(&'static self, timer_freq: Hertz) { diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index 44e88d365..99055d906 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -1,13 +1,11 @@ -use crate::clock::Clock; -use crate::clock::{set_freqs, ClockFreqs}; -use crate::interrupt; use crate::pac; -use crate::pac::peripherals::{self, RCC, TIM2}; +use crate::pac::peripherals::{self, RCC}; +use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; use crate::time::U32Ext; use embassy::util::Unborrow; use pac::rcc::vals; -use vals::{Hpre, Lptimen, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw}; +use vals::{Hpre, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, /// and with the addition of the init function to configure a system clock. @@ -492,7 +490,6 @@ impl RccExt for RCC { }; Clocks { - source: cfgr.mux, sys_clk: sys_clk.hz(), ahb_clk: ahb_freq.hz(), apb1_clk: apb1_freq.hz(), @@ -505,69 +502,6 @@ impl RccExt for RCC { } } -/// Frozen clock frequencies -/// -/// The existence of this value indicates that the clock configuration can no longer be changed -#[derive(Clone, Copy)] -pub struct Clocks { - source: ClockSrc, - sys_clk: Hertz, - ahb_clk: Hertz, - apb1_clk: Hertz, - apb1_tim_clk: Hertz, - apb2_clk: Hertz, - apb2_tim_clk: Hertz, - apb1_pre: u8, - apb2_pre: u8, -} - -impl Clocks { - /// Returns the clock source - pub fn source(&self) -> &ClockSrc { - &self.source - } - - /// Returns the system (core) frequency - pub fn sys_clk(&self) -> Hertz { - self.sys_clk - } - - /// Returns the frequency of the AHB - pub fn ahb_clk(&self) -> Hertz { - self.ahb_clk - } - - /// Returns the frequency of the APB1 - pub fn apb1_clk(&self) -> Hertz { - self.apb1_clk - } - - /// Returns the frequency of the APB1 timers - pub fn apb1_tim_clk(&self) -> Hertz { - self.apb1_tim_clk - } - - /// Returns the prescaler of the APB1 - pub fn apb1_pre(&self) -> u8 { - self.apb1_pre - } - - /// Returns the frequency of the APB2 - pub fn apb2_clk(&self) -> Hertz { - self.apb2_clk - } - - /// Returns the frequency of the APB2 timers - pub fn apb2_tim_clk(&self) -> Hertz { - self.apb2_tim_clk - } - - /// Returns the prescaler of the APB2 - pub fn apb2_pre(&self) -> u8 { - self.apb2_pre - } -} - /// Token that exists only, if the HSI48 clock has been enabled /// /// You can get an instance of this struct by calling [`Rcc::enable_hsi48`]. @@ -598,9 +532,7 @@ pub unsafe fn init(config: Config) { w.set_iophen(enabled); }); - let mut r = ::steal(); + let r = ::steal(); let clocks = r.freeze(config); - set_freqs(ClockFreqs { - tim2: clocks.apb1_clk(), - }); + set_freqs(clocks); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index f15cee7f6..cb8780343 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,3 +1,35 @@ +use crate::time::Hertz; +use core::mem::MaybeUninit; + +/// Frozen clock frequencies +/// +/// The existence of this value indicates that the clock configuration can no longer be changed +#[derive(Clone, Copy)] +pub struct Clocks { + pub sys_clk: Hertz, + pub ahb_clk: Hertz, + pub apb1_clk: Hertz, + pub apb1_tim_clk: Hertz, + pub apb2_clk: Hertz, + pub apb2_tim_clk: Hertz, + pub apb1_pre: u8, + pub apb2_pre: u8, +} + +static mut CLOCK_FREQS: MaybeUninit = MaybeUninit::uninit(); + +/// Sets the clock frequencies +/// +/// Safety: Sets a mutable global. +pub unsafe fn set_freqs(freqs: Clocks) { + CLOCK_FREQS.as_mut_ptr().write(freqs); +} + +/// Safety: Reads a mutable global. +pub unsafe fn get_freqs() -> &'static Clocks { + &*CLOCK_FREQS.as_ptr() +} + cfg_if::cfg_if! { if #[cfg(feature = "_stm32h7")] { mod h7; From 3669eba561aa25c492e446c72899452e61e5a921 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 27 May 2021 10:01:40 +0200 Subject: [PATCH 11/11] Use builder --- embassy-stm32/src/lib.rs | 5 ++-- embassy-stm32/src/rcc/l0/mod.rs | 43 --------------------------------- 2 files changed, 3 insertions(+), 45 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 49ead8506..34f065165 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -46,8 +46,9 @@ pub struct Config { } impl Config { - pub fn new(rcc: rcc::Config) -> Self { - Self { rcc } + pub fn rcc(mut self, rcc: rcc::Config) -> Self { + self.rcc = rcc; + self } } diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index 99055d906..0cf3c2cb7 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -224,49 +224,6 @@ impl Config { self.apb2_pre = pre; self } - - #[inline] - pub fn hsi16() -> Config { - Config { - mux: ClockSrc::HSI16, - ahb_pre: AHBPrescaler::NotDivided, - apb1_pre: APBPrescaler::NotDivided, - apb2_pre: APBPrescaler::NotDivided, - } - } - - #[inline] - pub fn msi(range: MSIRange) -> Config { - Config { - mux: ClockSrc::MSI(range), - ahb_pre: AHBPrescaler::NotDivided, - apb1_pre: APBPrescaler::NotDivided, - apb2_pre: APBPrescaler::NotDivided, - } - } - - #[inline] - pub fn pll(pll_src: PLLSource, pll_mul: PLLMul, pll_div: PLLDiv) -> Config { - Config { - mux: ClockSrc::PLL(pll_src, pll_mul, pll_div), - ahb_pre: AHBPrescaler::NotDivided, - apb1_pre: APBPrescaler::NotDivided, - apb2_pre: APBPrescaler::NotDivided, - } - } - - #[inline] - pub fn hse(freq: T) -> Config - where - T: Into, - { - Config { - mux: ClockSrc::HSE(freq.into()), - ahb_pre: AHBPrescaler::NotDivided, - apb1_pre: APBPrescaler::NotDivided, - apb2_pre: APBPrescaler::NotDivided, - } - } } /// RCC peripheral