类似ARM,总有一堆启动文件,RISCV的我在精简,没想到精简的太深入,乱了,有没有做过启动代码,lds文件解读的朋友?
这些玩意让人崩溃,32位单片机写个简单程序这么困难么?
lds文件,
OUTPUT_ARCH("riscv")
ENTRY(_start) /* The first instruction to execute in a program is called the entry point. 如果定义了start符号, 使用start符号值 */
MEMORY
{
/* Run in FLASH */
flash (rxai!w) : ORIGIN = 0x08000000, LENGTH = 128k
ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 32K
/* Run in RAM */
/* flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 24k
ram (wxa!ri) : ORIGIN = 0x20006000, LENGTH = 8K
*/
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash
.ilalign :
{
. = ALIGN(4);
PROVIDE( _ilm_lma = . );
} >flash AT>flash
.ialign :
{
PROVIDE( _ilm = . );
} >flash AT>flash
.text :
{
*(.rodata .rodata.*)
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash
. = ALIGN(4);
PROVIDE (__etext = .);
PROVIDE (_etext = .);/*0x80022c8*/
PROVIDE (etext = .);/*0x80022c8*/
PROVIDE( _eilm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash
. = ALIGN(4);
PROVIDE( _eilm = . );
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash
.data :
{
*(.rdata)
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800);
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . ); /*0X200052A0 0X200002A0*/
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram
. = ALIGN(8);
PROVIDE( _end = . ); /*0X2000,0340*/
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram
}
Entry.S文件
// See LICENSE for license details
#ifndef ENTRY_S
#define ENTRY_S
#include "riscv_encoding.h"
#include "riscv_bits.h"
#include "n200_eclic.h"
#include "n200_timer.h"
###############################################
###############################################
# Disable Interrupt
#
.macro DISABLE_MIE
csrc CSR_MSTATUS, MSTATUS_MIE
.endm
###############################################
###############################################
#Save caller registers
.macro SAVE_CONTEXT
#ifdef __riscv_flen
#if (__riscv_flen==64 )
addi sp, sp, -20*REGBYTES - 20*FPREGBYTES
#else
addi sp, sp, -20*REGBYTES
#endif
#else
addi sp, sp, -20*REGBYTES
#endif
STORE x1, 0*REGBYTES(sp)
STORE x4, 1*REGBYTES(sp)
STORE x5, 2*REGBYTES(sp)
STORE x6, 3*REGBYTES(sp)
STORE x7, 4*REGBYTES(sp)
STORE x10, 5*REGBYTES(sp)
STORE x11, 6*REGBYTES(sp)
STORE x12, 7*REGBYTES(sp)
STORE x13, 8*REGBYTES(sp)
STORE x14, 9*REGBYTES(sp)
STORE x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 11*REGBYTES(sp)
STORE x17, 12*REGBYTES(sp)
STORE x28, 13*REGBYTES(sp)
STORE x29, 14*REGBYTES(sp)
STORE x30, 15*REGBYTES(sp)
STORE x31, 16*REGBYTES(sp)
#endif
#ifdef __riscv_flen
#if (__riscv_flen == 64)
FPSTORE f0, (20*REGBYTES + 0*FPREGBYTES)(sp)
FPSTORE f1, (20*REGBYTES + 1*FPREGBYTES)(sp)
FPSTORE f2, (20*REGBYTES + 2*FPREGBYTES)(sp)
FPSTORE f3, (20*REGBYTES + 3*FPREGBYTES)(sp)
FPSTORE f4, (20*REGBYTES + 4*FPREGBYTES)(sp)
FPSTORE f5, (20*REGBYTES + 5*FPREGBYTES)(sp)
FPSTORE f6, (20*REGBYTES + 6*FPREGBYTES)(sp)
FPSTORE f7, (20*REGBYTES + 7*FPREGBYTES)(sp)
FPSTORE f10, (20*REGBYTES + 8*FPREGBYTES)(sp)
FPSTORE f11, (20*REGBYTES + 9*FPREGBYTES)(sp)
FPSTORE f12, (20*REGBYTES + 10*FPREGBYTES)(sp)
FPSTORE f13, (20*REGBYTES + 11*FPREGBYTES)(sp)
FPSTORE f14, (20*REGBYTES + 12*FPREGBYTES)(sp)
FPSTORE f15, (20*REGBYTES + 13*FPREGBYTES)(sp)
FPSTORE f16, (20*REGBYTES + 14*FPREGBYTES)(sp)
FPSTORE f17, (20*REGBYTES + 15*FPREGBYTES)(sp)
FPSTORE f28, (20*REGBYTES + 16*FPREGBYTES)(sp)
FPSTORE f29, (20*REGBYTES + 17*FPREGBYTES)(sp)
FPSTORE f30, (20*REGBYTES + 18*FPREGBYTES)(sp)
FPSTORE f31, (20*REGBYTES + 19*FPREGBYTES)(sp)
#endif
#endif
.endm
###############################################
###############################################
#restore caller registers
.macro RESTORE_CONTEXT
LOAD x1, 0*REGBYTES(sp)
LOAD x4, 1*REGBYTES(sp)
LOAD x5, 2*REGBYTES(sp)
LOAD x6, 3*REGBYTES(sp)
LOAD x7, 4*REGBYTES(sp)
LOAD x10, 5*REGBYTES(sp)
LOAD x11, 6*REGBYTES(sp)
LOAD x12, 7*REGBYTES(sp)
LOAD x13, 8*REGBYTES(sp)
LOAD x14, 9*REGBYTES(sp)
LOAD x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 11*REGBYTES(sp)
LOAD x17, 12*REGBYTES(sp)
LOAD x28, 13*REGBYTES(sp)
LOAD x29, 14*REGBYTES(sp)
LOAD x30, 15*REGBYTES(sp)
LOAD x31, 16*REGBYTES(sp)
#endif
#ifdef __riscv_flen
#if (__riscv_flen==64)
/* Restore fp caller registers */
FPLOAD f0, (20*REGBYTES + 0*FPREGBYTES)(sp)
FPLOAD f1, (20*REGBYTES + 1*FPREGBYTES)(sp)
FPLOAD f2, (20*REGBYTES + 2*FPREGBYTES)(sp)
FPLOAD f3, (20*REGBYTES + 3*FPREGBYTES)(sp)
FPLOAD f4, (20*REGBYTES + 4*FPREGBYTES)(sp)
FPLOAD f5, (20*REGBYTES + 5*FPREGBYTES)(sp)
FPLOAD f6, (20*REGBYTES + 6*FPREGBYTES)(sp)
FPLOAD f7, (20*REGBYTES + 7*FPREGBYTES)(sp)
FPLOAD f10, (20*REGBYTES + 8*FPREGBYTES)(sp)
FPLOAD f11, (20*REGBYTES + 9*FPREGBYTES)(sp)
FPLOAD f12, (20*REGBYTES + 10*FPREGBYTES)(sp)
FPLOAD f13, (20*REGBYTES + 11*FPREGBYTES)(sp)
FPLOAD f14, (20*REGBYTES + 12*FPREGBYTES)(sp)
FPLOAD f15, (20*REGBYTES + 13*FPREGBYTES)(sp)
FPLOAD f16, (20*REGBYTES + 14*FPREGBYTES)(sp)
FPLOAD f17, (20*REGBYTES + 15*FPREGBYTES)(sp)
FPLOAD f28, (20*REGBYTES + 16*FPREGBYTES)(sp)
FPLOAD f29, (20*REGBYTES + 17*FPREGBYTES)(sp)
FPLOAD f30, (20*REGBYTES + 18*FPREGBYTES)(sp)
FPLOAD f31, (20*REGBYTES + 19*FPREGBYTES)(sp)
#endif
#endif
#ifdef __riscv_flen
#if(__riscv_flen == 64 )
addi sp, sp, 20*REGBYTES + 20*FPREGBYTES
#else
addi sp, sp, 20*REGBYTES
#endif
#else
// De-allocate the stack space
addi sp, sp, 20*REGBYTES
#endif
.endm
###############################################
###############################################
#restore caller registers
.macro RESTORE_CONTEXT_EXCPT_X5
LOAD x1, 0*REGBYTES(sp)
LOAD x6, 2*REGBYTES(sp)
LOAD x7, 3*REGBYTES(sp)
LOAD x10, 4*REGBYTES(sp)
LOAD x11, 5*REGBYTES(sp)
LOAD x12, 6*REGBYTES(sp)
LOAD x13, 7*REGBYTES(sp)
LOAD x14, 8*REGBYTES(sp)
LOAD x15, 9*REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 10*REGBYTES(sp)
LOAD x17, 11*REGBYTES(sp)
LOAD x28, 12*REGBYTES(sp)
LOAD x29, 13*REGBYTES(sp)
LOAD x30, 14*REGBYTES(sp)
LOAD x31, 15*REGBYTES(sp)
#endif
.endm
###############################################
###############################################
#restore caller registers
.macro RESTORE_CONTEXT_ONLY_X5
LOAD x5, 1*REGBYTES(sp)
.endm
###############################################
###############################################
# Save the mepc and mstatus
#
.macro SAVE_EPC_STATUS
csrr x5, CSR_MEPC
STORE x5, 16*REGBYTES(sp)
csrr x5, CSR_MSTATUS
STORE x5, 17*REGBYTES(sp)
csrr x5, CSR_MSUBM
STORE x5, 18*REGBYTES(sp)
.endm
###############################################
###############################################
# Restore the mepc and mstatus
#
.macro RESTORE_EPC_STATUS
LOAD x5, 16*REGBYTES(sp)
csrw CSR_MEPC, x5
LOAD x5, 17*REGBYTES(sp)
csrw CSR_MSTATUS, x5
LOAD x5, 18*REGBYTES(sp)
csrw CSR_MSUBM, x5
.endm
###############################################
###############################################
// Trap entry point
//
.section .text.trap
.align 6// In CLIC mode, the trap entry must be 64bytes aligned
.global trap_entry
.weak trap_entry
trap_entry:
// Allocate the stack space
// addi sp, sp, -19*REGBYTES
// Save the caller saving registers (context)
SAVE_CONTEXT
// Save the MEPC/Mstatus/Msubm reg
SAVE_EPC_STATUS
// Set the function argument
csrr a0, mcause
mv a1, sp
// Call the function
call handle_trap
// Restore the MEPC/Mstatus/Msubm reg
RESTORE_EPC_STATUS
// Restore the caller saving registers (context)
RESTORE_CONTEXT
// De-allocate the stack space
// addi sp, sp, 19*REGBYTES
// Return to regular code
mret
###############################################
###############################################
// IRQ entry point
//
.section .text.irq
.align 2
.global irq_entry
.weak irq_entry
irq_entry: // -------------> This label will be set to MTVT2 register
// Allocate the stack space
SAVE_CONTEXT// Save 16 regs
//------This special CSR read operation, which is actually use mcause as operand to directly store it to memory
csrrwi x0, CSR_PUSHMCAUSE, 17
//------This special CSR read operation, which is actually use mepc as operand to directly store it to memory
csrrwi x0, CSR_PUSHMEPC, 18
//------This special CSR read operation, which is actually use Msubm as operand to directly store it to memory
csrrwi x0, CSR_PUSHMSUBM, 19
service_loop:
//------This special CSR read/write operation, which is actually Claim the CLIC to find its pending highest
// ID, if the ID is not 0, then automatically enable the mstatus.MIE, and jump to its vector-entry-label, and
// update the link register
csrrw ra, CSR_JALMNXTI, ra
//RESTORE_CONTEXT_EXCPT_X5
#---- Critical section with interrupts disabled -----------------------
DISABLE_MIE # Disable interrupts
LOAD x5, 19*REGBYTES(sp)
csrw CSR_MSUBM, x5
LOAD x5, 18*REGBYTES(sp)
csrw CSR_MEPC, x5
LOAD x5, 17*REGBYTES(sp)
csrw CSR_MCAUSE, x5
RESTORE_CONTEXT
// Return to regular code
mret
#endif
|