diff --git a/Cargo.toml b/Cargo.toml index a672a93..46470d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ embassy-stm32 = { version = "0.1.0", git = "https://github.com/embassy-rs/embass "embedded-sdmmc", "chrono", ] } -embassy-sync = { version = "0.2.0", git = "https://github.com/embassy-rs/embassy.git", features = [ +embassy-sync = { version = "0.4.0", git = "https://github.com/embassy-rs/embassy.git", features = [ "defmt", ] } -embassy-executor = { version = "0.2.0", git = "https://github.com/embassy-rs/embassy.git", features = [ +embassy-executor = { version = "0.3.1", git = "https://github.com/embassy-rs/embassy.git", features = [ "nightly", "arch-cortex-m", "executor-thread", @@ -42,10 +42,10 @@ embassy-time = { version = "0.1.2", git = "https://github.com/embassy-rs/embassy embassy-usb = { version = "0.1.0", git = "https://github.com/embassy-rs/embassy.git", features = [ "defmt", ] } -defmt = "0.3" +defmt = "0.3.5" defmt-rtt = "0.4" embedded-hal = "0.2.6" -embedded-io = "0.5.0" +embedded-io = "0.6.1" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = [ "async-await", @@ -54,7 +54,7 @@ heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" embedded-storage = "0.3.0" micromath = "2.0.0" -static_cell = { version = "1.1", features = ["nightly"] } +static_cell = { version = "2.0.0", features = ["nightly"] } chrono = { version = "^0.4", default-features = false } [profile.dev] diff --git a/examples/blinky.rs b/examples/blinky.rs index 811b15b..dba3971 100644 --- a/examples/blinky.rs +++ b/examples/blinky.rs @@ -2,75 +2,51 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::cell::RefCell; -use cortex_m::interrupt::Mutex; +use defmt::info; use defmt_rtt as _; -use embassy_executor::Spawner; -use embassy_stm32::gpio::Output; -use embassy_time::{Duration, Timer}; +use embassy_executor::{main, task, Spawner}; +use embassy_time::Timer; +use portenta_h7_async::led; -static LED_RED: Mutex>>> = - Mutex::new(RefCell::new(None)); -static LED_GREEN: Mutex>>> = - Mutex::new(RefCell::new(None)); -static LED_BLUE: Mutex>>> = - Mutex::new(RefCell::new(None)); - -#[embassy_executor::main] +#[main] async fn main(spawner: Spawner) { + info!("Starting"); let portenta_h7_async::Board { led_red, - led_green, led_blue, + led_green, + .. } = portenta_h7_async::Board::take(); - cortex_m::interrupt::free(|cs| { - LED_RED.borrow(cs).replace(Some(led_red)); - LED_GREEN.borrow(cs).replace(Some(led_green)); - LED_BLUE.borrow(cs).replace(Some(led_blue)); - }); - - spawner.spawn(blink_led_red()).unwrap(); - spawner.spawn(blink_led_green()).unwrap(); - spawner.spawn(blink_led_blue()).unwrap(); + spawner.spawn(blink_led_red(led_red)).unwrap(); + spawner.spawn(blink_led_green(led_green)).unwrap(); + spawner.spawn(blink_led_blue(led_blue)).unwrap(); loop { - Timer::after(Duration::from_millis(100)).await; + Timer::after_millis(100).await; } } -#[embassy_executor::task] -async fn blink_led_red() { +#[task] +async fn blink_led_red(mut led: led::user::Red) { loop { - cortex_m::interrupt::free(|cs| { - if let Some(led_red) = LED_RED.borrow(cs).borrow_mut().as_mut() { - led_red.toggle(); - } - }); - Timer::after(Duration::from_millis(500)).await; + led.toggle(); + Timer::after_millis(250).await; } } -#[embassy_executor::task] -async fn blink_led_green() { +#[task] +async fn blink_led_green(mut led: led::user::Green) { loop { - cortex_m::interrupt::free(|cs| { - if let Some(led_green) = LED_GREEN.borrow(cs).borrow_mut().as_mut() { - led_green.toggle(); - } - }); - Timer::after(Duration::from_millis(1_000)).await; + led.toggle(); + Timer::after_millis(500).await; } } -#[embassy_executor::task] -async fn blink_led_blue() { +#[task] +async fn blink_led_blue(mut led: led::user::Blue) { loop { - cortex_m::interrupt::free(|cs| { - if let Some(led_blue) = LED_BLUE.borrow(cs).borrow_mut().as_mut() { - led_blue.toggle(); - } - }); - Timer::after(Duration::from_millis(2_000)).await; + led.toggle(); + Timer::after_millis(1_000).await; } } diff --git a/src/led.rs b/src/led.rs new file mode 100644 index 0000000..614487c --- /dev/null +++ b/src/led.rs @@ -0,0 +1,47 @@ +//! led + +use embassy_stm32::{ + gpio::{Output, Pin}, + peripherals, +}; + +pub trait Led { + fn on(&mut self); + fn off(&mut self); + fn toggle(&mut self); +} + +pub mod user { + use super::*; + + pub type Red = Output<'static, peripherals::PK5>; + pub type Green = Output<'static, peripherals::PK6>; + pub type Blue = Output<'static, peripherals::PK7>; + + // Marker trait + trait BoardLed {} + impl BoardLed for Red {} + impl BoardLed for Green {} + impl BoardLed for Blue {} + + impl Led for Output<'static, T> + where + T: Pin, + Output<'static, T>: BoardLed, + { + #[inline] + fn on(&mut self) { + self.set_low(); + } + + #[inline] + fn off(&mut self) { + self.set_high(); + } + + #[inline] + fn toggle(&mut self) { + self.toggle(); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 764e33e..4c0c579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ #![no_std] +pub mod led; pub mod panic; +mod sys; use embassy_stm32::{ gpio::{Level, Output, Speed}, peripherals, @@ -22,6 +24,7 @@ impl<'a> Board<'a> { } pub fn setup() -> Self { + sys::Clk::new().reset().enable_ext_clock(); let p = embassy_stm32::init(Default::default()); let led_red = Output::new(p.PK5, Level::High, Speed::Low); let led_green = Output::new(p.PK6, Level::High, Speed::Low); diff --git a/src/sys.rs b/src/sys.rs new file mode 100644 index 0000000..86fa931 --- /dev/null +++ b/src/sys.rs @@ -0,0 +1,106 @@ +//! sys +//! +//! Clear up previous clock initialization done in bootloader +//! Enable external oscillator for HSE sourcing (25 MHz) +//! + +#![allow(dead_code)] + +use cortex_m::asm; +use embassy_stm32::pac::{self, gpio, rcc}; + +pub struct Unreset; +pub struct Reset; + +pub struct Clk { + _state: State, +} + +pub type ClkSource = pac::rcc::vals::Sw; +pub type PllSource = pac::rcc::vals::Pllsrc; + +impl Clk { + pub fn new() -> Clk { + Clk { _state: Unreset } + } + + pub fn get_source() -> ClkSource { + pac::RCC.cfgr().read().sws() + } + + pub fn get_pll_source() -> PllSource { + pac::RCC.pllckselr().read().pllsrc() + } + + pub fn reset(self) -> Clk { + let rcc = pac::RCC; + + // Enable HSI and load reset values + rcc.cr().modify(|w| w.set_hsion(true)); + rcc.hsicfgr().modify(|w| w.set_hsitrim(0b100000)); + + // Reset clock configuration and wait for clock switch + rcc.cfgr().write_value(Default::default()); + while rcc.cfgr().read() != Default::default() {} + + // Reset CSI, HSE, HSI48 and dividers + rcc.cr().modify(|w| { + w.set_hsikeron(false); + w.set_hsidiv(rcc::vals::Hsidiv::DIV1); + w.set_hsidivf(false); + w.set_csion(false); + w.set_csikeron(false); + w.set_hsi48on(false); + w.set_hsecsson(false); + w.set_hsebyp(false); + }); + + // Disable PLL1, PLL2, PLL3 + for n in 0..3usize { + rcc.cr().modify(|w| w.set_pllon(n, false)); + while rcc.cr().read().pllon(n) {} + } + + // Reset domain configurations + rcc.d1cfgr().write_value(Default::default()); + rcc.d2cfgr().write_value(Default::default()); + rcc.d3cfgr().write_value(Default::default()); + + // Reset PLLs configurations + for n in 0..3usize { + rcc.pllckselr() + .write(|w| w.set_divm(n, rcc::vals::Pllm::DIV32)); + rcc.plldivr(n) + .write(|w| w.set_pllr(rcc::vals::Plldiv::DIV2)); + rcc.pllfracr(n).write(|w| w.set_fracn(0x00)); + } + Clk { _state: Reset } + } +} + +impl Clk { + pub fn enable_ext_clock(self) -> Clk { + let rcc = pac::RCC; + // Enable GPIOH clock + rcc.ahb4enr().modify(|w| w.set_gpiohen(true)); + + // Enable oscilator via push pulled GPIOH_1 output + let gpioh = pac::GPIOH; + gpioh.bsrr().write(|w| w.set_bs(1, true)); + gpioh + .moder() + .modify(|w| w.set_moder(1, gpio::vals::Moder::OUTPUT)); + gpioh + .otyper() + .modify(|w| w.set_ot(1, gpio::vals::Ot::PUSHPULL)); + gpioh + .ospeedr() + .modify(|w| w.set_ospeedr(1, gpio::vals::Ospeedr::LOWSPEED)); + gpioh + .pupdr() + .modify(|w| w.set_pupdr(1, gpio::vals::Pupdr::PULLUP)); + + asm::delay(1_000); + Clk { _state: Reset } + } +}