This repository has been archived on 2023-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
bl_mcu_sdk/drivers/bl702_driver/startup/GCC/entry.S
Robert Lipe c39ba09f3d Fix build errors in entry.S. allows helloworld to compile and link.
1) __riscv_float_abi_single is not in the provided preprocessor namespace.
The default build sets -Werror and has -Warn implicitly. Testing something
that's not defined with an #if is therefore an error.
This is possibly a behavior change. If your builds ever define that AND
set it to 0, this way will fail, but #if defined (foo) + #if foo is akward
and probably not what you intended.

2) "csrw mtvt, t0" is not legal in at least
GNU assembler (GNU Binutils) 2.35
   Fortunately, riscv_encoding.h #defines a perfectly lovely value of
$0x307 that's appropriate for the chips AND is compatible with more assemblers.
This appears to be  an extension in
GNU assembler (SiFive Binutils 2.32.0-2019.08.0) 2.32
(present in bl_io_sdk, as provided by SiFive)
and that's probably what's in  your $PATH, but not relying on vendor
extension in this case is dead easy.

Two distinct problems. No, I'm not making different pull requests.
...this is a lot of words for a two line change. :-)
2021-06-20 13:43:14 +08:00

133 lines
4.3 KiB
ArmAsm

/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#include "riscv_encoding.h"
/* 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
la gp, __global_pointer$
.option pop
/* Disable global interrupt */
/*clear_csr(mstatus, MSTATUS_MIE);*/
csrci mstatus,8
/* Set up a simple trap vector to catch anything that goes wrong early in
* the boot process. */
la t0, Trap_Handler_Stub
/* enable CLIC Vectored mode */
ori t0,t0,3
csrw mtvec, t0
/* enable chicken bit if core is bullet series*/
la t0, __metal_chicken_bit
beqz t0, 1f
csrwi 0x7C1, 0
1:
/* There may be pre-initialization routines inside the MBI code that run in
* C, so here we set up a C environment. First we set up a stack pointer,
* which is left as a weak reference in order to allow initialization
* routines that do not need a stack to be set up to transparently be
* called. */
.weak __StackTop
la sp, __StackTop
/* Intial the mtvt, MUST BE 64 bytes aligned*/
.weak __Vectors
la t0, __Vectors
// From drivers/bl702_driver/risc-v/Core/Include/riscv_encoding.h
csrw CSR_MTVT, t0
#ifdef __riscv_float_abi_single
/* deal with FP */
/* Is F extension present? */
csrr t0, misa
andi t0, t0, (1 << ('F' - 'A'))
beqz t0, 1f
/* If so, enable it */
li t0, MSTATUS_FS
csrs mstatus, t0
fssr x0
1:
#endif
/* Check for an initialization routine and call it if one exists, otherwise
* just skip over the call entirely. Note that __metal_initialize isn't
* actually a full C function, as it doesn't end up with the .bss or .data
* segments having been initialized. This is done to avoid putting a
* burden on systems that can be initialized without having a C environment
* set up. */
call SystemInit
/* start load code to itcm like. */
call start_load
/* At this point we can enter the C runtime's startup file. The arguments
* to this function are designed to match those provided to the SEE, just
* so we don't have to write another ABI. */
csrr a0, mhartid
li a1, 0
li a2, 0
call main
/* If we've made it back here then there's probably something wrong. We
* allow the METAL to register a handler here. */
.weak __metal_after_main
la ra, __metal_after_main
beqz ra, 1f
jalr ra
1:
/* If that handler returns then 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
/* For sanity's sake we set up an early trap vector that just does nothing. If
* you end up here then there's a bug in the early boot code somewhere. */
.weak Trap_Handler_Stub
.section .text.metal.init.trapvec
.align 2
Trap_Handler_Stub:
.cfi_startproc
csrr t0, mcause
csrr t1, mepc
csrr t2, mtval
j Trap_Handler_Stub
.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