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