forked from M-Labs/thermostat
47 lines
1.2 KiB
Rust
47 lines
1.2 KiB
Rust
use core::arch::asm;
|
|
use cortex_m_rt::pre_init;
|
|
use stm32f4xx_hal::stm32::{RCC, SYSCFG};
|
|
|
|
const DFU_TRIG_MSG: u32 = 0xDECAFBAD;
|
|
|
|
extern "C" {
|
|
// This symbol comes from memory.x
|
|
static mut _dfu_msg: u32;
|
|
}
|
|
|
|
pub unsafe fn set_dfu_trigger() {
|
|
_dfu_msg = DFU_TRIG_MSG;
|
|
}
|
|
|
|
/// Called by reset handler in lib.rs immediately after reset.
|
|
/// This function should not be called outside of reset handler as
|
|
/// bootloader expects MCU to be in reset state when called.
|
|
#[cfg(target_arch = "arm")]
|
|
#[pre_init]
|
|
unsafe fn __pre_init() {
|
|
if _dfu_msg == DFU_TRIG_MSG {
|
|
_dfu_msg = 0x00000000;
|
|
|
|
// Enable system config controller clock
|
|
let rcc = &*RCC::ptr();
|
|
rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit());
|
|
|
|
// Bypass BOOT pins and remap bootloader to 0x00000000
|
|
let syscfg = &*SYSCFG::ptr();
|
|
syscfg.memrm.write(|w| w.mem_mode().bits(0b01));
|
|
|
|
// Impose instruction and memory barriers
|
|
cortex_m::asm::isb();
|
|
cortex_m::asm::dsb();
|
|
|
|
asm!(
|
|
// Set stack pointer to bootloader location
|
|
"LDR R0, =0x1FFF0000",
|
|
"LDR SP,[R0, #0]",
|
|
// Jump to bootloader
|
|
"LDR R0,[R0, #4]",
|
|
"BX R0",
|
|
);
|
|
}
|
|
}
|