From e82eceab23a7cfb12debbc3f875b03650daa0925 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 16 May 2023 21:39:32 +0000 Subject: [PATCH 1/4] Implement reset() and halt() functions --- rp2040-hal/src/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index 080d58991..d9587ce71 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -92,3 +92,48 @@ pub use sio::Sio; pub use spi::Spi; pub use timer::Timer; pub use watchdog::Watchdog; + +/// Trigger full reset of the RP2040. +/// +/// When called from core0, it will shut down core1 and +/// then call `SCB::sys_reset()`, which keeps the debug +/// connection active. +/// +/// This is not possible when called from core1. It will +/// trigger a watchdog reset of the whole system instead, +/// which breaks a running debug connection. +pub fn reset() -> ! { + unsafe { + if crate::Sio::core() == 0 { + (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()); + pac::SCB::sys_reset(); + } else { + (*pac::PSM::PTR).wdsel.write(|w| w.bits(0x0000ffff)); + (*pac::WATCHDOG::PTR).ctrl.write(|w| w.trigger().set_bit()); + } + #[allow(clippy::empty_loop)] + loop {} + } +} + +/// Halt the RP2040. +/// +/// Completely disables the other core, and parks the current core in an +/// infinite loop with interrupts disabled. +/// +/// Doesn't stop other subsystems. +pub fn halt() -> ! { + unsafe { + cortex_m::interrupt::disable(); + // Stop other core + if crate::Sio::core() == 0 { + (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()); + } else { + (*pac::PSM::PTR).frce_off.write(|w| w.proc0().set_bit()); + } + // Keep current core running, so debugging stays possible + loop { + cortex_m::asm::wfe() + } + } +} From 5b6afe15a193f1aee87b1843ac25a4242fc32123 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Sat, 22 Jul 2023 10:34:11 +0000 Subject: [PATCH 2/4] Adapt to changes from #585 --- rp2040-hal/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index d9587ce71..ce9f035d0 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -88,6 +88,7 @@ pub use i2c::I2C; /// of `main`. As spinlocks are not automatically unlocked on software resets, /// this can prevent unexpected deadlocks when running from a debugger. pub use rp2040_hal_macros::entry; +use sio::CoreId; pub use sio::Sio; pub use spi::Spi; pub use timer::Timer; @@ -104,7 +105,7 @@ pub use watchdog::Watchdog; /// which breaks a running debug connection. pub fn reset() -> ! { unsafe { - if crate::Sio::core() == 0 { + if crate::Sio::core() == CoreId::Core0 { (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()); pac::SCB::sys_reset(); } else { @@ -126,7 +127,7 @@ pub fn halt() -> ! { unsafe { cortex_m::interrupt::disable(); // Stop other core - if crate::Sio::core() == 0 { + if crate::Sio::core() == CoreId::Core0 { (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()); } else { (*pac::PSM::PTR).frce_off.write(|w| w.proc0().set_bit()); From adfa1a236be38246d1b699310a585ef4414123be Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Sat, 22 Jul 2023 14:08:06 +0000 Subject: [PATCH 3/4] Do a full reset, even though it breaks an open debug connection --- rp2040-hal/src/lib.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index ce9f035d0..9996b9521 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -96,22 +96,12 @@ pub use watchdog::Watchdog; /// Trigger full reset of the RP2040. /// -/// When called from core0, it will shut down core1 and -/// then call `SCB::sys_reset()`, which keeps the debug -/// connection active. -/// -/// This is not possible when called from core1. It will -/// trigger a watchdog reset of the whole system instead, -/// which breaks a running debug connection. +/// Uses the watchdog and the power-on state machine (PSM) to reset all on-chip components. pub fn reset() -> ! { unsafe { - if crate::Sio::core() == CoreId::Core0 { - (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()); - pac::SCB::sys_reset(); - } else { - (*pac::PSM::PTR).wdsel.write(|w| w.bits(0x0000ffff)); - (*pac::WATCHDOG::PTR).ctrl.write(|w| w.trigger().set_bit()); - } + cortex_m::interrupt::disable(); + (*pac::PSM::PTR).wdsel.write(|w| w.bits(0x0001ffff)); + (*pac::WATCHDOG::PTR).ctrl.write(|w| w.trigger().set_bit()); #[allow(clippy::empty_loop)] loop {} } @@ -122,7 +112,7 @@ pub fn reset() -> ! { /// Completely disables the other core, and parks the current core in an /// infinite loop with interrupts disabled. /// -/// Doesn't stop other subsystems. +/// Doesn't stop other subsystems, like the DMA controller. pub fn halt() -> ! { unsafe { cortex_m::interrupt::disable(); From 1aec0cba0cd0b0caad511a6632c87d73e36a72db Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 22 Aug 2023 20:25:34 +0000 Subject: [PATCH 4/4] Use match instead of if/else --- rp2040-hal/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index 9996b9521..376686b2b 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -117,10 +117,9 @@ pub fn halt() -> ! { unsafe { cortex_m::interrupt::disable(); // Stop other core - if crate::Sio::core() == CoreId::Core0 { - (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()); - } else { - (*pac::PSM::PTR).frce_off.write(|w| w.proc0().set_bit()); + match crate::Sio::core() { + CoreId::Core0 => (*pac::PSM::PTR).frce_off.write(|w| w.proc1().set_bit()), + CoreId::Core1 => (*pac::PSM::PTR).frce_off.write(|w| w.proc0().set_bit()), } // Keep current core running, so debugging stays possible loop {