Closed Acciente717 closed 3 years ago
Unfortunately rwpi is not fully supported by Rust on ARM at the moment. It turns out to be quite complicated; ARM contributed support to LLVM a while back of which some was merged but I don't believe anything has made it into Rust yet. If I remember correctly, I think anything static
or any vtables won't work because they need to be moved into sdata
instead of sbss
and relocated correctly, but are not. There was some earlier discussion of this on the rust-embedded Matrix chat here too.
It would be nice to have, but right now it's not something we can do anything about in this crate. If you find out anything more, please update this thread!
I successfully built and ran an OS binary image with rwpi. The code is here: https://github.com/Acciente717/mini-cortex-m4-os
Most of the code in boot.rs
is copied from cortex-m-rt
. I made some hack to the Reset()
function to get it compile. The key to resolve this problem is to find out a way to read the linker script defined symbols.
Although the correct way of using, e.g., the __sbss
symbol is to first declare it in the Rust source file and then take the address of it, it doesn't compile in this way. Instead, I tried using inline assembly
unsafe extern "C" fn Reset() -> ! {
extern "C" {
// These symbols come from `link.x`
static mut __sbss: u32;
static mut __ebss: u32;
static mut __sdata: u32;
static mut __edata: u32;
static __sidata: u32;
}
asm!(
"ldr r9, ={sdata}", // load static base
"ldr r0, ={sbss}",
"ldr r1, ={ebss}",
"bl {memzero}", // zero out bss section
"ldr r0, ={sdata}",
"ldr r1, ={edata}",
"ldr r2, ={sidata}",
"bl {memcopy}", // initialize data section in RAM
"bl {main}", // jump to main
sbss = sym __sbss,
ebss = sym __ebss,
sdata = sym __sdata,
edata = sym __edata,
sidata = sym __sidata,
memzero = sym memzero,
memcopy = sym memcopy,
main = sym main
);
loop {}
}
Magically, this compiles. From the disassembly, we can see that these symbols get allocated in ROM(flash).
08000400 <Reset>:
8000400: b580 push {r7, lr}
8000402: 466f mov r7, sp
8000404: f8df 9018 ldr.w r9, [pc, #24] ; 8000420 <_stext+0x20>
8000408: 4806 ldr r0, [pc, #24] ; (8000424 <_stext+0x24>)
800040a: 4907 ldr r1, [pc, #28] ; (8000428 <_stext+0x28>)
800040c: f000 f8a5 bl 800055a <_ZN17mini_cortex_m4_os4boot7memzero17h719c1bc8e3de9fd9E>
8000410: 4806 ldr r0, [pc, #24] ; (800042c <_stext+0x2c>)
8000412: 4907 ldr r1, [pc, #28] ; (8000430 <_stext+0x30>)
8000414: 4a07 ldr r2, [pc, #28] ; (8000434 <_stext+0x34>)
8000416: f000 f8b5 bl 8000584 <_ZN17mini_cortex_m4_os4boot7memcopy17h28a08465ccbd97e2E>
800041a: f000 fa85 bl 8000928 <_ZN17mini_cortex_m4_os4main17ha05f5ee7bef82e53E>
800041e: e7fe b.n 800041e <Reset+0x1e>
8000420: 20000000 .word 0x20000000 ; this is __sdata
8000424: 20000004 .word 0x20000004 ; this is __sbss
8000428: 20000130 .word 0x20000130 ; this is __ebss
800042c: 20000000 .word 0x20000000 ; this is __sdata again
8000430: 20000004 .word 0x20000004 ; this is __edata
8000434: 08004da4 .word 0x08004da4 ; this is __sidata
I don't know exactly why it works. It seems that we should always take the address of a compiler defined symbol, which doesn't compile, but should not read it as a variable, which does compile. Wierd. Any explanation on this is greatly appreciated.
For research purpose, I'm trying to build an image for my cortex-m4 microcontroller with
rwpi
relocation model. However, during linking stage, lld throws me the error:Below is an easy way to reproduce this error. This follows the tutorial in The Embedded Rust Book.
cargo install cargo-generate
to install an handy tool.cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
to download the example code.cd
into the cloned directory. Modify.cargo/config
. Add"-C", "relocation-model=rwpi"
torustflags
.cargo build
.The example code in
main.rs
uses thecortex-m-rt
crate, which during compile time will generate a link script for the linker. The generated link script can be found at./target/thumbv7m-none-eabi/debug/build/cortex-m-rt-xxxxxxxxxxxxxxxx/out/link.x
. I suppose that some information is missing for the linker. What should I do to resolve the error?The same question is asked on Stackoverflow here.