Merge pull request #38 from anall/bugfix/pll-uart-reset

Have the `pll` and `uart` HAL modules bring the hardware out of reset
This commit is contained in:
9names 2021-05-29 20:36:17 +10:00 committed by GitHub
commit 9bef0821d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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 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,

View file

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

View file

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