mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2025-01-11 13:01:30 +11:00
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.
This commit is contained in:
parent
9e7e785e22
commit
8d0fde20c6
|
@ -77,18 +77,15 @@ macro_rules! gpio {
|
||||||
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
|
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use crate::resets::SubsystemReset;
|
||||||
|
|
||||||
impl GpioExt<pac::$PADSX, sio::$siotoken> for pac::$GPIOX {
|
impl GpioExt<pac::$PADSX, sio::$siotoken> for pac::$GPIOX {
|
||||||
type Parts = Parts;
|
type Parts = Parts;
|
||||||
|
|
||||||
fn split(self, pads: pac::$PADSX, sio: sio::$siotoken, resets: &mut pac::RESETS) -> 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());
|
// FIXME: bring both of these up at the same time
|
||||||
// TODO: Implement Resets in the HAL
|
self.reset_bring_up(resets);
|
||||||
while resets.reset_done.read().$gpiox().bit_is_clear() {
|
pads.reset_bring_up(resets);
|
||||||
cortex_m::asm::delay(10);
|
|
||||||
}
|
|
||||||
while resets.reset_done.read().$padsx().bit_is_clear() {
|
|
||||||
cortex_m::asm::delay(10);
|
|
||||||
}
|
|
||||||
Parts {
|
Parts {
|
||||||
_pads: pads,
|
_pads: pads,
|
||||||
_sio: sio,
|
_sio: sio,
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub mod i2c;
|
||||||
pub mod pll;
|
pub mod pll;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod pwm;
|
pub mod pwm;
|
||||||
|
pub mod resets;
|
||||||
pub mod rom_data;
|
pub mod rom_data;
|
||||||
pub mod rtc;
|
pub mod rtc;
|
||||||
pub mod sio;
|
pub mod sio;
|
||||||
|
|
|
@ -14,6 +14,8 @@ use embedded_time::{
|
||||||
|
|
||||||
use nb::Error::WouldBlock;
|
use nb::Error::WouldBlock;
|
||||||
|
|
||||||
|
use crate::resets::SubsystemReset;
|
||||||
|
|
||||||
/// State of the PLL
|
/// State of the PLL
|
||||||
pub trait State {}
|
pub trait State {}
|
||||||
|
|
||||||
|
@ -39,7 +41,10 @@ impl State for Locked {}
|
||||||
impl State for Locking {}
|
impl State for Locking {}
|
||||||
|
|
||||||
/// Trait to handle both underlying devices from the PAC (PLL_SYS & PLL_USB)
|
/// Trait to handle both underlying devices from the PAC (PLL_SYS & PLL_USB)
|
||||||
pub trait PhaseLockedLoopDevice: Deref<Target = rp2040_pac::pll_sys::RegisterBlock> {}
|
pub trait PhaseLockedLoopDevice:
|
||||||
|
Deref<Target = rp2040_pac::pll_sys::RegisterBlock> + SubsystemReset
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl PhaseLockedLoopDevice for rp2040_pac::PLL_SYS {}
|
impl PhaseLockedLoopDevice for rp2040_pac::PLL_SYS {}
|
||||||
impl PhaseLockedLoopDevice for rp2040_pac::PLL_USB {}
|
impl PhaseLockedLoopDevice for rp2040_pac::PLL_USB {}
|
||||||
|
@ -190,7 +195,9 @@ impl<D: PhaseLockedLoopDevice> PhaseLockedLoop<Disabled, D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures and starts the PLL : it switches to Locking state.
|
/// Configures and starts the PLL : it switches to Locking state.
|
||||||
pub fn initialize(self) -> PhaseLockedLoop<Locking, D> {
|
pub fn initialize(self, resets: &mut rp2040_pac::RESETS) -> PhaseLockedLoop<Locking, D> {
|
||||||
|
self.device.reset_bring_up(resets);
|
||||||
|
|
||||||
// Turn off PLL in case it is already running
|
// Turn off PLL in case it is already running
|
||||||
self.device.pwr.reset();
|
self.device.pwr.reset();
|
||||||
self.device.fbdiv_int.reset();
|
self.device.fbdiv_int.reset();
|
||||||
|
|
49
rp2040-hal/src/resets.rs
Normal file
49
rp2040-hal/src/resets.rs
Normal file
|
@ -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);
|
|
@ -16,6 +16,8 @@ use crate::pac::{
|
||||||
UART0, UART1,
|
UART0, UART1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::resets::SubsystemReset;
|
||||||
|
|
||||||
/// Error type for UART operations.
|
/// Error type for UART operations.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -51,7 +53,7 @@ pub enum ReadErrorType {
|
||||||
pub trait State {}
|
pub trait State {}
|
||||||
|
|
||||||
/// Trait to handle both underlying devices (UART0 & UART1)
|
/// Trait to handle both underlying devices (UART0 & UART1)
|
||||||
pub trait UartDevice: Deref<Target = RegisterBlock> {}
|
pub trait UartDevice: Deref<Target = RegisterBlock> + SubsystemReset {}
|
||||||
|
|
||||||
impl UartDevice for UART0 {}
|
impl UartDevice for UART0 {}
|
||||||
impl UartDevice for UART1 {}
|
impl UartDevice for UART1 {}
|
||||||
|
@ -178,9 +180,12 @@ impl<D: UartDevice> UartPeripheral<Disabled, D> {
|
||||||
/// Enables the provided UART device with the given configuration.
|
/// Enables the provided UART device with the given configuration.
|
||||||
pub fn enable(
|
pub fn enable(
|
||||||
mut device: D,
|
mut device: D,
|
||||||
|
resets: &mut pac::RESETS,
|
||||||
config: UartConfig,
|
config: UartConfig,
|
||||||
frequency: Hertz,
|
frequency: Hertz,
|
||||||
) -> Result<UartPeripheral<Enabled, D>, Error> {
|
) -> Result<UartPeripheral<Enabled, D>, Error> {
|
||||||
|
device.reset_bring_up(resets);
|
||||||
|
|
||||||
let effective_baudrate = configure_baudrate(&mut device, &config.baudrate, &frequency)?;
|
let effective_baudrate = configure_baudrate(&mut device, &config.baudrate, &frequency)?;
|
||||||
|
|
||||||
// Enable the UART, both TX and RX
|
// Enable the UART, both TX and RX
|
||||||
|
|
Loading…
Reference in a new issue