diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 1c83e306d..4602e66f4 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -352,6 +352,50 @@ pub fn init(config: config::Config) -> Peripherals {
     peripherals
 }
 
+#[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.
+    // Since we're using SIO spinlock 31 for the critical-section impl, this causes random
+    // hangs if we reset in the middle of a CS, because the next boot sees the spinlock
+    // as locked and waits forever.
+    //
+    // See https://github.com/embassy-rs/embassy/issues/1736
+    // and https://github.com/rp-rs/rp-hal/issues/292
+    // and https://matrix.to/#/!vhKMWjizPZBgKeknOo:matrix.org/$VfOkQgyf1PjmaXZbtycFzrCje1RorAXd8BQFHTl4d5M
+    //
+    // According to Raspberry Pi, this is considered Working As Intended, and not an errata,
+    // even though this behavior is different from every other ARM chip (sys_reset usually resets
+    // the *system* as its name implies, not just the current core).
+    //
+    // To fix this, reset SIO on boot. We must do this in pre_init because it's unsound to do it
+    // in `embassy_rp::init`, since the user could've acquired a CS by then. pre_init is guaranteed
+    // to run before any user code.
+    //
+    // A similar thing could happen with PROC1. It is unclear whether it's possible for PROC1
+    // to stay unreset through a PROC0 reset, so we reset it anyway just in case.
+    //
+    // Important info from PSM logic (from Luke Wren in above Matrix thread)
+    //
+    //     The logic is, each PSM stage is reset if either of the following is true:
+    //     - The previous stage is in reset and FRCE_ON is false
+    //     - FRCE_OFF is true
+    //
+    // 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(|w| {
+        w.set_proc0(true);
+    });
+    // Then reset SIO and PROC1.
+    pac::PSM.frce_off().write(|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(|_| {});
+    pac::PSM.frce_on().write(|_| {});
+}
+
 /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.
 trait RegExt<T: Copy> {
     #[allow(unused)]