aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-02-05 00:06:41 +0000
committerGitHub <[email protected]>2025-02-05 00:06:41 +0000
commit556cc57c1fdc9eba0703ccc2281d39462d2d2c38 (patch)
treeabb8272abec426e26ed8a2999781139f41cf972f
parentfdb9795d6acba52cb023e54e2eb409ad78bdb451 (diff)
parent9da04cc38ea5cc17740bd9921f9f5cbb1c689a31 (diff)
Merge pull request #3851 from embassy-rs/rp23-atomics-fix
rp235x: fix atomics, fix SIO spinlock stuck bug, fix missing core1 reset.
-rw-r--r--embassy-rp/src/lib.rs59
-rw-r--r--embassy-rp/src/multicore.rs4
2 files changed, 51 insertions, 12 deletions
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index f0893b5a0..80ee47802 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,52 @@ 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
660 // Make atomics work between cores.
661 enable_actlr_extexclall();
662 }
663}
664
665/// Set the EXTEXCLALL bit in ACTLR.
666///
667/// The default MPU memory map marks all memory as non-shareable, so atomics don't
668/// synchronize memory accesses between cores at all. This bit forces all memory to be
669/// considered shareable regardless of what the MPU says.
670///
671/// TODO: does this interfere somehow if the user wants to use a custom MPU configuration?
672/// maybe we need to add a way to disable this?
673///
674/// This must be done FOR EACH CORE.
675#[cfg(feature = "_rp235x")]
676unsafe fn enable_actlr_extexclall() {
677 (&*cortex_m::peripheral::ICB::PTR).actlr.modify(|w| w | (1 << 29));
643} 678}
644 679
645/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. 680/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.
diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs
index ea0a29a36..1450505b9 100644
--- a/embassy-rp/src/multicore.rs
+++ b/embassy-rp/src/multicore.rs
@@ -65,6 +65,10 @@ unsafe fn core1_setup(stack_bottom: *mut usize) {
65 // embassy, somehow. trap if so since we can't deal with that. 65 // embassy, somehow. trap if so since we can't deal with that.
66 cortex_m::asm::udf(); 66 cortex_m::asm::udf();
67 } 67 }
68
69 #[cfg(feature = "_rp235x")]
70 crate::enable_actlr_extexclall();
71
68 unsafe { 72 unsafe {
69 gpio::init(); 73 gpio::init();
70 } 74 }