From 8d0fde20c69bf00ca5f75fab6aef83113f757b43 Mon Sep 17 00:00:00 2001 From: Andrea Nall Date: Sun, 16 May 2021 12:42:41 -0500 Subject: [PATCH] Add `SubsystemReset` trait to handle subsystem resets dd a `SubsystemReset` trait which adds a `reset_bring_up` function to the relevant PAC types to handle bringing subsystems out of reset. Also, correct that the PLL and UART modules did not bring the relevant subsystems out of reset and refactor the GPIO module to use the SubsystemReset trait. --- rp2040-hal/src/gpio.rs | 13 ++++------- rp2040-hal/src/lib.rs | 1 + rp2040-hal/src/pll.rs | 11 +++++++-- rp2040-hal/src/resets.rs | 49 ++++++++++++++++++++++++++++++++++++++++ rp2040-hal/src/uart.rs | 7 +++++- 5 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 rp2040-hal/src/resets.rs diff --git a/rp2040-hal/src/gpio.rs b/rp2040-hal/src/gpio.rs index 5b2e6bc..f9f1c36 100644 --- a/rp2040-hal/src/gpio.rs +++ b/rp2040-hal/src/gpio.rs @@ -77,18 +77,15 @@ macro_rules! gpio { use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use super::*; + use crate::resets::SubsystemReset; + impl GpioExt for pac::$GPIOX { type Parts = Parts; fn split(self, pads: pac::$PADSX, sio: sio::$siotoken, resets: &mut pac::RESETS) -> Parts { - resets.reset.modify(|_, w| w.$gpiox().clear_bit().$padsx().clear_bit()); - // TODO: Implement Resets in the HAL - while resets.reset_done.read().$gpiox().bit_is_clear() { - cortex_m::asm::delay(10); - } - while resets.reset_done.read().$padsx().bit_is_clear() { - cortex_m::asm::delay(10); - } + // FIXME: bring both of these up at the same time + self.reset_bring_up(resets); + pads.reset_bring_up(resets); Parts { _pads: pads, _sio: sio, diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index 9c0cb0d..c0dbc5f 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -19,6 +19,7 @@ pub mod i2c; pub mod pll; pub mod prelude; pub mod pwm; +pub mod resets; pub mod rom_data; pub mod rtc; pub mod sio; diff --git a/rp2040-hal/src/pll.rs b/rp2040-hal/src/pll.rs index 6e1a384..231bd95 100644 --- a/rp2040-hal/src/pll.rs +++ b/rp2040-hal/src/pll.rs @@ -14,6 +14,8 @@ use embedded_time::{ use nb::Error::WouldBlock; +use crate::resets::SubsystemReset; + /// State of the PLL pub trait State {} @@ -39,7 +41,10 @@ impl State for Locked {} impl State for Locking {} /// Trait to handle both underlying devices from the PAC (PLL_SYS & PLL_USB) -pub trait PhaseLockedLoopDevice: Deref {} +pub trait PhaseLockedLoopDevice: + Deref + SubsystemReset +{ +} impl PhaseLockedLoopDevice for rp2040_pac::PLL_SYS {} impl PhaseLockedLoopDevice for rp2040_pac::PLL_USB {} @@ -190,7 +195,9 @@ impl PhaseLockedLoop { } /// Configures and starts the PLL : it switches to Locking state. - pub fn initialize(self) -> PhaseLockedLoop { + pub fn initialize(self, resets: &mut rp2040_pac::RESETS) -> PhaseLockedLoop { + self.device.reset_bring_up(resets); + // Turn off PLL in case it is already running self.device.pwr.reset(); self.device.fbdiv_int.reset(); diff --git a/rp2040-hal/src/resets.rs b/rp2040-hal/src/resets.rs new file mode 100644 index 0000000..48c290f --- /dev/null +++ b/rp2040-hal/src/resets.rs @@ -0,0 +1,49 @@ +//! Subsystem Resets +// See [Chapter 2 Section 14](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details +use rp2040_pac as pac; + +mod private { + pub trait SubsystemReset { + fn reset_bring_up(&self, resets: &mut pac::RESETS); + } +} + +pub(crate) use private::SubsystemReset; + +macro_rules! generate_reset { + ($MODULE:ident, $module:ident) => { + impl SubsystemReset for pac::$MODULE { + fn reset_bring_up(&self, resets: &mut pac::RESETS) { + resets.reset.modify(|_, w| w.$module().clear_bit()); + while resets.reset_done.read().$module().bit_is_clear() {} + } + } + }; +} + +// In datasheet order +generate_reset!(USBCTRL_REGS, usbctrl); +generate_reset!(UART1, uart1); +generate_reset!(UART0, uart0); +generate_reset!(TIMER, timer); +generate_reset!(TBMAN, tbman); +generate_reset!(SYSINFO, sysinfo); +generate_reset!(SYSCFG, syscfg); +generate_reset!(SPI1, spi1); +generate_reset!(SPI0, spi0); +generate_reset!(RTC, rtc); +generate_reset!(PWM, pwm); +generate_reset!(PLL_USB, pll_usb); +generate_reset!(PLL_SYS, pll_sys); +generate_reset!(PIO1, pio1); +generate_reset!(PIO0, pio0); +generate_reset!(PADS_QSPI, pads_qspi); +generate_reset!(PADS_BANK0, pads_bank0); +//generate_reset!(JTAG,jtag); // This doesn't seem to have an item in the pac +generate_reset!(IO_QSPI, io_qspi); +generate_reset!(IO_BANK0, io_bank0); +generate_reset!(I2C1, i2c1); +generate_reset!(I2C0, i2c0); +generate_reset!(DMA, dma); +generate_reset!(BUSCTRL, busctrl); +generate_reset!(ADC, adc); diff --git a/rp2040-hal/src/uart.rs b/rp2040-hal/src/uart.rs index 868db57..080a368 100644 --- a/rp2040-hal/src/uart.rs +++ b/rp2040-hal/src/uart.rs @@ -16,6 +16,8 @@ use crate::pac::{ UART0, UART1, }; +use crate::resets::SubsystemReset; + /// Error type for UART operations. #[derive(Debug)] pub enum Error { @@ -51,7 +53,7 @@ pub enum ReadErrorType { pub trait State {} /// Trait to handle both underlying devices (UART0 & UART1) -pub trait UartDevice: Deref {} +pub trait UartDevice: Deref + SubsystemReset {} impl UartDevice for UART0 {} impl UartDevice for UART1 {} @@ -178,9 +180,12 @@ impl UartPeripheral { /// Enables the provided UART device with the given configuration. pub fn enable( mut device: D, + resets: &mut pac::RESETS, config: UartConfig, frequency: Hertz, ) -> Result, Error> { + device.reset_bring_up(resets); + let effective_baudrate = configure_baudrate(&mut device, &config.baudrate, &frequency)?; // Enable the UART, both TX and RX