diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-02-05 00:06:41 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-02-05 00:06:41 +0000 |
| commit | 556cc57c1fdc9eba0703ccc2281d39462d2d2c38 (patch) | |
| tree | abb8272abec426e26ed8a2999781139f41cf972f | |
| parent | fdb9795d6acba52cb023e54e2eb409ad78bdb451 (diff) | |
| parent | 9da04cc38ea5cc17740bd9921f9f5cbb1c689a31 (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.rs | 59 | ||||
| -rw-r--r-- | embassy-rp/src/multicore.rs | 4 |
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] |
| 603 | unsafe fn pre_init() { | 603 | unsafe 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")] | ||
| 676 | unsafe 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 | } |
