1#![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
38const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0018 as _;
41
42const 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}