rp2040_bootsel_via_double_reset/
lib.rs

1//! Enable bootsel via double reset.
2#![no_std]
3
4use core::{arch::asm, mem::MaybeUninit};
5
6use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayMs;
7use rp2040_hal::Timer;
8
9pub fn probe_double_reset(delay: &mut Timer) {
10    #[link_section = ".uninit"]
11    static mut FLAG: MaybeUninit<u32> = MaybeUninit::uninit();
12
13    let mut flag: u32;
14    unsafe {
15        asm!(
16            "ldr {flag}, [{addr}]",
17            addr  = in(reg) FLAG.as_ptr(),
18            flag = out(reg) flag,
19        );
20    }
21
22    if flag == 0x0B0075E1 {
23        unsafe { FLAG.write(0) };
24        delay.delay_ms(500);
25        // trigger bootsel
26        rp2040_hal::rom_data::reset_to_usb_boot(0, 0);
27        #[allow(clippy::empty_loop)]
28        loop {}
29    } else {
30        let value = 0x0B0075E1;
31        unsafe {
32            asm!(
33                "str {value}, [{addr}]",
34                addr = in(reg) FLAG.as_ptr(),
35                value = in(reg) value,
36            );
37        }
38        core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
39        delay.delay_ms(500);
40        let value = 0;
41        unsafe {
42            asm!(
43                "str {value}, [{addr}]",
44                addr = in(reg) FLAG.as_ptr(),
45                value = in(reg) value,
46            );
47        }
48    }
49}