From 8b757e1aec6a82759c6df190e35a7ebc7d500ca3 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 8 Apr 2022 03:40:51 +0200 Subject: Add stm32wlexx support --- ci.sh | 1 + embassy-stm32/Cargo.toml | 15 ++++ embassy-stm32/src/exti.rs | 2 +- embassy-stm32/src/rcc/mod.rs | 9 +- embassy-stm32/src/rcc/wl.rs | 189 ++++++++++++++++++++++++++++++++++++++++++ embassy-stm32/src/rcc/wl5.rs | 189 ------------------------------------------ stm32-gen-features/src/lib.rs | 44 +--------- 7 files changed, 214 insertions(+), 235 deletions(-) create mode 100644 embassy-stm32/src/rcc/wl.rs delete mode 100644 embassy-stm32/src/rcc/wl5.rs diff --git a/ci.sh b/ci.sh index 8f375eb92..116b6a319 100755 --- a/ci.sh +++ b/ci.sh @@ -57,6 +57,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5ub,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 030782466..037d32751 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -26,6 +26,7 @@ flavors = [ { regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi" }, { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" }, { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" }, + { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf" }, { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" }, { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" }, { regex_feature = "stm32wl.*", target = "thumbv7em-none-eabi" }, @@ -1343,4 +1344,18 @@ stm32wl55jc-cm4 = [ "stm32-metapac/stm32wl55jc-cm4" ] stm32wl55jc-cm0p = [ "stm32-metapac/stm32wl55jc-cm0p" ] stm32wl55uc-cm4 = [ "stm32-metapac/stm32wl55uc-cm4" ] stm32wl55uc-cm0p = [ "stm32-metapac/stm32wl55uc-cm0p" ] +stm32wle4c8 = [ "stm32-metapac/stm32wle4c8" ] +stm32wle4cb = [ "stm32-metapac/stm32wle4cb" ] +stm32wle4cc = [ "stm32-metapac/stm32wle4cc" ] +stm32wle4j8 = [ "stm32-metapac/stm32wle4j8" ] +stm32wle4jb = [ "stm32-metapac/stm32wle4jb" ] +stm32wle4jc = [ "stm32-metapac/stm32wle4jc" ] +stm32wle5c8 = [ "stm32-metapac/stm32wle5c8" ] +stm32wle5cb = [ "stm32-metapac/stm32wle5cb" ] +stm32wle5cc = [ "stm32-metapac/stm32wle5cc" ] +stm32wle5j8 = [ "stm32-metapac/stm32wle5j8" ] +stm32wle5jb = [ "stm32-metapac/stm32wle5jb" ] +stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ] +stm32wle5u8 = [ "stm32-metapac/stm32wle5u8" ] +stm32wle5ub = [ "stm32-metapac/stm32wle5ub" ] # END GENERATED FEATURES diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 8858bb648..957a1ca55 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -371,7 +371,7 @@ pub(crate) unsafe fn init() { foreach_exti_irq!(enable_irq); - #[cfg(not(any(rcc_wb, rcc_wl5, rcc_f1)))] + #[cfg(not(any(rcc_wb, rcc_wl5, rcc_wle, rcc_f1)))] ::enable(); #[cfg(stm32f1)] ::enable(); diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 37ecf8fba..d0ae2fc79 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -18,7 +18,7 @@ use core::mem::MaybeUninit; #[cfg_attr(rcc_l5, path = "l5.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")] #[cfg_attr(rcc_wb, path = "wb.rs")] -#[cfg_attr(rcc_wl5, path = "wl5.rs")] +#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")] mod _version; pub use _version::*; @@ -33,7 +33,7 @@ pub struct Clocks { pub apb2: Hertz, #[cfg(not(rcc_g0))] pub apb2_tim: Hertz, - #[cfg(any(rcc_wl5, rcc_u5))] + #[cfg(any(rcc_wl5, rcc_wle, rcc_u5))] pub apb3: Hertz, #[cfg(any(rcc_h7, rcc_h7ab))] pub apb4: Hertz, @@ -42,11 +42,12 @@ pub struct Clocks { pub ahb1: Hertz, #[cfg(any( rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, - rcc_wl5 + rcc_wl5, rcc_wle ))] pub ahb2: Hertz, #[cfg(any( - rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5 + rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, + rcc_wl5, rcc_wle ))] pub ahb3: Hertz, #[cfg(any(rcc_h7, rcc_h7ab))] diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs new file mode 100644 index 000000000..fb2dd9986 --- /dev/null +++ b/embassy-stm32/src/rcc/wl.rs @@ -0,0 +1,189 @@ +use crate::pac::RCC; +use crate::rcc::{set_freqs, Clocks}; +use crate::time::U32Ext; + +/// 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. + +/// Only the basic setup using the HSE and HSI clocks are supported as of now. + +/// HSI speed +pub const HSI_FREQ: u32 = 16_000_000; + +pub const HSE32_FREQ: u32 = 32_000_000; + +/// System clock mux source +#[derive(Clone, Copy)] +pub enum ClockSrc { + HSE32, + HSI16, +} + +/// AHB prescaler +#[derive(Clone, Copy, PartialEq)] +pub enum AHBPrescaler { + NotDivided, + Div2, + Div3, + Div4, + Div5, + Div6, + Div8, + Div10, + Div16, + Div32, + Div64, + Div128, + Div256, + Div512, +} + +/// APB prescaler +#[derive(Clone, Copy)] +pub enum APBPrescaler { + NotDivided, + Div2, + Div4, + Div8, + Div16, +} + +impl Into for APBPrescaler { + fn into(self) -> u8 { + match self { + APBPrescaler::NotDivided => 1, + APBPrescaler::Div2 => 0x04, + APBPrescaler::Div4 => 0x05, + APBPrescaler::Div8 => 0x06, + APBPrescaler::Div16 => 0x07, + } + } +} + +impl Into for AHBPrescaler { + fn into(self) -> u8 { + match self { + AHBPrescaler::NotDivided => 1, + AHBPrescaler::Div2 => 0x08, + AHBPrescaler::Div3 => 0x01, + AHBPrescaler::Div4 => 0x09, + AHBPrescaler::Div5 => 0x02, + AHBPrescaler::Div6 => 0x05, + AHBPrescaler::Div8 => 0x0a, + AHBPrescaler::Div10 => 0x06, + AHBPrescaler::Div16 => 0x0b, + AHBPrescaler::Div32 => 0x07, + AHBPrescaler::Div64 => 0x0c, + AHBPrescaler::Div128 => 0x0d, + AHBPrescaler::Div256 => 0x0e, + AHBPrescaler::Div512 => 0x0f, + } + } +} + +/// Clocks configutation +pub struct Config { + pub mux: ClockSrc, + pub ahb_pre: AHBPrescaler, + pub apb1_pre: APBPrescaler, + pub apb2_pre: APBPrescaler, + pub enable_lsi: bool, +} + +impl Default for Config { + #[inline] + fn default() -> Config { + Config { + mux: ClockSrc::HSI16, + ahb_pre: AHBPrescaler::NotDivided, + apb1_pre: APBPrescaler::NotDivided, + apb2_pre: APBPrescaler::NotDivided, + enable_lsi: false, + } + } +} + +pub(crate) unsafe fn init(config: Config) { + let (sys_clk, sw) = match config.mux { + ClockSrc::HSI16 => { + // Enable HSI16 + RCC.cr().write(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + (HSI_FREQ, 0x01) + } + ClockSrc::HSE32 => { + // Enable HSE32 + RCC.cr().write(|w| { + w.set_hsebyppwr(true); + w.set_hseon(true); + }); + while !RCC.cr().read().hserdy() {} + + (HSE32_FREQ, 0x02) + } + }; + + RCC.cfgr().modify(|w| { + w.set_sw(sw.into()); + if config.ahb_pre == AHBPrescaler::NotDivided { + w.set_hpre(0); + } else { + w.set_hpre(config.ahb_pre.into()); + } + w.set_ppre1(config.apb1_pre.into()); + w.set_ppre2(config.apb2_pre.into()); + }); + + let ahb_freq: u32 = match config.ahb_pre { + AHBPrescaler::NotDivided => sys_clk, + pre => { + let pre: u8 = pre.into(); + let pre = 1 << (pre as u32 - 7); + sys_clk / pre + } + }; + + let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { + APBPrescaler::NotDivided => (ahb_freq, ahb_freq), + pre => { + let pre: u8 = pre.into(); + let pre: u8 = 1 << (pre - 3); + let freq = ahb_freq / pre as u32; + (freq, freq * 2) + } + }; + + let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { + APBPrescaler::NotDivided => (ahb_freq, ahb_freq), + pre => { + let pre: u8 = pre.into(); + let pre: u8 = 1 << (pre - 3); + let freq = ahb_freq / (1 << (pre as u8 - 3)); + (freq, freq * 2) + } + }; + + // TODO: completely untested + let apb3_freq = ahb_freq; + + if config.enable_lsi { + let csr = RCC.csr().read(); + if !csr.lsion() { + RCC.csr().modify(|w| w.set_lsion(true)); + while !RCC.csr().read().lsirdy() {} + } + } + + set_freqs(Clocks { + sys: sys_clk.hz(), + ahb1: ahb_freq.hz(), + ahb2: ahb_freq.hz(), + ahb3: ahb_freq.hz(), + apb1: apb1_freq.hz(), + apb2: apb2_freq.hz(), + apb3: apb3_freq.hz(), + apb1_tim: apb1_tim_freq.hz(), + apb2_tim: apb2_tim_freq.hz(), + }); +} diff --git a/embassy-stm32/src/rcc/wl5.rs b/embassy-stm32/src/rcc/wl5.rs deleted file mode 100644 index fb2dd9986..000000000 --- a/embassy-stm32/src/rcc/wl5.rs +++ /dev/null @@ -1,189 +0,0 @@ -use crate::pac::RCC; -use crate::rcc::{set_freqs, Clocks}; -use crate::time::U32Ext; - -/// 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. - -/// Only the basic setup using the HSE and HSI clocks are supported as of now. - -/// HSI speed -pub const HSI_FREQ: u32 = 16_000_000; - -pub const HSE32_FREQ: u32 = 32_000_000; - -/// System clock mux source -#[derive(Clone, Copy)] -pub enum ClockSrc { - HSE32, - HSI16, -} - -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div3, - Div4, - Div5, - Div6, - Div8, - Div10, - Div16, - Div32, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Into for APBPrescaler { - fn into(self) -> u8 { - match self { - APBPrescaler::NotDivided => 1, - APBPrescaler::Div2 => 0x04, - APBPrescaler::Div4 => 0x05, - APBPrescaler::Div8 => 0x06, - APBPrescaler::Div16 => 0x07, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> u8 { - match self { - AHBPrescaler::NotDivided => 1, - AHBPrescaler::Div2 => 0x08, - AHBPrescaler::Div3 => 0x01, - AHBPrescaler::Div4 => 0x09, - AHBPrescaler::Div5 => 0x02, - AHBPrescaler::Div6 => 0x05, - AHBPrescaler::Div8 => 0x0a, - AHBPrescaler::Div10 => 0x06, - AHBPrescaler::Div16 => 0x0b, - AHBPrescaler::Div32 => 0x07, - AHBPrescaler::Div64 => 0x0c, - AHBPrescaler::Div128 => 0x0d, - AHBPrescaler::Div256 => 0x0e, - AHBPrescaler::Div512 => 0x0f, - } - } -} - -/// Clocks configutation -pub struct Config { - pub mux: ClockSrc, - pub ahb_pre: AHBPrescaler, - pub apb1_pre: APBPrescaler, - pub apb2_pre: APBPrescaler, - pub enable_lsi: bool, -} - -impl Default for Config { - #[inline] - fn default() -> Config { - Config { - mux: ClockSrc::HSI16, - ahb_pre: AHBPrescaler::NotDivided, - apb1_pre: APBPrescaler::NotDivided, - apb2_pre: APBPrescaler::NotDivided, - enable_lsi: false, - } - } -} - -pub(crate) unsafe fn init(config: Config) { - let (sys_clk, sw) = match config.mux { - ClockSrc::HSI16 => { - // Enable HSI16 - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - (HSI_FREQ, 0x01) - } - ClockSrc::HSE32 => { - // Enable HSE32 - RCC.cr().write(|w| { - w.set_hsebyppwr(true); - w.set_hseon(true); - }); - while !RCC.cr().read().hserdy() {} - - (HSE32_FREQ, 0x02) - } - }; - - RCC.cfgr().modify(|w| { - w.set_sw(sw.into()); - if config.ahb_pre == AHBPrescaler::NotDivided { - w.set_hpre(0); - } else { - w.set_hpre(config.ahb_pre.into()); - } - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); - }); - - let ahb_freq: u32 = match config.ahb_pre { - AHBPrescaler::NotDivided => sys_clk, - pre => { - let pre: u8 = pre.into(); - let pre = 1 << (pre as u32 - 7); - sys_clk / pre - } - }; - - let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { - APBPrescaler::NotDivided => (ahb_freq, ahb_freq), - pre => { - let pre: u8 = pre.into(); - let pre: u8 = 1 << (pre - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) - } - }; - - let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { - APBPrescaler::NotDivided => (ahb_freq, ahb_freq), - pre => { - let pre: u8 = pre.into(); - let pre: u8 = 1 << (pre - 3); - let freq = ahb_freq / (1 << (pre as u8 - 3)); - (freq, freq * 2) - } - }; - - // TODO: completely untested - let apb3_freq = ahb_freq; - - if config.enable_lsi { - let csr = RCC.csr().read(); - if !csr.lsion() { - RCC.csr().modify(|w| w.set_lsion(true)); - while !RCC.csr().read().lsirdy() {} - } - } - - set_freqs(Clocks { - sys: sys_clk.hz(), - ahb1: ahb_freq.hz(), - ahb2: ahb_freq.hz(), - ahb3: ahb_freq.hz(), - apb1: apb1_freq.hz(), - apb2: apb2_freq.hz(), - apb3: apb3_freq.hz(), - apb1_tim: apb1_tim_freq.hz(), - apb2_tim: apb2_tim_freq.hz(), - }); -} diff --git a/stm32-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs index bef11c2ad..7aaad9da3 100644 --- a/stm32-gen-features/src/lib.rs +++ b/stm32-gen-features/src/lib.rs @@ -1,38 +1,11 @@ //! FIXME discuss about which errors to print and when to panic -use std::{iter::FilterMap, path::Path, slice::Iter}; - -const SUPPORTED_FAMILIES: &[&str] = &[ - "stm32f0", "stm32f1", "stm32f2", "stm32f3", "stm32f4", "stm32f7", "stm32g0", "stm32g4", - "stm32l0", "stm32l1", "stm32l4", "stm32l5", "stm32h7", "stm32u5", "stm32wb", "stm32wl5", -]; +use std::path::Path; const SEPARATOR_START: &str = "# BEGIN GENERATED FEATURES\n"; const SEPARATOR_END: &str = "# END GENERATED FEATURES\n"; const HELP: &str = "# Generated by stm32-gen-features. DO NOT EDIT.\n"; -/// True if the chip named `name` is supported else false -fn is_supported(name: &str) -> bool { - SUPPORTED_FAMILIES - .iter() - .any(|family| name.starts_with(family)) -} - -type SupportedIter<'a> = FilterMap< - Iter<'a, (String, Vec)>, - fn(&(String, Vec)) -> Option<(&String, &Vec)>, ->; -trait FilterSupported { - fn supported(&self) -> SupportedIter; -} -impl FilterSupported for &[(String, Vec)] { - /// Get a new Vec with only the supported chips - fn supported(&self) -> SupportedIter { - self.iter() - .filter_map(|(name, cores)| is_supported(name).then(|| (name, cores))) - } -} - /// Get the list of all the chips and their supported cores /// /// Print errors to `stderr` when something is returned by the glob but is not in the returned @@ -85,7 +58,7 @@ fn chip_cores(path: &Path) -> Vec { /// Panics if a file contains yaml syntax errors or if a value does not have a consistent type pub fn embassy_stm32_needed_data(names_and_cores: &[(String, Vec)]) -> String { let mut result = String::new(); - for (chip_name, cores) in names_and_cores.supported() { + for (chip_name, cores) in names_and_cores { if cores.len() > 1 { for core_name in cores.iter() { result += &format!( @@ -150,22 +123,11 @@ pub fn generate_cargo_toml_file(previous_text: &str, new_contents: &str) -> Stri mod tests { use super::*; - #[test] - fn stm32f407vg_is_supported() { - assert!(is_supported("stm32f407vg")) - } - - #[test] - fn abcdef_is_not_supported() { - assert!(!is_supported("abcdef")) - } - #[test] #[ignore] - fn stm32f407vg_yaml_file_exists_and_is_supported() { + fn stm32f407vg_yaml_file_exists() { assert!(chip_names_and_cores() .as_slice() - .supported() .into_iter() .any(|(name, _)| { name == "stm32f407vg" })) } -- cgit