summaryrefslogtreecommitdiff
path: root/fw/fe310/bsp/init
diff options
context:
space:
mode:
Diffstat (limited to 'fw/fe310/bsp/init')
-rw-r--r--fw/fe310/bsp/init/Makefile13
-rw-r--r--fw/fe310/bsp/init/entry.S63
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