From fa5038866fa942fec0129bd51991b1ffbac426f0 Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 16:13:57 +0800 Subject: [PATCH 1/9] feat: f072 basic examples and feature --- Cargo.toml | 1 + examples/py32f072/Cargo.toml | 46 ++++++++++++++++++++++++++++ examples/py32f072/build.rs | 10 ++++++ examples/py32f072/memory.x | 5 +++ examples/py32f072/src/bin/raw_rtt.rs | 20 ++++++++++++ 5 files changed, 82 insertions(+) create mode 100644 examples/py32f072/Cargo.toml create mode 100644 examples/py32f072/build.rs create mode 100644 examples/py32f072/memory.x create mode 100644 examples/py32f072/src/bin/raw_rtt.rs diff --git a/Cargo.toml b/Cargo.toml index d6df88f..602a5a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,6 +87,7 @@ exti = [] py32f030k28 = ["py32-metapac/py32f030k28"] py32f030f16 = ["py32-metapac/py32f030f16"] +py32f072c1b = ["py32-metapac/py32f072c1b"] # As of 2023-12-04, this driver is implemented using CC1 as the halfway rollover interrupt, and any # additional CC capabilities to provide timer alarms to embassy-time. embassy-time requires AT LEAST diff --git a/examples/py32f072/Cargo.toml b/examples/py32f072/Cargo.toml new file mode 100644 index 0000000..4ff9e9d --- /dev/null +++ b/examples/py32f072/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "py32f030-examples" +version = "0.1.0" +edition = "2021" + +[dependencies] +panic-halt = "1.0.0" +cortex-m = { version = "0.7.7", features = [ + "critical-section-single-core", + "critical-section", +] } +cortex-m-rt = "0.7.3" +cortex-m-semihosting = { version = "0.5" } +panic-probe = { version = "0.3", features = ["print-defmt"] } + +embassy-sync = { version = "0.6.0", features = ["defmt"] } +embassy-executor = { version = "0.6.1", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } + +embedded-io = { version = "0.6.0" } +embedded-io-async = { version = "0.6.1" } + +py32-hal = { path = "../../", features = [ "time-driver-tim3", "py32f072c1b"]} + +defmt = "0.3" +defmt-rtt = "0.4" + +# cargo build/run +[profile.dev] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 'z' # <- +overflow-checks = true # <- + +# cargo build/run --release +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- + diff --git a/examples/py32f072/build.rs b/examples/py32f072/build.rs new file mode 100644 index 0000000..4b3ca97 --- /dev/null +++ b/examples/py32f072/build.rs @@ -0,0 +1,10 @@ +fn main() { + // `--nmagic` is required if memory section addresses are not aligned to 0x10000, + // for example the FLASH and RAM sections in your `memory.x`. + // See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + println!("cargo:rustc-link-arg=--nmagic"); + + println!("cargo:rustc-link-arg=-Tlink.x"); + + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/py32f072/memory.x b/examples/py32f072/memory.x new file mode 100644 index 0000000..ce058eb --- /dev/null +++ b/examples/py32f072/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 128K /* BANK_1 */ + RAM : ORIGIN = 0x20000000, LENGTH = 16K +} \ No newline at end of file diff --git a/examples/py32f072/src/bin/raw_rtt.rs b/examples/py32f072/src/bin/raw_rtt.rs new file mode 100644 index 0000000..2b64227 --- /dev/null +++ b/examples/py32f072/src/bin/raw_rtt.rs @@ -0,0 +1,20 @@ +#![no_std] +#![no_main] + +use cortex_m_rt::entry; +use defmt::*; +use defmt_rtt as _; +use hal::pac; +use panic_halt as _; +use py32_hal as hal; + +#[entry] +fn main() -> ! { + info!("Hello World!"); + + loop { + info!("tick"); + + cortex_m::asm::delay(8_000_000); + } +} From d29828b1125e2522f0d3e1b0abb8ce8e9a8fb1e7 Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 16:14:36 +0800 Subject: [PATCH 2/9] feat: f072 RCC support --- src/rcc/{f030.rs => f0.rs} | 48 ++++++++++++++++++++++++++++++-------- src/rcc/mod.rs | 5 ++-- 2 files changed, 41 insertions(+), 12 deletions(-) rename src/rcc/{f030.rs => f0.rs} (87%) diff --git a/src/rcc/f030.rs b/src/rcc/f0.rs similarity index 87% rename from src/rcc/f030.rs rename to src/rcc/f0.rs index 90e32d1..d4f0688 100644 --- a/src/rcc/f030.rs +++ b/src/rcc/f0.rs @@ -2,6 +2,9 @@ use crate::pac::rcc::vals::Pllsrc; // pub use crate::pac::rcc::vals::Prediv as PllPreDiv; pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler, Sw as Sysclk, HsiFs, Hsidiv}; +#[cfg(rcc_f072)] +pub use crate::pac::rcc::vals::Pllmul as PllMul; + use crate::pac::{/* FLASH , */RCC}; use crate::time::Hertz; @@ -47,8 +50,9 @@ pub struct Pll { // /// On some chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. // pub prediv: PllPreDiv, - // /// PLL multiplication factor. - // pub mul: PllMul, + #[cfg(rcc_f072)] + /// PLL multiplication factor. + pub mul: PllMul, } /// Clocks configutation @@ -92,6 +96,8 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_hsion(true)); if let Some(value) = config.hsi { let val = value.0; + + #[cfg(rcc_f030)] let (fs_val, trim_addr): (HsiFs, usize) = match val { 4_000_000u32 => (HsiFs::HSI_4MHZ, 0x1FFF_0F00), 8_000_000u32 => (HsiFs::HSI_8MHZ, 0x1FFF_0F04), @@ -100,6 +106,16 @@ pub(crate) unsafe fn init(config: Config) { 24_000_000u32 => (HsiFs::HSI_24MHZ, 0x1FFF_0F10), _ => panic!("Unsupported HSI frequency"), }; + + #[cfg(rcc_f072)] + let (fs_val, trim_addr): (HsiFs, usize) = match val { + 4_000_000u32 => (HsiFs::HSI_4MHZ, 0x1FFF_3200), + 8_000_000u32 => (HsiFs::HSI_8MHZ, 0x1FFF_3208), + 16_000_000u32 => (HsiFs::HSI_16MHZ, 0x1FFF_3210), + 22_120_000u32 => (HsiFs::HSI_22_12MHZ, 0x1FFF_3218), + 24_000_000u32 => (HsiFs::HSI_24MHZ, 0x1FFF_3220), + _ => panic!("Unsupported HSI frequency"), + }; let trim_val = (unsafe { *(trim_addr as *const u32) } & 0x1FFF ) as u16; RCC.icscr().modify(|w| {w.set_hsi_fs(fs_val); w.set_hsi_trim(trim_val);}); }; @@ -140,14 +156,21 @@ pub(crate) unsafe fn init(config: Config) { PllSource::HSE => (Pllsrc::HSE, unwrap!(hse)), PllSource::HSI => (Pllsrc::HSI, unwrap!(hsi)), }; + #[cfg(rcc_f030)] let out_freq = src_freq * 2u8; + #[cfg(rcc_f072)] + let out_freq = src_freq * pll.mul; assert!(max::PLL_IN.contains(&src_freq)); // assert!(max::PLL_OUT.contains(&pll.src.out_freq(pll.mul))); RCC.cr().modify(|w| w.set_pllon(false)); while RCC.cr().read().pllrdy() {} - RCC.pllcfgr().modify(|w| w.set_pllsrc(src_val)); + RCC.pllcfgr().modify(|w| { + #[cfg(rcc_f072)] + w.set_pllmul(pll.mul); + w.set_pllsrc(src_val); + }); RCC.cr().modify(|w| w.set_pllon(true)); cortex_m::asm::delay(1_000); while !RCC.cr().read().pllrdy() {} @@ -197,14 +220,19 @@ pub(crate) unsafe fn init(config: Config) { // } // }); + + let latency: u32 = match hclk1.0 { + ..=24_000_000 => 0, + ..=48_000_000 => 1, + _ => 2, + }; // Temporarily: set flash latency - if hclk1.0 > 24_000_000 { - unsafe { - let acr_reg = 0x4002_2000 as *mut u32; - let value = acr_reg.read_volatile() | 0x1; - acr_reg.write_volatile(value); - } + unsafe { + let acr_reg = 0x4002_2000 as *mut u32; + let value = acr_reg.read_volatile() | latency; + acr_reg.write_volatile(value); } + // Set prescalers // CFGR has been written before (PLL, PLL48) don't overwrite these settings @@ -285,7 +313,7 @@ mod max { // pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(48_000_000); // pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(48_000_000); - // py32f030 + #[cfg(any(rcc_f030, rcc_f072))] pub(crate) const PLL_IN: RangeInclusive = Hertz(16_000_000)..=Hertz(24_000_000); // pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(48_000_000); } diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index 4882661..937c249 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -7,8 +7,9 @@ use crate::pac::RCC; pub use crate::_generated::mux; use crate::time::Hertz; -mod f030; -pub use f030::*; +#[cfg_attr(py32f0, path = "f0.rs")] +mod _version; +pub use _version::*; #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] From 6b05ea1f0184522ca326b7c24f24a0c4cd2cbc8d Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 16:15:04 +0800 Subject: [PATCH 3/9] example: add rcc_72mhz example --- examples/py32f072/src/bin/rcc_72mhz.rs | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 examples/py32f072/src/bin/rcc_72mhz.rs diff --git a/examples/py32f072/src/bin/rcc_72mhz.rs b/examples/py32f072/src/bin/rcc_72mhz.rs new file mode 100644 index 0000000..b92e791 --- /dev/null +++ b/examples/py32f072/src/bin/rcc_72mhz.rs @@ -0,0 +1,37 @@ +#![no_std] +#![no_main] +#![feature(impl_trait_in_assoc_type)] + +use defmt::*; +use py32_hal::gpio::{Level, Output, Speed}; +use py32_hal::rcc::{Pll, PllSource, Sysclk, PllMul}; +use py32_hal::time::Hertz; +use embassy_executor::Spawner; +use {defmt_rtt as _, panic_halt as _}; + + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut cfg: py32_hal::Config = Default::default(); + cfg.rcc.hsi = Some(Hertz::mhz(24)); + cfg.rcc.pll = Some(Pll { + src: PllSource::HSI, + mul: PllMul::MUL3, + }); + cfg.rcc.sys = Sysclk::PLL; + let p = py32_hal::init(cfg); + + info!("Hello World!"); + + let mut led = Output::new(p.PB2, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + cortex_m::asm::delay(8_000_000); + + info!("low"); + led.set_low(); + cortex_m::asm::delay(8_000_000); + } +} \ No newline at end of file From b6eced9a6b2fe78826cc3ecc9bcefb171a7e30d4 Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 17:00:40 +0800 Subject: [PATCH 4/9] feat: f072 tim-driver support --- Cargo.toml | 1 + build.rs | 33 ++++++------- examples/py32f072/Cargo.toml | 2 +- src/time_driver.rs | 93 ++++++++++++------------------------ 4 files changed, 48 insertions(+), 81 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 602a5a3..b02f722 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,6 +96,7 @@ py32f072c1b = ["py32-metapac/py32f072c1b"] time-driver-any = ["_time-driver"] time-driver-tim1 = ["_time-driver"] time-driver-tim3 = ["_time-driver"] +time-driver-tim15 = ["_time-driver"] _time-driver = [] diff --git a/build.rs b/build.rs index 9b1cfcf..72f7510 100644 --- a/build.rs +++ b/build.rs @@ -199,22 +199,19 @@ fn main() { let time_driver_singleton = match time_driver.as_ref().map(|x| x.as_ref()) { None => "", Some("tim1") => "TIM1", - // Some("tim2") => "TIM2", + Some("tim2") => "TIM2", Some("tim3") => "TIM3", - // Some("tim4") => "TIM4", - // Some("tim5") => "TIM5", - // Some("tim8") => "TIM8", - // Some("tim9") => "TIM9", - // Some("tim12") => "TIM12", - // Some("tim14") => "TIM14", - // Some("tim15") => "TIM15", - // Some("tim16") => "TIM16", - // Some("tim17") => "TIM17", - // Some("tim20") => "TIM20", - // Some("tim21") => "TIM21", - // Some("tim22") => "TIM22", - // Some("tim23") => "TIM23", - // Some("tim24") => "TIM24", + Some("tim4") => "TIM4", + Some("tim5") => "TIM5", + Some("tim8") => "TIM8", + Some("tim9") => "TIM9", + Some("tim12") => "TIM12", + Some("tim15") => "TIM15", + Some("tim20") => "TIM20", + Some("tim21") => "TIM21", + Some("tim22") => "TIM22", + Some("tim23") => "TIM23", + Some("tim24") => "TIM24", Some("any") => { // Order of TIM candidators: // 1. 2CH -> 2CH_CMP -> GP16 -> GP32 -> ADV @@ -228,9 +225,9 @@ fn main() { // ] [ // 2CH - // 2CH_CMP + "TIM15", // 2CH_CMP "TIM3", // GP16 - // GP32 + "TIM2", // GP32 "TIM1", //ADV ] .iter() @@ -243,7 +240,7 @@ fn main() { cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase())); } for tim in [ - "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", /*"tim14", "tim15", "tim16", "tim17",*/ "tim20", "tim21", "tim22", "tim23", + "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23", "tim24", ] { cfgs.declare(format!("time_driver_{}", tim)); diff --git a/examples/py32f072/Cargo.toml b/examples/py32f072/Cargo.toml index 4ff9e9d..35ed3a7 100644 --- a/examples/py32f072/Cargo.toml +++ b/examples/py32f072/Cargo.toml @@ -20,7 +20,7 @@ embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime embedded-io = { version = "0.6.0" } embedded-io-async = { version = "0.6.1" } -py32-hal = { path = "../../", features = [ "time-driver-tim3", "py32f072c1b"]} +py32-hal = { path = "../../", features = [ "time-driver-tim15", "py32f072c1b"]} defmt = "0.3" defmt-rtt = "0.4" diff --git a/src/time_driver.rs b/src/time_driver.rs index 1d0e520..dd346b2 100644 --- a/src/time_driver.rs +++ b/src/time_driver.rs @@ -29,49 +29,42 @@ use crate::{interrupt, peripherals}; // available after reserving CC1 for regular time keeping. For example, TIM2 has four CC registers: // CC1, CC2, CC3, and CC4, so it can provide ALARM_COUNT = 3. -// cfg_if::cfg_if! { -// if #[cfg(any(time_driver_tim14, time_driver_tim16, time_driver_tim17))] { -// const ALARM_COUNT: usize = 1; -// } else { -// const ALARM_COUNT: usize = 3; -// } -// } -const ALARM_COUNT: usize = 3; +cfg_if::cfg_if! { + if #[cfg(any(time_driver_tim15))] { + const ALARM_COUNT: usize = 1; + } else { + const ALARM_COUNT: usize = 3; + } +} #[cfg(time_driver_tim1)] type T = peripherals::TIM1; -// #[cfg(time_driver_tim2)] -// type T = peripherals::TIM2; +#[cfg(time_driver_tim2)] +type T = peripherals::TIM2; #[cfg(time_driver_tim3)] type T = peripherals::TIM3; -// #[cfg(time_driver_tim4)] -// type T = peripherals::TIM4; -// #[cfg(time_driver_tim5)] -// type T = peripherals::TIM5; -// #[cfg(time_driver_tim8)] -// type T = peripherals::TIM8; -// #[cfg(time_driver_tim9)] -// type T = peripherals::TIM9; -// #[cfg(time_driver_tim12)] -// type T = peripherals::TIM12; -// #[cfg(time_driver_tim14)] -// type T = peripherals::TIM14; -// #[cfg(time_driver_tim15)] -// type T = peripherals::TIM15; -// #[cfg(time_driver_tim16)] -// type T = peripherals::TIM16; -// #[cfg(time_driver_tim17)] -// type T = peripherals::TIM17; -// #[cfg(time_driver_tim20)] -// type T = peripherals::TIM20; -// #[cfg(time_driver_tim21)] -// type T = peripherals::TIM21; -// #[cfg(time_driver_tim22)] -// type T = peripherals::TIM22; -// #[cfg(time_driver_tim23)] -// type T = peripherals::TIM23; -// #[cfg(time_driver_tim24)] -// type T = peripherals::TIM24; +#[cfg(time_driver_tim4)] +type T = peripherals::TIM4; +#[cfg(time_driver_tim5)] +type T = peripherals::TIM5; +#[cfg(time_driver_tim8)] +type T = peripherals::TIM8; +#[cfg(time_driver_tim9)] +type T = peripherals::TIM9; +#[cfg(time_driver_tim12)] +type T = peripherals::TIM12; +#[cfg(time_driver_tim15)] +type T = peripherals::TIM15; +#[cfg(time_driver_tim20)] +type T = peripherals::TIM20; +#[cfg(time_driver_tim21)] +type T = peripherals::TIM21; +#[cfg(time_driver_tim22)] +type T = peripherals::TIM22; +#[cfg(time_driver_tim23)] +type T = peripherals::TIM23; +#[cfg(time_driver_tim24)] +type T = peripherals::TIM24; foreach_interrupt! { (TIM1, timer, $block:ident, CC, $irq:ident) => { @@ -154,14 +147,6 @@ foreach_interrupt! { DRIVER.on_interrupt() } }; - // (TIM14, timer, $block:ident, CC, $irq:ident) => { - // #[cfg(time_driver_tim14)] - // #[cfg(feature = "rt")] - // #[interrupt] - // fn $irq() { - // DRIVER.on_interrupt() - // } - // }; (TIM15, timer, $block:ident, CC, $irq:ident) => { #[cfg(time_driver_tim15)] #[cfg(feature = "rt")] @@ -170,22 +155,6 @@ foreach_interrupt! { DRIVER.on_interrupt() } }; - // (TIM16, timer, $block:ident, CC, $irq:ident) => { - // #[cfg(time_driver_tim16)] - // #[cfg(feature = "rt")] - // #[interrupt] - // fn $irq() { - // DRIVER.on_interrupt() - // } - // }; - // (TIM17, timer, $block:ident, CC, $irq:ident) => { - // #[cfg(time_driver_tim17)] - // #[cfg(feature = "rt")] - // #[interrupt] - // fn $irq() { - // DRIVER.on_interrupt() - // } - // }; (TIM20, timer, $block:ident, CC, $irq:ident) => { #[cfg(time_driver_tim20)] #[cfg(feature = "rt")] From c3f3074df5efe0a99e83786317d839d720905c62 Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 17:01:00 +0800 Subject: [PATCH 5/9] feat: bits32 timer --- src/timer/low_level.rs | 76 +++++++++++++++++++++--------------------- src/timer/mod.rs | 6 ++-- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/timer/low_level.rs b/src/timer/low_level.rs index cf34ec5..c9882fc 100644 --- a/src/timer/low_level.rs +++ b/src/timer/low_level.rs @@ -218,10 +218,10 @@ impl<'d, T: CoreInstance> Timer<'d, T> { unsafe { crate::pac::timer::TimCore::from_ptr(T::regs()) } } - // #[cfg(timer32bits)] - // fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 { - // unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } - // } + #[cfg(py32f072)] + fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 { + unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } + } /// Start the timer. pub fn start(&self) { @@ -266,23 +266,23 @@ impl<'d, T: CoreInstance> Timer<'d, T> { regs.egr().write(|r| r.set_ug(true)); regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } - // #[cfg(timer32bits)] - // TimerBits::Bits32 => { - // let pclk_ticks_per_timer_period = (timer_f / f) as u64; - // let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); - // let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); - - // // the timer counts `0..=arr`, we want it to count `0..divide_by` - // let arr: u32 = unwrap!(u32::try_from(divide_by - 1)); - - // let regs = self.regs_gp32_unchecked(); - // regs.psc().write_value(psc); - // regs.arr().write_value(arr); - - // regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - // regs.egr().write(|r| r.set_ug(true)); - // regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - // } + #[cfg(py32f072)] + TimerBits::Bits32 => { + let pclk_ticks_per_timer_period = (timer_f / f) as u64; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); + let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); + + // the timer counts `0..=arr`, we want it to count `0..divide_by` + let arr: u32 = unwrap!(u32::try_from(divide_by - 1)); + + let regs = self.regs_gp32_unchecked(); + regs.psc().write_value(psc); + regs.arr().write_value(arr); + + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); + } } } @@ -340,14 +340,14 @@ impl<'d, T: CoreInstance> Timer<'d, T> { timer_f / arr / (psc + 1) } - // #[cfg(timer32bits)] - // TimerBits::Bits32 => { - // let regs = self.regs_gp32_unchecked(); - // let arr = regs.arr().read(); - // let psc = regs.psc().read(); - - // timer_f / arr / (psc + 1) - // } + #[cfg(py32f072)] + TimerBits::Bits32 => { + let regs = self.regs_gp32_unchecked(); + let arr = regs.arr().read(); + let psc = regs.psc().read(); + + timer_f / arr / (psc + 1) + } } } @@ -411,8 +411,8 @@ impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { pub fn get_max_compare_value(&self) -> u32 { match T::BITS { TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, - // #[cfg(timer32bits)] - // TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), + #[cfg(py32f072)] + TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), } } } @@ -553,10 +553,10 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { let value = unwrap!(u16::try_from(value)); self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); } - // #[cfg(timer32bits)] - // TimerBits::Bits32 => { - // self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); - // } + #[cfg(py32f072)] + TimerBits::Bits32 => { + self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); + } } } @@ -564,8 +564,8 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { pub fn get_compare_value(&self, channel: Channel) -> u32 { match T::BITS { TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, - // #[cfg(timer32bits)] - // TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), + #[cfg(py32f072)] + TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), } } @@ -613,7 +613,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } } -// #[cfg(timer32bits)] +// #[cfg(py32f072)] // impl<'d, T: GeneralInstance32bit4Channel> Timer<'d, T> { // /// Get access to the general purpose 32bit timer registers. // /// diff --git a/src/timer/mod.rs b/src/timer/mod.rs index c9de12e..840bccf 100644 --- a/src/timer/mod.rs +++ b/src/timer/mod.rs @@ -46,9 +46,9 @@ impl Channel { pub enum TimerBits { /// 16 bits. Bits16, - // /// 32 bits. - // #[cfg(timer32bits)] - // Bits32, + #[cfg(py32f072)] + /// 32 bits. + Bits32, } struct State { From f91f706d4c7085db7438778f874eff6d9996b828 Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 17:01:32 +0800 Subject: [PATCH 6/9] example: add f072 blink example (embassy) --- examples/py32f072/src/bin/blinky.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 examples/py32f072/src/bin/blinky.rs diff --git a/examples/py32f072/src/bin/blinky.rs b/examples/py32f072/src/bin/blinky.rs new file mode 100644 index 0000000..5e4cdf3 --- /dev/null +++ b/examples/py32f072/src/bin/blinky.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] +#![feature(impl_trait_in_assoc_type)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_time::Timer; +use py32_hal::gpio::{Level, Output, Speed}; +use {defmt_rtt as _, panic_halt as _}; + +// main is itself an async function. +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = py32_hal::init(Default::default()); + info!("Hello World!"); + + let mut led = Output::new(p.PB2, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after_millis(1000).await; + + info!("low"); + led.set_low(); + Timer::after_millis(1000).await; + } +} From 989cce9aadf94d0490784594156e48886c4ec31d Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 17:13:40 +0800 Subject: [PATCH 7/9] docs: update readme --- README.md | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e0fdb58..18c6cc1 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,18 @@ Keypoints: - Embassy support - All-in-one metapac for peripheral register access, check [py32-data](https://github.com/py32-rs/py32-data) for more - All-in-one HAL crate, no need to create a new crate for each chip -- Async drivers, with async/await support, DMA (TODO)support +- Async drivers, with async/await support, DMA(TODO) support - Write once, run on all supported chips(should be) ## Supported Devices and Peripherals Currently, supported chips are listed in `Cargo.toml` as feature flags. -Supported chip flags: `py32f030f16`, `py32f030k28`, More is coming... +Supported chip flags: `py32f030f16`, `py32f030k28`, `py32f072c1b`, More is coming... + +Note: Currently the program behavior has nothing to do with chip packaging. + + others should work if you are careful as most peripherals are similar enough.In fact, the IPs of peripherals in different PY32 series may be consistent. Moreover, some series use the same die, so it might not require much work. @@ -41,18 +45,18 @@ For a full list of chip capabilities and peripherals, check the [py32-data](http | Family | F002B/L020/F001 | F030/F003/F002A | F040/F07x/MD410 | F403 | | ---------- | --------------- | --------------- | --------------- | ---- | -| Embassy | | ✅ | | | -| RCC | | ✅ | | | -| GPIO | | ✅ | | | -| INTERRUPT | | ✅ | | | +| Embassy | | ✅ | ✅ | | +| RCC | | ✅ | ✅ | | +| GPIO | | ✅ | ✅ | | +| INTERRUPT | | ✅ | ✅ | | | DMA | N/A | | | | -| EXTI | | ✅+ | | | -| USART | | ✅ | | | -| I2C | | ✅ | | | +| EXTI | | ✅+ | ❓ | | +| USART | | ✅ | ❓ | | +| I2C | | ✅ | ❓ | | | SPI | | | | | -| ADC | | ✅+ | | | +| ADC | | ✅+ | ❓ | | | RTC | | | | | -| Timer(PWM) | | ✅ | | | +| Timer(PWM) | | ✅ | ❓ | | | USB/OTG | N/A | N/A | | | - ✅ : Expected to work @@ -66,11 +70,17 @@ For a full list of chip capabilities and peripherals, check the [py32-data](http Too many... -- DMA Support (Channel Map, Codegen, API, RingBuffer, I2C...) +- DMA support (channel map, codegen, API, RingBuffer, I2C...) + +- Test F072 peripherals + +- HSE test and examples - Other series -- SPI, USART +- SPI, RTC + +- F072 TIM2(GP32) support - ... From 31fd8cfcd23b6059f6b8fe37899ce986f3e1741b Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 16:12:15 +0800 Subject: [PATCH 8/9] feat: chips, peripheral_versions cfgs generate --- build.rs | 109 +++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 60 deletions(-) diff --git a/build.rs b/build.rs index 72f7510..caea4ba 100644 --- a/build.rs +++ b/build.rs @@ -10,7 +10,7 @@ use quote::{format_ident, quote}; use py32_metapac::metadata::ir::BitOffset; use py32_metapac::metadata::{ MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, /*StopMode,*/ - // ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, + ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, }; @@ -43,12 +43,12 @@ fn main() { } } - // for &(kind, versions) in ALL_PERIPHERAL_VERSIONS.iter() { - // cfgs.declare(kind); - // for &version in versions.iter() { - // cfgs.declare(format!("{}_{}", kind, version)); - // } - // } + for &(kind, versions) in ALL_PERIPHERAL_VERSIONS.iter() { + cfgs.declare(kind); + for &version in versions.iter() { + cfgs.declare(format!("{}_{}", kind, version)); + } + } // ======== // Generate singletons @@ -561,7 +561,7 @@ fn main() { .unwrap() .byte_offset; let reg_offset: u8 = (reg_offset / 4).try_into().unwrap(); - + let bit_offset = &rcc_registers .ir .fieldsets @@ -1635,64 +1635,53 @@ fn main() { // ======== // Configs for multicore and for targeting groups of chips - // fn get_chip_cfgs(chip_name: &str) -> Vec { - // let mut cfgs = Vec::new(); + fn get_chip_cfgs(chip_name: &str) -> Vec { + let mut cfgs = Vec::new(); - // // Multicore + // Multicore - // let mut s = chip_name.split('_'); - // let mut chip_name: String = s.next().unwrap().to_string(); - // let core_name = if let Some(c) = s.next() { - // if !c.starts_with("CM") { - // chip_name.push('_'); - // chip_name.push_str(c); - // None - // } else { - // Some(c) - // } - // } else { - // None - // }; - - // if let Some(core) = core_name { - // cfgs.push(format!("{}_{}", &chip_name[..chip_name.len() - 2], core)); - // } + let mut s = chip_name.split('_'); + let mut chip_name: String = s.next().unwrap().to_string(); + let core_name = if let Some(c) = s.next() { + if !c.starts_with("CM") { + chip_name.push('_'); + chip_name.push_str(c); + None + } else { + Some(c) + } + } else { + None + }; - // // Configs for targeting groups of chips - // if &chip_name[..8] == "stm32wba" { - // cfgs.push(chip_name[..8].to_owned()); // stm32wba - // cfgs.push(chip_name[..10].to_owned()); // stm32wba52 - // cfgs.push(format!("package_{}", &chip_name[10..11])); - // cfgs.push(format!("flashsize_{}", &chip_name[11..12])); - // } else { - // if &chip_name[..8] == "stm32h7r" || &chip_name[..8] == "stm32h7s" { - // cfgs.push("stm32h7rs".to_owned()); - // } else { - // cfgs.push(chip_name[..7].to_owned()); // stm32f4 - // } - // cfgs.push(chip_name[..9].to_owned()); // stm32f429 - // cfgs.push(format!("{}x", &chip_name[..8])); // stm32f42x - // cfgs.push(format!("{}x{}", &chip_name[..7], &chip_name[8..9])); // stm32f4x9 - // cfgs.push(format!("package_{}", &chip_name[9..10])); - // cfgs.push(format!("flashsize_{}", &chip_name[10..11])); - // } + if let Some(core) = core_name { + cfgs.push(format!("{}_{}", &chip_name[..chip_name.len() - 2], core)); + } - // // Mark the L4+ chips as they have many differences to regular L4. - // if &chip_name[..7] == "stm32l4" { - // if "pqrs".contains(&chip_name[7..8]) { - // cfgs.push("stm32l4_plus".to_owned()); - // } else { - // cfgs.push("stm32l4_nonplus".to_owned()); - // } - // } + // Configs for targeting groups of chips + if &chip_name[..9] == "py32f002a" || &chip_name[..9] == "py32f002b" { + cfgs.push(chip_name[..6].to_owned()); // py32f0 + cfgs.push(chip_name[..9].to_owned()); // py32f002a + // TODO + } + else { + cfgs.push(chip_name[..6].to_owned()); // py32f0 + cfgs.push(chip_name[..8].to_owned()); // py32f030 + cfgs.push(format!("package_{}", &chip_name[8..10])); + cfgs.push(format!("flashsize_{}", &chip_name[10..11])); + } + + // cfgs.push(format!("{}x", &chip_name[..8])); // stm32f42x + // cfgs.push(format!("{}x{}", &chip_name[..7], &chip_name[8..9])); // stm32f4x9 + - // cfgs - // } + cfgs + } - // cfgs.enable_all(&get_chip_cfgs(&chip_name)); - // for &chip_name in ALL_CHIPS.iter() { - // cfgs.declare_all(&get_chip_cfgs(&chip_name.to_ascii_lowercase())); - // } + cfgs.enable_all(&get_chip_cfgs(&chip_name)); + for &chip_name in ALL_CHIPS.iter() { + cfgs.declare_all(&get_chip_cfgs(&chip_name.to_ascii_lowercase())); + } println!("cargo:rerun-if-changed=build.rs"); } From 3097a69dbbedf22fd4abf6f20120b7a0ff95309e Mon Sep 17 00:00:00 2001 From: decaday Date: Fri, 22 Nov 2024 17:33:57 +0800 Subject: [PATCH 9/9] fix: missing .cargo/config.toml, wrong package name --- examples/py32f072/.cargo/config.toml | 11 +++++++++++ examples/py32f072/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 examples/py32f072/.cargo/config.toml diff --git a/examples/py32f072/.cargo/config.toml b/examples/py32f072/.cargo/config.toml new file mode 100644 index 0000000..af5600b --- /dev/null +++ b/examples/py32f072/.cargo/config.toml @@ -0,0 +1,11 @@ +[target.thumbv6m-none-eabi] +# probe-rs chip list | grep -i PY32 +runner = 'probe-rs run --chip PY32F072xb' + +[build] +target = "thumbv6m-none-eabi" + +[env] +DEFMT_LOG = "trace" + +# rustflags = ["-C", "link-arg=-Tlink.x"] diff --git a/examples/py32f072/Cargo.toml b/examples/py32f072/Cargo.toml index 35ed3a7..466a291 100644 --- a/examples/py32f072/Cargo.toml +++ b/examples/py32f072/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "py32f030-examples" +name = "py32f072-examples" version = "0.1.0" edition = "2021"