panic_usb_boot/
lib.rs

1//! Set the panicking behavior to reset into the usb boot interface
2//!
3//! This crate contains an implementation of `panic_fmt` that calls the rp2040's ROM function to reset to usb boot
4//!
5//! # Usage
6//!
7//! ``` ignore
8//! #![no_std]
9//!
10//! extern crate panic_usb_boot;
11//!
12//! fn main() {
13//!     panic!("argument is ignored");
14//! }
15//! ```
16//!
17//! # Breakable symbols
18//!
19//! With the panic handler being `#[inline(never)]` the symbol `rust_begin_unwind` will be
20//! available to place a breakpoint on to halt when a panic is happening.
21
22#![no_std]
23
24#[cfg(all(feature="usb_mass_storage", feature="picoboot"))]
25const DISABLE_INTEFACE_MASK: u32 = 0;
26#[cfg(all(not(feature="usb_mass_storage"), feature="picoboot"))]
27const DISABLE_INTEFACE_MASK: u32 = 1;
28#[cfg(all(feature="usb_mass_storage", not(feature="picoboot")))]
29const DISABLE_INTEFACE_MASK: u32 = 2;
30#[cfg(all(not(feature="usb_mass_storage"), not(feature="picoboot")))]
31const DISABLE_INTEFACE_MASK: u32 = compile_error!("No interface was selected.\nEnable at least one of the folliwing crate features:\n- picoboot\n- usb_mass_storage\n");
32
33use core::panic::PanicInfo;
34
35type ResetToUsbBootFn = unsafe extern "C" fn(u32, u32) -> !;
36type RomTableLookupFn<T> = unsafe extern "C" fn(*const u16, u32) -> T;
37
38/// The following addresses are described at `2.8.2. Bootrom Contents`
39/// Pointer to the lookup table function supplied by the rom.
40const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0018 as _;
41
42/// Pointer to helper functions lookup table.
43const FUNC_TABLE: *const u16 = 0x0000_0014 as _;
44
45unsafe fn rom_hword_as_ptr(rom_address: *const u16) -> *const u32 {
46    let ptr: u16 = *rom_address;
47    ptr as *const u32
48}
49
50#[inline(never)]
51#[panic_handler]
52unsafe fn panic(_info: &PanicInfo) -> ! {
53    let rom_table_lookup_ptr: *const u32 = rom_hword_as_ptr(ROM_TABLE_LOOKUP_PTR);
54    let rom_table_lookup_fn: RomTableLookupFn<ResetToUsbBootFn> = core::mem::transmute(rom_table_lookup_ptr);
55    let reset_to_usb_boot = rom_table_lookup_fn(
56        rom_hword_as_ptr(FUNC_TABLE) as *const u16,
57        u16::from_le_bytes(*b"UB") as u32,
58    );
59    loop {
60        reset_to_usb_boot(0_u32, DISABLE_INTEFACE_MASK);
61    }
62}