I'm trying to write a bootloader for an STM32 in Rust and I can't figure out how to correctly populate the stack pointer. Near as I can tell the code should be:
asm!("MOV SP, $0" :: "0"(stack_pointer)); // set the stack pointer
but the compiler disagrees:
error: invalid operand in inline asm: 'MOV SP, $0'
--> src/main.rs:38:5
|
38 | asm!("MOV SP, $0" :: "0"(stack_pointer)); // set the stack pointer
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: <inline asm>:1:11: error: unexpected token in operand
MOV SP,
^
--> src/main.rs:38:5
|
38 | asm!("MOV SP, $0" :: "0"(stack_pointer)); // set the stack pointer
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What am I doing wrong? It seem to be complaining about the dollar sign, but I got that directly from the documentation.
Per the conversation in the comments, I've tried two things, both of which compile(!) but neither of which seem to work (but that could be for any of a billion reasons, still working on it):
Version A:
asm!("MOV R0, #0x0800");
asm!("LSL R0, R0, #16");
asm!("MOV R1, #0x8000");
asm!("ORR R2, R1, R0");
asm!("LDRT R0, [R2]");
asm!("MOV SP, R0");
entry_point()
Version B:
#[inline(never)]
unsafe fn go(_addr: u32, entry_point: fn()->()) {
asm!("MOV SP, R0");
entry_point()
}
It seems to me you're having two problems:
The second part seems easy with global_asm!
:
#![feature(global_asm)]
global_asm!(r#"
.global go
go:
mov sp, r0
bx r1
"#);
extern "C" {
pub fn go(addr: u32, entry_point: extern fn());
}
or with normal asm!
:
#![feature(asm)]
#[no_mangle]
pub unsafe fn go(addr: u32, entry_point: fn()) {
asm!("mov sp, r0" :: "{r0}"(addr) : "sp");
entry_point()
}
I think the "0"(stack_pointer)
part didn't work because stack_pointer
is not a constant.
Your Version B results in the same ASM code; but it really should mark "sp" as clobbered, and "{r0}"(addr)
makes sure the first argument really is in r0
.
Clifford seems to prefer passing a pointer to a "vector table", which could look like this:
#[repr(C)]
pub struct VectorTable {
stack_pointer: u32,
entry_point: extern fn() -> !,
}
global_asm!(r#"
.global go
go:
ldr sp, [r0]
ldr pc, [r0, #4]
"#);
extern "C" {
pub fn go(vt: &VectorTable) -> !;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With