aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/lib.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-02-05 00:46:30 +0100
committerDario Nieuwenhuis <[email protected]>2025-02-05 00:57:15 +0100
commitbb2d9ec7f81bbf0d83e873d53eb37f9d0b359f3b (patch)
tree5f969fc54abaed1fea866fd378c2dc48215f25b0 /embassy-rp/src/lib.rs
parenta2014c961d5ed1ebb665542aba208c60c9071cd5 (diff)
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.
Diffstat (limited to 'embassy-rp/src/lib.rs')
-rw-r--r--embassy-rp/src/lib.rs41
1 files 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 {
598 peripherals 598 peripherals
599} 599}
600 600
601#[cfg(all(feature = "rt", feature = "rp2040"))] 601#[cfg(feature = "rt")]
602#[cortex_m_rt::pre_init] 602#[cortex_m_rt::pre_init]
603unsafe fn pre_init() { 603unsafe fn pre_init() {
604 // SIO does not get reset when core0 is reset with either `scb::sys_reset()` or with SWD. 604 // 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() {
629 // 629 //
630 // The PSM order is SIO -> PROC0 -> PROC1. 630 // The PSM order is SIO -> PROC0 -> PROC1.
631 // So, we have to force-on PROC0 to prevent it from getting reset when resetting SIO. 631 // So, we have to force-on PROC0 to prevent it from getting reset when resetting SIO.
632 pac::PSM.frce_on().write_and_wait(|w| { 632 #[cfg(feature = "rp2040")]
633 w.set_proc0(true); 633 {
634 }); 634 pac::PSM.frce_on().write_and_wait(|w| {
635 // Then reset SIO and PROC1. 635 w.set_proc0(true);
636 pac::PSM.frce_off().write_and_wait(|w| { 636 });
637 w.set_sio(true); 637 // Then reset SIO and PROC1.
638 w.set_proc1(true); 638 pac::PSM.frce_off().write_and_wait(|w| {
639 }); 639 w.set_sio(true);
640 // clear force_off first, force_on second. The other way around would reset PROC0. 640 w.set_proc1(true);
641 pac::PSM.frce_off().write_and_wait(|_| {}); 641 });
642 pac::PSM.frce_on().write_and_wait(|_| {}); 642 // clear force_off first, force_on second. The other way around would reset PROC0.
643 pac::PSM.frce_off().write_and_wait(|_| {});
644 pac::PSM.frce_on().write_and_wait(|_| {});
645 }
646
647 #[cfg(feature = "_rp235x")]
648 {
649 // on RP235x, datasheet says "The FRCE_ON register is a development feature that does nothing in production devices."
650 // No idea why they removed it. Removing it means we can't use PSM to reset SIO, because it comes before
651 // PROC0, so we'd need FRCE_ON to prevent resetting ourselves.
652 //
653 // So we just unlock the spinlock manually.
654 pac::SIO.spinlock(31).write_value(1);
655
656 // We can still use PSM to reset PROC1 since it comes after PROC0 in the state machine.
657 pac::PSM.frce_off().write_and_wait(|w| w.set_proc1(true));
658 pac::PSM.frce_off().write_and_wait(|_| {});
659 }
643} 660}
644 661
645/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. 662/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.