1use core::{
2 ptr,
3 sync::atomic::{self, Ordering},
4};
5
6const DFU_FLAG: u32 = 0xDEAD_BEEF;
8
9unsafe extern "C" {
10 unsafe static mut _dfu_flag: u8;
11}
12
13pub fn dfu_reboot() {
15 unsafe {
16 ptr::write_unaligned(ptr::addr_of_mut!(_dfu_flag).cast(), DFU_FLAG);
17 }
18
19 cortex_m::peripheral::SCB::sys_reset();
20}
21
22pub fn dfu_flag_is_set() -> bool {
24 unsafe {
25 let start_ptr = ptr::addr_of_mut!(_dfu_flag).cast();
26 let set = DFU_FLAG == ptr::read_unaligned(start_ptr);
27
28 core::ptr::write_unaligned(start_ptr, 0);
30 atomic::fence(Ordering::SeqCst);
31 cortex_m::asm::dsb();
32 set
33 }
34}
35
36pub fn bootload_dfu() {
42 cortex_m::interrupt::disable();
45
46 let systick = unsafe { &*cortex_m::peripheral::SYST::PTR };
48 unsafe {
49 systick.csr.write(0);
50 systick.rvr.write(0);
51 systick.cvr.write(0);
52 }
53
54 let nvic = unsafe { &*cortex_m::peripheral::NVIC::PTR };
56 for reg in nvic.icer.iter() {
57 unsafe {
58 reg.write(u32::MAX);
59 }
60 }
61
62 for reg in nvic.icpr.iter() {
63 unsafe {
64 reg.write(u32::MAX);
65 }
66 }
67
68 unsafe { cortex_m::interrupt::enable() };
69
70 log::info!("Jumping to DFU");
71
72 unsafe {
75 cortex_m::asm::bootload(0x1FF0_9800 as _);
76 }
77}