From bb2d9ec7f81bbf0d83e873d53eb37f9d0b359f3b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Feb 2025 00:46:30 +0100 Subject: [PATCH] rp: Workaround "SIO spinlock stuck bug", reset PROC1 at boot. Just like RP2040. The bug was "working as intended" on rp2040, so it is on rp235x. --- embassy-rp/src/lib.rs | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f0893b5a0..8b0023ea5 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -598,7 +598,7 @@ pub fn init(config: config::Config) -> Peripherals { peripherals } -#[cfg(all(feature = "rt", feature = "rp2040"))] +#[cfg(feature = "rt")] #[cortex_m_rt::pre_init] unsafe fn pre_init() { // SIO does not get reset when core0 is reset with either `scb::sys_reset()` or with SWD. @@ -629,17 +629,34 @@ unsafe fn pre_init() { // // The PSM order is SIO -> PROC0 -> PROC1. // So, we have to force-on PROC0 to prevent it from getting reset when resetting SIO. - pac::PSM.frce_on().write_and_wait(|w| { - w.set_proc0(true); - }); - // Then reset SIO and PROC1. - pac::PSM.frce_off().write_and_wait(|w| { - w.set_sio(true); - w.set_proc1(true); - }); - // clear force_off first, force_on second. The other way around would reset PROC0. - pac::PSM.frce_off().write_and_wait(|_| {}); - pac::PSM.frce_on().write_and_wait(|_| {}); + #[cfg(feature = "rp2040")] + { + pac::PSM.frce_on().write_and_wait(|w| { + w.set_proc0(true); + }); + // Then reset SIO and PROC1. + pac::PSM.frce_off().write_and_wait(|w| { + w.set_sio(true); + w.set_proc1(true); + }); + // clear force_off first, force_on second. The other way around would reset PROC0. + pac::PSM.frce_off().write_and_wait(|_| {}); + pac::PSM.frce_on().write_and_wait(|_| {}); + } + + #[cfg(feature = "_rp235x")] + { + // on RP235x, datasheet says "The FRCE_ON register is a development feature that does nothing in production devices." + // No idea why they removed it. Removing it means we can't use PSM to reset SIO, because it comes before + // PROC0, so we'd need FRCE_ON to prevent resetting ourselves. + // + // So we just unlock the spinlock manually. + pac::SIO.spinlock(31).write_value(1); + + // We can still use PSM to reset PROC1 since it comes after PROC0 in the state machine. + pac::PSM.frce_off().write_and_wait(|w| w.set_proc1(true)); + pac::PSM.frce_off().write_and_wait(|_| {}); + } } /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.