打印

有无RISCV单片机 的启动代码解读?

[复制链接]
1093|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
司成|  楼主 | 2019-11-4 01:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
类似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

使用特权

评论回复

相关帖子

沙发
司成|  楼主 | 2019-11-5 09:54 | 只看该作者
顶顶顶顶顶顶顶顶顶顶顶顶

使用特权

评论回复
板凳
sonicll| | 2019-11-6 19:28 | 只看该作者
本帖最后由 sonicll 于 2019-11-6 19:32 编辑

你贴的这两个都不是启动文件,lds是链接文件,指定代码段数据段堆栈等等内容都在哪个地址存放,类似于keil里的sct文件。Entry.s里面定义的是进入中断时的操作,手动压栈弹栈,RISCV不能像cortex-m3那样在中断发生时硬件保存现场,只能软件来保存中断现场。你贴的应该是GD的代码吧?还有个start.s,那个才是启动文件

使用特权

评论回复
地板
司成|  楼主 | 2019-11-18 11:34 | 只看该作者
sonicll 发表于 2019-11-6 19:28
你贴的这两个都不是启动文件,lds是链接文件,指定代码段数据段堆栈等等内容都在哪个地址存放,类似于keil ...

现在差不多搞明白了。

因为riscv搞得更复杂。让我更迷糊。



arm烂了,riscv目前看除了ide好一点,也烂的相当的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

142

帖子

2

粉丝