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:
Andrea Nall 2021-05-16 12:42:41 -05:00
parent 9e7e785e22
commit 8d0fde20c6
5 changed files with 70 additions and 11 deletions

View file

@ -77,18 +77,15 @@ macro_rules! gpio {
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
use super::*;
use crate::resets::SubsystemReset;
impl GpioExt<pac::$PADSX, sio::$siotoken> 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,

View file

@ -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;

View file

@ -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<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_USB {}
@ -190,7 +195,9 @@ impl<D: PhaseLockedLoopDevice> PhaseLockedLoop<Disabled, D> {
}
/// 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
self.device.pwr.reset();
self.device.fbdiv_int.reset();

49
rp2040-hal/src/resets.rs Normal file
View 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);

View file

@ -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<Target = RegisterBlock> {}
pub trait UartDevice: Deref<Target = RegisterBlock> + SubsystemReset {}
impl UartDevice for UART0 {}
impl UartDevice for UART1 {}
@ -178,9 +180,12 @@ impl<D: UartDevice> UartPeripheral<Disabled, D> {
/// Enables the provided UART device with the given configuration.
pub fn enable(
mut device: D,
resets: &mut pac::RESETS,
config: UartConfig,
frequency: Hertz,
) -> Result<UartPeripheral<Enabled, D>, Error> {
device.reset_bring_up(resets);
let effective_baudrate = configure_baudrate(&mut device, &config.baudrate, &frequency)?;
// Enable the UART, both TX and RX