When developing a Rust no_std
bootloader for my micro:bit v2.21 (Cortex-M4, nRF52833), I have encountered a weird error.
The bootloader jumps to the main application using cortex_m::asm::bootstrap(sp, pc);
call.
Out of curiosity, I wanted to see:
0x0
and 0x4
).I know I can peek into the vector table using objdump
, but I wanted to see it right from the code to ensure I am handing over the bootloader's control to the right place.
What an interesting journey this was :)
Anyway, I ran into a weird issue happening only in the debug
profile.
Using the rtt_target
and log
crates, I wanted to see the SP and PC values on flash and the values they point to in RAM.
When logging the content of the SP (dereferencing the value of the 0x0
address in flash), I got:
ERROR [cortex_sp_null] The panic handler was called with PanicInfo: panicked at src/main.rs:43:9:
null pointer dereference occurred
This is a simplified main fn
I used.
#[entry]
fn main() -> ! {
let flash_origin = 0x0u32;
// Load memory addresses from the Vector Table in Flash
let sp_ptr = flash_origin as *const u32; // Stack Pointer
let pc_ptr = (flash_origin + 4) as *const u32; // Program Counter pointer
unsafe {
info!("SP FLASH ADDRESS: {:#010X}", sp_ptr as usize);
info!("PC FLASH ADDRESS: {:#010X}", pc_ptr as usize);
info!("SP RAM ADDRESS: {:#010X}", *sp_ptr);
info!("PC RAM ADDRESS: {:#010X}", *pc_ptr);
}
loop { /* print the counter */ }
}
And this line caused the panic: info!("SP RAM ADDRESS: {:#010X}", *sp_ptr);
When building and flashing the code with the --release
parameter, the code runs fine and prints out:
INFO [cortex_sp_null] Started the application
INFO [cortex_sp_null] SP FLASH ADDRESS: 0x00000000
INFO [cortex_sp_null] PC FLASH ADDRESS: 0x00000004
INFO [cortex_sp_null] SP RAM ADDRESS: 0x20020000
INFO [cortex_sp_null] PC RAM ADDRESS: 0x00000401
INFO [cortex_sp_null] Counter: 0
INFO [cortex_sp_null] Counter: 1
Without the --release
parameter, though, I get:
INFO [cortex_sp_null] Started the application
INFO [cortex_sp_null] SP FLASH ADDRESS: 0x00000000
INFO [cortex_sp_null] PC FLASH ADDRESS: 0x00000004
ERROR [cortex_sp_null] The panic handler was called with PanicInfo: panicked at src/main.rs:43:9:
null pointer dereference occurred
Do you have any idea why this could be happening? I would have assumed that the behaviour should be the same regardless of the profile.
The simplified replication application is available on GitHub, including full replication steps in the README. https://github.com/lobodpav/cortex-sp-null
As I have learned, Rust considers a pointer to the 0x0
address as a null pointer. Hence, the runtime error.
The valid way to read from the 0x0
memory address is via the assembly language like so:
let sp_value: u32;
unsafe { core::arch::asm!("ldr {0}, [{1}]", out(reg) sp_value, in(reg) 0x0); };
info!("SP RAM ADDRESS: {:#010X}", sp_value);
The above code has printed the expected result:
INFO [cortex_sp_null] SP RAM ADDRESS: 0x20020000