diff --git a/examples/blinky.rs b/examples/blinky.rs index 55af42b..3e2d8c8 100644 --- a/examples/blinky.rs +++ b/examples/blinky.rs @@ -7,7 +7,10 @@ #![no_main] #[allow(unused_imports)] -use portenta_h7::{log, log_init, user_led}; +use portenta_h7::{ + board::{self, Board}, + led, log, log_init, +}; use rtic::app; use systick_monotonic::{fugit::MillisDurationU64, Systick}; @@ -20,9 +23,9 @@ mod app { #[local] struct Local { - led_red: user_led::Red, - led_green: user_led::Green, - led_blue: user_led::Blue, + led_red: led::user::Red, + led_green: led::user::Green, + led_blue: led::user::Blue, } #[monotonic(binds = SysTick, default = true)] @@ -32,15 +35,15 @@ mod app { fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { log_init!(); - let mono = Systick::new(cx.core.SYST, portenta_h7::CORE_FREQUENCY.raw()); + let mono = Systick::new(cx.core.SYST, board::CORE_FREQUENCY.raw()); - // Get boatd resources - let portenta_h7::Board { + // Get board resources + let Board { led_red, led_green, led_blue, .. - } = portenta_h7::Board::take(); + } = Board::take(); #[cfg(debug_assertions)] log!("spawning tasks"); diff --git a/examples/usb_echo.rs b/examples/usb_echo.rs index c77b7b8..488326d 100644 --- a/examples/usb_echo.rs +++ b/examples/usb_echo.rs @@ -8,9 +8,9 @@ use cortex_m::singleton; use portenta_h7::{ + board::{self, Board, UsbBus, USB}, + led::{self, Led}, log, log_init, - user_led::{self, UserLed}, - UsbBus, USB, }; use rtic::app; use systick_monotonic::Systick; @@ -31,7 +31,7 @@ mod app { #[local] struct Local { - led_blue: user_led::Blue, + led_blue: led::user::Blue, usb_dev: UsbDevice<'static, UsbBus>, usb_serial_port: CdcAcmClass<'static, UsbBus>, } @@ -43,10 +43,10 @@ mod app { fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { log_init!(); - let mono = Systick::new(cx.core.SYST, portenta_h7::CORE_FREQUENCY.raw()); + let mono = Systick::new(cx.core.SYST, board::CORE_FREQUENCY.raw()); // Get board resources - let portenta_h7::Board { led_blue, usb, .. } = portenta_h7::Board::take(); + let Board { led_blue, usb, .. } = Board::take(); // Init USB stack let usb_bus = singleton!( @@ -110,14 +110,14 @@ mod app { // Transition to enumeration UsbDeviceState::Configured if previous_state == UsbDeviceState::Addressed => { log!("Enumeration completed"); - cx.local.led_blue.set_on(); + cx.local.led_blue.on(); } // Already enumerated UsbDeviceState::Configured => {} // Enumeration lost _ if previous_state == UsbDeviceState::Configured => { log!("Enumeration lost"); - cx.local.led_blue.set_off(); + cx.local.led_blue.off(); } _ => (), } diff --git a/src/board.rs b/src/board.rs new file mode 100644 index 0000000..54afa25 --- /dev/null +++ b/src/board.rs @@ -0,0 +1,99 @@ +//! board + +#[allow(unused)] +use crate::log; +use crate::{hal, led, sys}; +use core::sync::atomic::{AtomicBool, Ordering}; +pub use hal::usb_hs::{UsbBus, USB1_ULPI as USB}; +use hal::{gpio::PinState, pac, prelude::*, rcc, time::Hertz, usb_hs::USB1_ULPI}; + +pub const CORE_FREQUENCY: Hertz = Hertz::from_raw(480_000_000); + +pub struct Board { + pub led_red: led::user::Red, + pub led_green: led::user::Green, + pub led_blue: led::user::Blue, + pub usb: USB1_ULPI, +} + +impl Board { + pub fn take() -> Self { + static TAKEN: AtomicBool = AtomicBool::new(false); + debug_assert!(!TAKEN.swap(true, Ordering::SeqCst)); + Self::setup() + } + + fn setup() -> Self { + #[cfg(debug_assertions)] + log!("Board init"); + + // Reset previous configuration and enable external oscillator as HSE source (25 MHz) + sys::Clk::new().reset().enable_ext_clock(); + let dp = pac::Peripherals::take().unwrap(); + + // Configure power domains and clock tree + let pwrcfg = dp.PWR.constrain().vos0(&dp.SYSCFG).freeze(); + let ccdr = dp + .RCC + .constrain() + .use_hse(25.MHz()) + .bypass_hse() + .sys_ck(CORE_FREQUENCY) + .hclk(240.MHz()) + .pll1_strategy(rcc::PllConfigStrategy::Iterative) + .freeze(pwrcfg, &dp.SYSCFG); + + debug_assert_eq!(sys::Clk::get_source(), Some(sys::ClkSource::Pll1)); + debug_assert_eq!(sys::Clk::get_pll_source(), sys::PllSourceVariant::Hse); + + // USB + let (gpioa, gpiob, gpioc, gpioh, gpioi, gpioj) = { + ( + dp.GPIOA.split(ccdr.peripheral.GPIOA), + dp.GPIOB.split(ccdr.peripheral.GPIOB), + dp.GPIOC.split(ccdr.peripheral.GPIOC), + dp.GPIOH.split_without_reset(ccdr.peripheral.GPIOH), // Do not do a reset since external oscillator is enabled by GPIOH1 + dp.GPIOI.split(ccdr.peripheral.GPIOI), + dp.GPIOJ.split(ccdr.peripheral.GPIOJ), + ) + }; + // Enable ULPI transceiver (GPIOJ4) + let mut ulpi_reset = gpioj.pj4.into_push_pull_output(); + ulpi_reset.set_high(); + + let usb = USB1_ULPI::new( + dp.OTG1_HS_GLOBAL, + dp.OTG1_HS_DEVICE, + dp.OTG1_HS_PWRCLK, + gpioa.pa5.into_alternate(), + gpioi.pi11.into_alternate(), + gpioh.ph4.into_alternate(), + gpioc.pc0.into_alternate(), + gpioa.pa3.into_alternate(), + gpiob.pb0.into_alternate(), + gpiob.pb1.into_alternate(), + gpiob.pb10.into_alternate(), + gpiob.pb11.into_alternate(), + gpiob.pb12.into_alternate(), + gpiob.pb13.into_alternate(), + gpiob.pb5.into_alternate(), + ccdr.peripheral.USB1OTG, + &ccdr.clocks, + ); + + // User LEDs + let gpiok = dp.GPIOK.split(ccdr.peripheral.GPIOK); + let (led_red, led_green, led_blue) = ( + gpiok.pk5.into_push_pull_output_in_state(PinState::High), + gpiok.pk6.into_push_pull_output_in_state(PinState::High), + gpiok.pk7.into_push_pull_output_in_state(PinState::High), + ); + + Board { + led_red, + led_green, + led_blue, + usb, + } + } +} diff --git a/src/interrupt.rs b/src/interrupt.rs index f6958e0..f17c40d 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -2,7 +2,8 @@ pub use crate::hal::pac::interrupt; use crate::hal::{self, usb_hs::USB1_ULPI}; -use crate::CorePeripherals; + +type CorePeripherals = cortex_m::Peripherals; pub trait InterruptEnabler { fn enable_interrupt(&self); diff --git a/src/led.rs b/src/led.rs new file mode 100644 index 0000000..4a3a9c4 --- /dev/null +++ b/src/led.rs @@ -0,0 +1,44 @@ +//! led + +pub use crate::hal::gpio::{gpiok::*, Output, Pin, PinState, PushPull}; +type DigitalOutputPin = Pin>; + +pub trait Led { + fn on(&mut self); + fn off(&mut self); + fn toggle(&mut self); +} + +pub mod user { + use super::*; + + pub type Red = DigitalOutputPin<'K', 5>; + pub type Green = DigitalOutputPin<'K', 6>; + pub type Blue = DigitalOutputPin<'K', 7>; + + // Marker trait + trait BoardLed {} + impl BoardLed for Red {} + impl BoardLed for Green {} + impl BoardLed for Blue {} + + impl Led for DigitalOutputPin + where + DigitalOutputPin: 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 f875639..4a9e0f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,107 +1,11 @@ #![no_std] +pub mod board; pub mod interrupt; +pub mod led; pub mod panic; mod sys; -pub mod user_led; - -use core::sync::atomic::{AtomicBool, Ordering}; pub use cortex_m_rt::entry; -pub use hal::usb_hs::{UsbBus, USB1_ULPI as USB}; -use hal::{gpio::PinState, pac, prelude::*, rcc, time::Hertz, usb_hs::USB1_ULPI}; #[allow(unused_imports)] pub use rtt_target::{rprintln as log, rtt_init_print as log_init}; pub use stm32h7xx_hal as hal; - -pub type CorePeripherals = cortex_m::Peripherals; - -pub const CORE_FREQUENCY: Hertz = Hertz::from_raw(480_000_000); - -pub struct Board { - pub led_red: user_led::Red, - pub led_green: user_led::Green, - pub led_blue: user_led::Blue, - pub usb: USB1_ULPI, -} - -impl Board { - pub fn take() -> Self { - static TAKEN: AtomicBool = AtomicBool::new(false); - debug_assert!(!TAKEN.swap(true, Ordering::SeqCst)); - Self::setup() - } - - fn setup() -> Self { - #[cfg(debug_assertions)] - log!("Board init"); - - // Reset previous configuration and enable external oscillator as HSE source (25 MHz) - sys::Clk::new().reset().enable_ext_clock(); - let dp = pac::Peripherals::take().unwrap(); - - // Configure power domains and clock tree - let pwrcfg = dp.PWR.constrain().vos0(&dp.SYSCFG).freeze(); - let ccdr = dp - .RCC - .constrain() - .use_hse(25.MHz()) - .bypass_hse() - .sys_ck(CORE_FREQUENCY) - .hclk(240.MHz()) - .pll1_strategy(rcc::PllConfigStrategy::Iterative) - .freeze(pwrcfg, &dp.SYSCFG); - - debug_assert_eq!(sys::Clk::get_source(), Some(sys::ClkSource::Pll1)); - debug_assert_eq!(sys::Clk::get_pll_source(), sys::PllSourceVariant::Hse); - - // USB - let (gpioa, gpiob, gpioc, gpioh, gpioi, gpioj) = { - ( - dp.GPIOA.split(ccdr.peripheral.GPIOA), - dp.GPIOB.split(ccdr.peripheral.GPIOB), - dp.GPIOC.split(ccdr.peripheral.GPIOC), - dp.GPIOH.split_without_reset(ccdr.peripheral.GPIOH), // Do not do a reset since external oscillator is enabled by GPIOH1 - dp.GPIOI.split(ccdr.peripheral.GPIOI), - dp.GPIOJ.split(ccdr.peripheral.GPIOJ), - ) - }; - // Enable ULPI transceiver (GPIOJ4) - let mut ulpi_reset = gpioj.pj4.into_push_pull_output(); - ulpi_reset.set_high(); - - let usb = USB1_ULPI::new( - dp.OTG1_HS_GLOBAL, - dp.OTG1_HS_DEVICE, - dp.OTG1_HS_PWRCLK, - gpioa.pa5.into_alternate(), - gpioi.pi11.into_alternate(), - gpioh.ph4.into_alternate(), - gpioc.pc0.into_alternate(), - gpioa.pa3.into_alternate(), - gpiob.pb0.into_alternate(), - gpiob.pb1.into_alternate(), - gpiob.pb10.into_alternate(), - gpiob.pb11.into_alternate(), - gpiob.pb12.into_alternate(), - gpiob.pb13.into_alternate(), - gpiob.pb5.into_alternate(), - ccdr.peripheral.USB1OTG, - &ccdr.clocks, - ); - - // User LEDs - let gpiok = dp.GPIOK.split(ccdr.peripheral.GPIOK); - let (led_red, led_green, led_blue) = ( - gpiok.pk5.into_push_pull_output_in_state(PinState::High), - gpiok.pk6.into_push_pull_output_in_state(PinState::High), - gpiok.pk7.into_push_pull_output_in_state(PinState::High), - ); - - Board { - led_red, - led_green, - led_blue, - usb, - } - } -} diff --git a/src/user_led.rs b/src/user_led.rs deleted file mode 100644 index bfd20e0..0000000 --- a/src/user_led.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! led - -pub use crate::hal::gpio::{gpiok::*, Output, Pin, PinState, PushPull}; - -type DigitalOutputPin = Pin>; -pub type Red = DigitalOutputPin<'K', 5>; -pub type Green = DigitalOutputPin<'K', 6>; -pub type Blue = DigitalOutputPin<'K', 7>; - -pub trait BoardLed {} - -impl BoardLed for Red {} -impl BoardLed for Green {} -impl BoardLed for Blue {} - -pub trait UserLed { - fn set_on(&mut self); - fn set_off(&mut self); - fn toggle(&mut self); -} - -impl UserLed for DigitalOutputPin -where - DigitalOutputPin: BoardLed, -{ - #[inline(always)] - fn set_on(&mut self) { - self.set_low(); - } - - #[inline(always)] - fn set_off(&mut self) { - self.set_high(); - } - - #[inline(always)] - fn toggle(&mut self) { - self.toggle(); - } -}