diff options
Diffstat (limited to 'fw/fe310/bsp/init')
-rw-r--r-- | fw/fe310/bsp/init/Makefile | 13 | ||||
-rw-r--r-- | fw/fe310/bsp/init/entry.S | 63 |
2 files changed, 76 insertions, 0 deletions
diff --git a/fw/fe310/bsp/init/Makefile b/fw/fe310/bsp/init/Makefile new file mode 100644 index 0000000..2df25e7 --- /dev/null +++ b/fw/fe310/bsp/init/Makefile @@ -0,0 +1,13 @@ +include ../../common.mk +CFLAGS += -I$(bsp_dir)/include -I$(bsp_dir)/drivers + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +%.o: %.S + $(CC) $(CFLAGS) -c $< + +all: entry.o + +clean: + rm -f *.o diff --git a/fw/fe310/bsp/init/entry.S b/fw/fe310/bsp/init/entry.S new file mode 100644 index 0000000..6b80217 --- /dev/null +++ b/fw/fe310/bsp/init/entry.S @@ -0,0 +1,63 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* This code executes before _start, which is contained inside the C library. + * In embedded systems we want to ensure that _enter, which contains the first + * code to be executed, can be loaded at a specific address. To enable this + * feature we provide the '.text.metal.init.enter' section, which is + * defined to have the first address being where execution should start. */ +.section .text.metal.init.enter +.global _enter +_enter: + .cfi_startproc + + /* Inform the debugger that there is nowhere to backtrace past _enter. */ + .cfi_undefined ra + + /* The absolute first thing that must happen is configuring the global + * pointer register, which must be done with relaxation disabled because + * it's not valid to obtain the address of any symbol without GP + * configured. The C environment might go ahead and do this again, but + * that's safe as it's a fixed register. */ +.option push +.option norelax +1:auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) +.option pop + + /* Set up a trap vector */ + la t0, eos_trap_vector + csrw mtvec, t0 + + /* This is a bare-metal environment and therefor is expected + * to define its own stack pointer. We also align the stack pointer here + * because the only RISC-V ABI that's currently defined mandates 16-byte + * stack alignment. */ + la sp, _sp + andi sp, sp, -16 + + /* At this point we can enter the C runtime's startup file. */ + call _start + + /* If we've made it back here then there's probably something wrong. + * There's not a whole lot we can do, just try to make some noise. */ + la t0, 1f + csrw mtvec, t0 +1: + lw t1, 0(x0) + j 1b + + .cfi_endproc + +/* The GCC port might not emit a __register_frame_info symbol, which eventually + * results in a weak undefined reference that eventually causes crash when it + * is dereference early in boot. We really shouldn't need to put this here, + * but to deal with what I think is probably a bug in the linker script I'm + * going to leave this in for now. At least it's fairly cheap :) */ +.weak __register_frame_info +.global __register_frame_info +.section .text.metal.init.__register_frame_info +__register_frame_info: + .cfi_startproc + ret + .cfi_endproc |