2024-12-03 17:50:35 +01:00
|
|
|
use core::{mem::MaybeUninit, ptr::addr_of_mut};
|
2024-10-03 22:54:05 +02:00
|
|
|
|
|
|
|
|
use stm32f4xx_hal::pac;
|
|
|
|
|
|
|
|
|
|
fn jump_to_bootloader() {
|
|
|
|
|
unsafe {
|
|
|
|
|
cortex_m::interrupt::disable();
|
|
|
|
|
|
|
|
|
|
let address: u32 = 0x1FFF0000;
|
|
|
|
|
|
|
|
|
|
let device = pac::Peripherals::steal();
|
|
|
|
|
device.SYSCFG.memrm.modify(|_, w| w.bits(0x01));
|
|
|
|
|
|
|
|
|
|
let mut p = cortex_m::Peripherals::steal();
|
|
|
|
|
p.SCB.invalidate_icache();
|
|
|
|
|
p.SCB.vtor.write(address as u32);
|
|
|
|
|
|
|
|
|
|
cortex_m::interrupt::enable();
|
|
|
|
|
|
|
|
|
|
cortex_m::asm::bootload(address as *const u32);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const BOOTLOADER_REQUESTED: u32 = 0xdecafbad;
|
|
|
|
|
|
2024-12-03 17:50:35 +01:00
|
|
|
#[link_section = ".uninit.DFU_FLAG"]
|
|
|
|
|
static mut DFU_FLAG: MaybeUninit<u32> = MaybeUninit::uninit();
|
2024-10-03 22:54:05 +02:00
|
|
|
|
|
|
|
|
fn get_bootloader_flag() -> u32 {
|
2024-12-03 17:50:35 +01:00
|
|
|
unsafe { DFU_FLAG.assume_init() }
|
2024-10-03 22:54:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_bootloader_flag() {
|
2024-12-03 17:50:35 +01:00
|
|
|
unsafe { DFU_FLAG.write(BOOTLOADER_REQUESTED) };
|
2024-10-03 22:54:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_bootloader_flag() {
|
2024-12-03 17:50:35 +01:00
|
|
|
unsafe { DFU_FLAG.write(0) };
|
2024-10-03 22:54:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn init() {
|
|
|
|
|
let requested = get_bootloader_flag() == BOOTLOADER_REQUESTED;
|
|
|
|
|
if requested {
|
|
|
|
|
jump_to_bootloader();
|
|
|
|
|
}
|
2024-12-03 17:50:35 +01:00
|
|
|
|
|
|
|
|
clear_bootloader_flag();
|
2024-10-03 22:54:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn reboot_to_bootloader() -> ! {
|
|
|
|
|
defmt::info!("Rebooting into the bootloader");
|
|
|
|
|
set_bootloader_flag();
|
|
|
|
|
cortex_m::peripheral::SCB::sys_reset();
|
|
|
|
|
}
|