Triggering the dfu bootloader works
This commit is contained in:
parent
8cf75ac70d
commit
1c4714381b
9 changed files with 235 additions and 33 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
# TODO(2) replace `$CHIP` with your chip's name (see `probe-run --list-chips` output)
|
||||
runner = "probe-run --chip STM32F401CCU6"
|
||||
runner = "probe-rs run --chip STM32F401CCUx"
|
||||
rustflags = [
|
||||
"-C", "linker=flip-link",
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
|
|
|
|||
59
firmware/src/bootloader.rs
Normal file
59
firmware/src/bootloader.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use core::ptr::addr_of_mut;
|
||||
|
||||
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;
|
||||
|
||||
fn magic_mut_ptr() -> *mut u32 {
|
||||
extern "C" {
|
||||
#[link_name = "_dfu_magic"]
|
||||
static mut magic: u32;
|
||||
}
|
||||
|
||||
unsafe { addr_of_mut!(magic) }
|
||||
}
|
||||
|
||||
fn get_bootloader_flag() -> u32 {
|
||||
unsafe { magic_mut_ptr().read_volatile() }
|
||||
}
|
||||
|
||||
fn set_bootloader_flag() {
|
||||
unsafe { magic_mut_ptr().write_volatile(BOOTLOADER_REQUESTED) };
|
||||
}
|
||||
|
||||
fn clear_bootloader_flag() {
|
||||
unsafe { magic_mut_ptr().write_volatile(BOOTLOADER_REQUESTED) };
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
let requested = get_bootloader_flag() == BOOTLOADER_REQUESTED;
|
||||
if requested {
|
||||
clear_bootloader_flag();
|
||||
jump_to_bootloader();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reboot_to_bootloader() -> ! {
|
||||
defmt::info!("Rebooting into the bootloader");
|
||||
set_bootloader_flag();
|
||||
cortex_m::peripheral::SCB::sys_reset();
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ use defmt_brtt as _; // global logger
|
|||
use panic_probe as _;
|
||||
use stm32f4xx_hal as _;
|
||||
|
||||
mod bootloader;
|
||||
|
||||
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
|
||||
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
|
||||
#[defmt::panic_handler]
|
||||
|
|
@ -21,7 +23,9 @@ mod app {
|
|||
|
||||
use as5048a::AS5048A;
|
||||
|
||||
use heapless::Vec;
|
||||
use core::fmt::Write;
|
||||
use heapless::{String, Vec};
|
||||
use num_traits::{Float, FloatConst};
|
||||
use postcard::{from_bytes_cobs, to_vec_cobs};
|
||||
use stm32f4xx_hal::{
|
||||
gpio::{gpioa, gpiob, gpioc, Output, PushPull},
|
||||
|
|
@ -29,20 +33,19 @@ mod app {
|
|||
otg_fs::{UsbBus, UsbBusType, USB},
|
||||
pac::{I2C1, SPI1},
|
||||
prelude::*,
|
||||
spi,
|
||||
signature, spi,
|
||||
};
|
||||
use usb_device::class_prelude::UsbBusAllocator;
|
||||
use usb_device::prelude::*;
|
||||
use usb_device::{class_prelude::UsbBusAllocator, device};
|
||||
use usbd_serial::SerialPort;
|
||||
|
||||
use num_traits::{Float, FloatConst};
|
||||
|
||||
use xca9548a::{SlaveAddr, Xca9548a};
|
||||
|
||||
use qmc5883l::{self, QMC5883L};
|
||||
|
||||
use radomctl_protocol::*;
|
||||
|
||||
use crate::bootloader;
|
||||
use rtic_monotonics::systick::prelude::*;
|
||||
|
||||
systick_monotonic!(Mono, 4000);
|
||||
|
|
@ -83,6 +86,8 @@ mod app {
|
|||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
bootloader::init();
|
||||
|
||||
defmt::info!("init");
|
||||
|
||||
let rcc = cx.device.RCC.constrain();
|
||||
|
|
@ -92,11 +97,8 @@ mod app {
|
|||
let clocks = rcc
|
||||
.cfgr
|
||||
.use_hse(25.MHz())
|
||||
.require_pll48clk()
|
||||
.sysclk(84.MHz())
|
||||
.hclk(84.MHz())
|
||||
.pclk1(42.MHz())
|
||||
.pclk2(84.MHz())
|
||||
.require_pll48clk()
|
||||
.freeze();
|
||||
|
||||
Mono::start(cx.core.SYST, clocks.sysclk().to_Hz());
|
||||
|
|
@ -131,16 +133,23 @@ mod app {
|
|||
|
||||
let usb_serial = usbd_serial::SerialPort::new(unsafe { USB_BUS.as_ref().unwrap() });
|
||||
|
||||
let usb_dev = UsbDeviceBuilder::new(
|
||||
unsafe { USB_BUS.as_ref().unwrap() },
|
||||
UsbVidPid(0x16c0, 0x27dd),
|
||||
)
|
||||
.device_class(usbd_serial::USB_CLASS_CDC)
|
||||
.strings(&[StringDescriptors::default()
|
||||
.manufacturer("Amteurfunk Forschungs Gruppe")
|
||||
.product("Radom Controler")])
|
||||
.unwrap()
|
||||
.build();
|
||||
let uid = signature::Uid::get();
|
||||
|
||||
static mut SERIAL: String<16> = String::new();
|
||||
unsafe {
|
||||
write!(SERIAL, "{}{:x}{:x}", uid.lot_num(), uid.x(), uid.y()).unwrap();
|
||||
}
|
||||
|
||||
let usb_dev = unsafe {
|
||||
UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0x16c0, 0x27dd))
|
||||
.device_class(usbd_serial::USB_CLASS_CDC)
|
||||
.strings(&[StringDescriptors::default()
|
||||
.manufacturer("Amteurfunk Forschungs Gruppe")
|
||||
.product("Radom Controler")
|
||||
.serial_number(SERIAL.as_ref())])
|
||||
.unwrap()
|
||||
.build()
|
||||
};
|
||||
|
||||
defmt::info!("USB Setup done");
|
||||
|
||||
|
|
@ -416,9 +425,11 @@ mod app {
|
|||
to_vec_cobs::<RadomMessage, USB_BUFFER_SIZE>(&device_msg).unwrap();
|
||||
serial.write(bytes.as_slice()).unwrap();
|
||||
}
|
||||
HostMessage::TriggerDFUBootloader => todo!(),
|
||||
HostMessage::TriggerDFUBootloader => {
|
||||
bootloader::reboot_to_bootloader();
|
||||
}
|
||||
},
|
||||
Err(err) => defmt::error!("Unable to parse host message: {}", err),
|
||||
Err(err) => defmt::error!("Unable to parse host message"),
|
||||
};
|
||||
|
||||
*buffer = Vec::<u8, USB_BUFFER_SIZE>::from_slice(rest).unwrap();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue