From 5a53b7167140e09b7c5ae9a627d55cae656f4f1e Mon Sep 17 00:00:00 2001 From: topquark12 Date: Tue, 12 Jan 2021 14:56:58 +0800 Subject: [PATCH 1/8] dfu: working software triggered dfu --- memory.x | 4 +++- src/command_parser.rs | 2 ++ src/main.rs | 52 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/memory.x b/memory.x index 213f9a1..5366550 100644 --- a/memory.x +++ b/memory.x @@ -3,7 +3,9 @@ MEMORY FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K /* reserved for config data */ CONFIG (rx) : ORIGIN = 0x8100000, LENGTH = 16K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 111K + /* reserved for DFU trigger message */ + DFU_MSG (wrx) : ORIGIN = 0x2001BC00, LENGTH = 1K RAM2 (xrw) : ORIGIN = 0x2001C000, LENGTH = 16K RAM3 (xrw) : ORIGIN = 0x20020000, LENGTH = 64K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K diff --git a/src/command_parser.rs b/src/command_parser.rs index db1ea8f..09fac7b 100644 --- a/src/command_parser.rs +++ b/src/command_parser.rs @@ -179,6 +179,7 @@ pub enum Command { channel: usize, rate: Option, }, + Dfu, } fn end(input: &[u8]) -> IResult<&[u8], ()> { @@ -535,6 +536,7 @@ fn command(input: &[u8]) -> IResult<&[u8], Result> { pid, steinhart_hart, postfilter, + value(Ok(Command::Dfu), tag("dfu")), ))(input) } diff --git a/src/main.rs b/src/main.rs index c745a8f..555673c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_main)] -#![feature(maybe_uninit_extra, maybe_uninit_ref)] +#![feature(maybe_uninit_extra, maybe_uninit_ref, asm)] #![cfg_attr(test, allow(unused))] // TODO: #![deny(warnings, unused)] @@ -13,7 +13,7 @@ use log::{error, info, warn}; use core::fmt::Write; use cortex_m::asm::wfi; -use cortex_m_rt::entry; +use cortex_m_rt::{entry, pre_init}; use stm32f4xx_hal::{ hal::watchdog::{WatchdogEnable, Watchdog}, rcc::RccExt, @@ -77,6 +77,8 @@ const CHANNEL_CONFIG_KEY: [&str; 2] = ["ch0", "ch1"]; const TCP_PORT: u16 = 23; +const DFU_MSG_ADDR: usize = 0x2001BC00; +const DFU_TRIG_MSG: usize = 0xDECAFBAD; fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool { let send_free = socket.send_capacity() - socket.send_queue(); @@ -422,6 +424,18 @@ fn main() -> ! { channels.power_down(i); } + SCB::sys_reset(); + } + Command::Dfu => { + for i in 0..CHANNELS { + channels.power_down(i); + } + + unsafe { + let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; + *dfu_msg_addr = DFU_TRIG_MSG; + } + SCB::sys_reset(); } } @@ -473,3 +487,37 @@ fn main() -> ! { unreachable!() } + +#[pre_init] +#[no_mangle] +unsafe fn __pre_init() { + + let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; + + if *dfu_msg_addr == DFU_TRIG_MSG{ + + *dfu_msg_addr = 0x00000000; + + const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; + const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000; + + core::ptr::write_volatile( + RCC_APB2ENR, + *RCC_APB2ENR | RCC_APB2ENR_ENABLE_SYSCFG_CLOCK, + ); + + const SYSCFG_MEMRMP: *mut u32 = 0x40013800 as *mut u32; + const SYSCFG_MEMRMP_MAP_ROM: u32 = 0x00000001; + + core::ptr::write_volatile( + SYSCFG_MEMRMP, + *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, + ); + + asm!("LDR R0, =0x1FFF0000"); + asm!("LDR SP,[R0, #0]"); + asm!("LDR R0,[R0, #4]"); + asm!("BX R0"); + } + +} \ No newline at end of file -- 2.44.1 From 5cf91eb7ea0ac1ee8bbeac640eaa68d9315e4936 Mon Sep 17 00:00:00 2001 From: topquark12 Date: Tue, 12 Jan 2021 15:09:42 +0800 Subject: [PATCH 2/8] dfu: refactor --- src/dfu.rs | 43 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 59 ++++++++++++++++++++++++----------------------------- 2 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 src/dfu.rs diff --git a/src/dfu.rs b/src/dfu.rs new file mode 100644 index 0000000..89b473b --- /dev/null +++ b/src/dfu.rs @@ -0,0 +1,43 @@ +use cortex_m_rt::{pre_init}; + +const DFU_MSG_ADDR: usize = 0x2001BC00; +const DFU_TRIG_MSG: usize = 0xDECAFBAD; + +pub unsafe fn trig_dfu() { + let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; + *dfu_msg_addr = DFU_TRIG_MSG; +} + +#[pre_init] +#[no_mangle] +unsafe fn __pre_init() { + + let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; + + if *dfu_msg_addr == DFU_TRIG_MSG{ + + *dfu_msg_addr = 0x00000000; + + const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; + const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000; + + core::ptr::write_volatile( + RCC_APB2ENR, + *RCC_APB2ENR | RCC_APB2ENR_ENABLE_SYSCFG_CLOCK, + ); + + const SYSCFG_MEMRMP: *mut u32 = 0x40013800 as *mut u32; + const SYSCFG_MEMRMP_MAP_ROM: u32 = 0x00000001; + + core::ptr::write_volatile( + SYSCFG_MEMRMP, + *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, + ); + + asm!("LDR R0, =0x1FFF0000"); + asm!("LDR SP,[R0, #0]"); + asm!("LDR R0,[R0, #4]"); + asm!("BX R0"); + } + +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 555673c..0bae17a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use log::{error, info, warn}; use core::fmt::Write; use cortex_m::asm::wfi; -use cortex_m_rt::{entry, pre_init}; +use cortex_m_rt::{entry}; use stm32f4xx_hal::{ hal::watchdog::{WatchdogEnable, Watchdog}, rcc::RccExt, @@ -66,6 +66,7 @@ mod channel_state; mod config; use config::ChannelConfig; mod flash_store; +mod dfu; const HSE: MegaHertz = MegaHertz(8); #[cfg(not(feature = "semihosting"))] @@ -77,9 +78,6 @@ const CHANNEL_CONFIG_KEY: [&str; 2] = ["ch0", "ch1"]; const TCP_PORT: u16 = 23; -const DFU_MSG_ADDR: usize = 0x2001BC00; -const DFU_TRIG_MSG: usize = 0xDECAFBAD; - fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool { let send_free = socket.send_capacity() - socket.send_queue(); if data.len() > send_free + 1 { @@ -430,12 +428,9 @@ fn main() -> ! { for i in 0..CHANNELS { channels.power_down(i); } - unsafe { - let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; - *dfu_msg_addr = DFU_TRIG_MSG; + dfu::trig_dfu(); } - SCB::sys_reset(); } } @@ -488,36 +483,36 @@ fn main() -> ! { unreachable!() } -#[pre_init] -#[no_mangle] -unsafe fn __pre_init() { +// #[pre_init] +// #[no_mangle] +// unsafe fn __pre_init() { - let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; +// let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; - if *dfu_msg_addr == DFU_TRIG_MSG{ +// if *dfu_msg_addr == DFU_TRIG_MSG{ - *dfu_msg_addr = 0x00000000; +// *dfu_msg_addr = 0x00000000; - const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; - const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000; +// const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; +// const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000; - core::ptr::write_volatile( - RCC_APB2ENR, - *RCC_APB2ENR | RCC_APB2ENR_ENABLE_SYSCFG_CLOCK, - ); +// core::ptr::write_volatile( +// RCC_APB2ENR, +// *RCC_APB2ENR | RCC_APB2ENR_ENABLE_SYSCFG_CLOCK, +// ); - const SYSCFG_MEMRMP: *mut u32 = 0x40013800 as *mut u32; - const SYSCFG_MEMRMP_MAP_ROM: u32 = 0x00000001; +// const SYSCFG_MEMRMP: *mut u32 = 0x40013800 as *mut u32; +// const SYSCFG_MEMRMP_MAP_ROM: u32 = 0x00000001; - core::ptr::write_volatile( - SYSCFG_MEMRMP, - *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, - ); +// core::ptr::write_volatile( +// SYSCFG_MEMRMP, +// *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, +// ); - asm!("LDR R0, =0x1FFF0000"); - asm!("LDR SP,[R0, #0]"); - asm!("LDR R0,[R0, #4]"); - asm!("BX R0"); - } +// asm!("LDR R0, =0x1FFF0000"); +// asm!("LDR SP,[R0, #0]"); +// asm!("LDR R0,[R0, #4]"); +// asm!("BX R0"); +// } -} \ No newline at end of file +// } \ No newline at end of file -- 2.44.1 From c861f2df836599a4bf2886a0cfbabd1ace9f5b4d Mon Sep 17 00:00:00 2001 From: topquark12 Date: Tue, 12 Jan 2021 15:27:30 +0800 Subject: [PATCH 3/8] dfu: documentation --- src/dfu.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/dfu.rs b/src/dfu.rs index 89b473b..0668a88 100644 --- a/src/dfu.rs +++ b/src/dfu.rs @@ -1,23 +1,30 @@ use cortex_m_rt::{pre_init}; +/// RAM location used to store DFU trigger message const DFU_MSG_ADDR: usize = 0x2001BC00; + +/// DFU trigger message const DFU_TRIG_MSG: usize = 0xDECAFBAD; +/// Set DFU trigger message pub unsafe fn trig_dfu() { let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; *dfu_msg_addr = DFU_TRIG_MSG; } +/// Called by reset handler in lib.rs immediately after reset, checks if booting into dfu is needed #[pre_init] -#[no_mangle] unsafe fn __pre_init() { let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; + // Check DFU trigger message if *dfu_msg_addr == DFU_TRIG_MSG{ + // Reset message *dfu_msg_addr = 0x00000000; + // Enable system config controller clock const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000; @@ -26,6 +33,7 @@ unsafe fn __pre_init() { *RCC_APB2ENR | RCC_APB2ENR_ENABLE_SYSCFG_CLOCK, ); + // Bypass BOOT pins and remap bootloader to 0x00000000 const SYSCFG_MEMRMP: *mut u32 = 0x40013800 as *mut u32; const SYSCFG_MEMRMP_MAP_ROM: u32 = 0x00000001; @@ -34,8 +42,11 @@ unsafe fn __pre_init() { *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, ); + // Set stack pointer to bootloader location asm!("LDR R0, =0x1FFF0000"); asm!("LDR SP,[R0, #0]"); + + // Jump to bootloader asm!("LDR R0,[R0, #4]"); asm!("BX R0"); } -- 2.44.1 From e41415f82ced313e4f440c318f7dbac88ea13e7d Mon Sep 17 00:00:00 2001 From: topquark12 Date: Tue, 12 Jan 2021 15:36:29 +0800 Subject: [PATCH 4/8] dfu: clean up --- src/dfu.rs | 4 ++-- src/main.rs | 36 +----------------------------------- 2 files changed, 3 insertions(+), 37 deletions(-) diff --git a/src/dfu.rs b/src/dfu.rs index 0668a88..0e40935 100644 --- a/src/dfu.rs +++ b/src/dfu.rs @@ -3,10 +3,10 @@ use cortex_m_rt::{pre_init}; /// RAM location used to store DFU trigger message const DFU_MSG_ADDR: usize = 0x2001BC00; -/// DFU trigger message +/// DFU trigger message const DFU_TRIG_MSG: usize = 0xDECAFBAD; -/// Set DFU trigger message +/// Set DFU trigger pub unsafe fn trig_dfu() { let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; *dfu_msg_addr = DFU_TRIG_MSG; diff --git a/src/main.rs b/src/main.rs index 0bae17a..142278f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use log::{error, info, warn}; use core::fmt::Write; use cortex_m::asm::wfi; -use cortex_m_rt::{entry}; +use cortex_m_rt::entry; use stm32f4xx_hal::{ hal::watchdog::{WatchdogEnable, Watchdog}, rcc::RccExt, @@ -482,37 +482,3 @@ fn main() -> ! { unreachable!() } - -// #[pre_init] -// #[no_mangle] -// unsafe fn __pre_init() { - -// let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; - -// if *dfu_msg_addr == DFU_TRIG_MSG{ - -// *dfu_msg_addr = 0x00000000; - -// const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; -// const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000; - -// core::ptr::write_volatile( -// RCC_APB2ENR, -// *RCC_APB2ENR | RCC_APB2ENR_ENABLE_SYSCFG_CLOCK, -// ); - -// const SYSCFG_MEMRMP: *mut u32 = 0x40013800 as *mut u32; -// const SYSCFG_MEMRMP_MAP_ROM: u32 = 0x00000001; - -// core::ptr::write_volatile( -// SYSCFG_MEMRMP, -// *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, -// ); - -// asm!("LDR R0, =0x1FFF0000"); -// asm!("LDR SP,[R0, #0]"); -// asm!("LDR R0,[R0, #4]"); -// asm!("BX R0"); -// } - -// } \ No newline at end of file -- 2.44.1 From a320b6104e228090c81a5821a6dce0dc44d18474 Mon Sep 17 00:00:00 2001 From: topquark12 Date: Tue, 12 Jan 2021 15:46:50 +0800 Subject: [PATCH 5/8] dfu: update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a3ba034..a6fe73e 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ formatted as line-delimited JSON. | `load [0/1]` | Restore configuration for channel all/0/1 from flash | | `save [0/1]` | Save configuration for channel all/0/1 to flash | | `reset` | Reset the device | +| `dfu` | Reset device and enters USB device firmware update (DFU) mode | | `ipv4 [Y.Y.Y.Y]` | Configure IPv4 address, netmask length, and optional default gateway | -- 2.44.1 From 2e6116016ac2b9918f33e1b885d068631d7ffb40 Mon Sep 17 00:00:00 2001 From: topquark12 Date: Wed, 13 Jan 2021 11:06:06 +0800 Subject: [PATCH 6/8] dfu: refactor for PR --- README.md | 2 +- memory.x | 5 +++-- src/dfu.rs | 49 +++++++++++++++++++++++-------------------------- src/main.rs | 3 ++- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index a6fe73e..89dc63a 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ formatted as line-delimited JSON. | `load [0/1]` | Restore configuration for channel all/0/1 from flash | | `save [0/1]` | Save configuration for channel all/0/1 to flash | | `reset` | Reset the device | -| `dfu` | Reset device and enters USB device firmware update (DFU) mode | +| `dfu` | Reset device and enters USB device firmware update (DFU) mode | | `ipv4 [Y.Y.Y.Y]` | Configure IPv4 address, netmask length, and optional default gateway | diff --git a/memory.x b/memory.x index 5366550..c0ae171 100644 --- a/memory.x +++ b/memory.x @@ -3,12 +3,13 @@ MEMORY FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K /* reserved for config data */ CONFIG (rx) : ORIGIN = 0x8100000, LENGTH = 16K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 111K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K - 4 /* reserved for DFU trigger message */ - DFU_MSG (wrx) : ORIGIN = 0x2001BC00, LENGTH = 1K + DFU_MSG (wrx) : ORIGIN = 0x2001BFFC, LENGTH = 4 RAM2 (xrw) : ORIGIN = 0x2001C000, LENGTH = 16K RAM3 (xrw) : ORIGIN = 0x20020000, LENGTH = 64K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K } _stack_start = ORIGIN(CCMRAM) + LENGTH(CCMRAM); +_dfu_msg = ORIGIN(DFU_MSG); diff --git a/src/dfu.rs b/src/dfu.rs index 0e40935..0af4e38 100644 --- a/src/dfu.rs +++ b/src/dfu.rs @@ -1,28 +1,25 @@ use cortex_m_rt::{pre_init}; -/// RAM location used to store DFU trigger message -const DFU_MSG_ADDR: usize = 0x2001BC00; +const DFU_TRIG_MSG: u32 = 0xDECAFBAD; -/// DFU trigger message -const DFU_TRIG_MSG: usize = 0xDECAFBAD; - -/// Set DFU trigger -pub unsafe fn trig_dfu() { - let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; - *dfu_msg_addr = DFU_TRIG_MSG; +pub unsafe fn set_dfu_trigger() { + extern "C" { + static mut _dfu_msg: u32; + } + _dfu_msg = DFU_TRIG_MSG; } -/// Called by reset handler in lib.rs immediately after reset, checks if booting into dfu is needed +/// 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. #[pre_init] unsafe fn __pre_init() { + extern "C" { + static mut _dfu_msg: u32; + } - let dfu_msg_addr = DFU_MSG_ADDR as *mut usize; - - // Check DFU trigger message - if *dfu_msg_addr == DFU_TRIG_MSG{ - - // Reset message - *dfu_msg_addr = 0x00000000; + if _dfu_msg == DFU_TRIG_MSG { + _dfu_msg = 0x00000000; // Enable system config controller clock const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32; @@ -41,14 +38,14 @@ unsafe fn __pre_init() { SYSCFG_MEMRMP, *SYSCFG_MEMRMP | SYSCFG_MEMRMP_MAP_ROM, ); - - // Set stack pointer to bootloader location - asm!("LDR R0, =0x1FFF0000"); - asm!("LDR SP,[R0, #0]"); - - // Jump to bootloader - asm!("LDR R0,[R0, #4]"); - asm!("BX R0"); + + asm!( + // Set stack pointer to bootloader location + "LDR R0, =0x1FFF0000", + "LDR SP,[R0, #0]", + // Jump to bootloader + "LDR R0,[R0, #4]", + "BX R0", + ); } - } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 142278f..8cf4b6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -429,8 +429,9 @@ fn main() -> ! { channels.power_down(i); } unsafe { - dfu::trig_dfu(); + dfu::set_dfu_trigger(); } + socket.close(); SCB::sys_reset(); } } -- 2.44.1 From 251e4d3dd4a7919ac002843807807a44931a3e64 Mon Sep 17 00:00:00 2001 From: topquark12 Date: Wed, 13 Jan 2021 11:16:57 +0800 Subject: [PATCH 7/8] dfu: cleanup --- src/dfu.rs | 11 ++++------- src/main.rs | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/dfu.rs b/src/dfu.rs index 0af4e38..9ac6727 100644 --- a/src/dfu.rs +++ b/src/dfu.rs @@ -2,10 +2,11 @@ use cortex_m_rt::{pre_init}; const DFU_TRIG_MSG: u32 = 0xDECAFBAD; +extern "C" { + static mut _dfu_msg: u32; +} + pub unsafe fn set_dfu_trigger() { - extern "C" { - static mut _dfu_msg: u32; - } _dfu_msg = DFU_TRIG_MSG; } @@ -14,10 +15,6 @@ pub unsafe fn set_dfu_trigger() { /// bootloader expects MCU to be in reset state when called. #[pre_init] unsafe fn __pre_init() { - extern "C" { - static mut _dfu_msg: u32; - } - if _dfu_msg == DFU_TRIG_MSG { _dfu_msg = 0x00000000; diff --git a/src/main.rs b/src/main.rs index 8cf4b6b..7f29472 100644 --- a/src/main.rs +++ b/src/main.rs @@ -431,7 +431,7 @@ fn main() -> ! { unsafe { dfu::set_dfu_trigger(); } - socket.close(); + SCB::sys_reset(); } } -- 2.44.1 From 253bebd9d55523aa34e590015f8860552e91aaa0 Mon Sep 17 00:00:00 2001 From: topquark12 Date: Wed, 13 Jan 2021 11:50:09 +0800 Subject: [PATCH 8/8] dfu: document _dfu_msg --- src/dfu.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dfu.rs b/src/dfu.rs index 9ac6727..95a4085 100644 --- a/src/dfu.rs +++ b/src/dfu.rs @@ -3,6 +3,7 @@ use cortex_m_rt::{pre_init}; const DFU_TRIG_MSG: u32 = 0xDECAFBAD; extern "C" { + // This symbol comes from memory.x static mut _dfu_msg: u32; } -- 2.44.1