0

Following is the _start entry point for my embedded rust code. The _stack_start comes from linker script.

#[no_mangle]
pub fn _start() -> ! {

    extern "C" {
        static  _stack_start: u32;
    }
    unsafe{
        let sp1 = &_stack_start;
        asm!("mv sp, {}" ,
            in(reg) sp1);
    }

    type FnPtr = fn() -> !;
    let th: FnPtr = trap_handler;
    unsafe{

        asm!("csrw mtvec, {}" ,
            in(reg) th);
    }
}

When compiled for RV32I, objdump spits the following:

80000004 <_start>:
80000004:   1141                addi    sp,sp,-16
80000006:   c606                sw  ra,12(sp)
80000008:   80000537            lui a0,0x80000
8000000c:   09850513            addi    a0,a0,152 # 80000098 <_stack_start+0x0>
80000010:   812a                mv  sp,a0
80000012:   80000537            lui a0,0x80000
80000016:   00050513            mv  a0,a0
8000001a:   30551073            csrw    mtvec,a0
8000001e:   4555                    li  a0,21

as you clearly see, the problem here is that compiler is trying to push the return address to stack even before the stack is set. How to tell compiler not to do it? This causes exception as the initial value of sp is unknown.

RRON
  • 1,037
  • 3
  • 12
  • 32
  • You definitely shouldn't be using the default calling convention for `_start`. It should probably be an `extern "C"` function, [`#[naked]`](https://github.com/rust-lang/rust/issues/32408) function, or a `global_asm` block. – Aiden4 Oct 01 '22 at 19:41
  • I have a feeling that the stack pointer is not meant to be set explicitly, at least not inside of a method call. Are you sure that there isn't some linker functionality that does this for you? The [embedonomicon](https://docs.rust-embedded.org/embedonomicon/memory-layout.html) reads like the linker can achieve this without any code. Of course I'm not an expert and those are just my thoughts from looking at this problem for a couple of minutes. – Finomnis Oct 02 '22 at 07:49

0 Answers0