software_dfu #46
43
src/dfu.rs
Normal file
43
src/dfu.rs
Normal file
@ -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() {
|
||||
sb10q
commented
Why not put it outside the functions so this declaration can be shared? Why not put it outside the functions so this declaration can be shared?
|
||||
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{
|
||||
sb10q
commented
see comment above see comment above
|
||||
|
||||
sb10q
commented
remove blank line remove blank line
|
||||
*dfu_msg_addr = 0x00000000;
|
||||
|
||||
const RCC_APB2ENR: *mut u32 = 0xE000_ED88 as *mut u32;
|
||||
const RCC_APB2ENR_ENABLE_SYSCFG_CLOCK: u32 = 0x00004000;
|
||||
sb10q
commented
space before { space before {
|
||||
|
||||
sb10q
commented
remove blank line remove blank line
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
59
src/main.rs
59
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();
|
||||
sb10q
commented
Does this work or do we need to wait for the network driver/hardware to actually send the packet? Does this work or do we need to wait for the network driver/hardware to actually send the packet?
What if there are other open sockets? Maybe address this entire issue in a second PR.
topquark12
commented
was just testing out the behavior of that, forgot to remove before committing. was just testing out the behavior of that, forgot to remove before committing.
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
Loading…
Reference in New Issue
Block a user
This can and should be automatically obtained via a linker symbol. See this example:
https://git.m-labs.hk/M-Labs/artiq-zynq/src/branch/master/src/runtime/src/kernel/core1.rs#L31-L36
https://git.m-labs.hk/M-Labs/artiq-zynq/src/branch/master/src/runtime/link.x#L10
The linker currently does not actually do anything to the ram carved out for the dfu trigger message, and I beleive there's no symbol generated for that chunk of memory.
I think I'll have to find the linker script the project is using, fork a copy, generate a symbol for that addr and use it in our project somehow.
Indeed, but the linker script can be modified so that such a symbol is generated. This way there isn't any value that needs to be manually synchronized in two places. You may not even need to hardcode the address; the linker could place that variable automatically.
Though hardcoding is actually more reliable since after a firmware update the address could have changed otherwise... add a comment that explains that.
The linker script is the second link I gave you.
I think specifying a region that only contains the DFU msg would be reasonable. This way the address would not be changed after update.
I thought that linker script is for a zynq? I am not sure where the linker script currently being used is placed, think it is packaged with one of the rust modules.
Okay, you mean the thermostat linker script.
That
memory.x
you modified can be used, as you can see it already defines the_stack_start
symbol.The stack is on CCM, the message is placed in RAM. I can try placing the msg in CCM, not sure what the reset behavior of CCM is yet.
@pca006132 There's already a dedicated region specified in memory.x . Though the linker does not do anything with that region, and I don't think the linker generates a symbol for that space.
I also haven't found the linker script of the project just yet.
The linker script is defined in
cortex-m-rt
, https://github.com/rust-embedded/cortex-m-rt/blob/master/link.x.inBut I'm not familiar with that, not sure how to add new symbols.
@topquark12 what's wrong with simply adding
at the end of thermostat's
memory.x
?