bl602 start.S启动文件分析

F:\study\bl602\study_bl_iot_sdk\bl_iot_sdk\components\platform\soc\bl602\bl602\evb\src\boot\gcc\start.S

源码如下:

//See LICENSE for license details.

/*This is defined in sifive/platform.h, but that can't be included from

* assembly. */

/*

mstatus (Machine Status) 它保存全局中断使能,以及许多其他状态

Bit3: MIE 中断总开关,1开,0关

Bit14~bit13:FS 表示浮点单元的状态,0b00 All off; 0b01initial; 0b10 Clean; 0b11 Dirty

*/

#defineCLINT_CTRL_ADDR 0x02000000

#defineMSTATUS_FS 0x00006000 //mstaus register FS bit position

#defineMSTATUS_MIE 0x00000008 //mstatus register MIE bit position

/* risc-v汇编语法: .section name [,subsection]

* .section 伪操作 将下面代码汇编到名为name的段当中

* 这是是将下面代码汇编到.init段(section)中

*/

.section .init

/* risc-v汇编语法: .global symbol

* .global伪操作定义bl602_start 是全局的

* 我的另一篇帖子"bl602链接文件分析"中可以知道bl602_start就是程序的入口地址

*/

.globl bl602_start

/* risc-v汇编语法: .type name,type description

* .type伪操作符号类型,将bl602_start定义为函数

*/

.type bl602_start,@function

/* cpu 从这里开始执行 */

bl602_start:

/* 以.cfi_开头的汇编指示符CFI即Call Frame Information ,是DWARF2.0定义的函数栈信息,是一种调试信息

* .cfi_开头汇编指示符用来告诉汇编编译器生成相应的DWARF调试信息,详情参考

* https://sourceware.org/binutils/docs-2.31/as/CFI-directives.html

* .cfi_startproc 出现在程序开始,程序结束时使用 .cfi_endproc

* .cfi_undefined ra 是取消ra寄存器之前的值,不能再恢复了

* ra:return address register 用于保存函数调用返回地址

*/

.cfi_startproc

.cfi_undefined ra

/*.option{rvc,norvc,push,pop}

* .option 伪操作用于设定某些架构特定的选项

* .option push 临时保存当前的选项设置

* .option pop 将最近操作设置恢复出来重新生效

* .option push .option pop 成对使用可以在汇编程序中不影响全局选项的情况下,为其中嵌入的某一段

* 代码特别的设置不同选项

* . option relax 允许链接器松弛(链接时多次扫描,尽可能将跳转的两条指定替换为一条)

* .option norelax 不允许链接器松弛

* 此处.option push 就是将所有.option设置入栈选保存起来,等执行完特殊代码后

* 再执行.option pop 恢复

*/

.optionpush

.optionnorelax

/*disable IRQ*/

/* li a0,immediately

*li伪指令可以将任意的32位数据或者地址加载到指定的寄存器

* 这里是 将MSTATUS_MIE 加载到临时寄存器t0

*

*csrc 是特权指令(属于CSR操作指令,CSR指令操作CSR寄存器,CSR寄存器有8个比较重要的)

*

* csrc mstatus,t0 是将mstatus寄存器的t0中对应位置零,这样就是mstatus.mie= 0 关闭总中断*/

li t0, MSTATUS_MIE

csrc mstatus, t0

/*

*la是一条加载伪指令

*gp 全局指针寄存器

* 将ld文件中标签 __global_pointer的值赋值给gp

*我的理解是读取ld文件中__global_pointer$的值,这里是内存地址,给到gp全局指针寄存器

*这样可以使用 relax 优化全局变量访问跳转指令,__global_pointer$值这里是一个内存地址,可以

*优化范围是基于此地址 +-2K范围。这里是优化 .sdata

*

* PROVIDE(__global_pointer$ = . + 0x7F0 );

* KEEP(*libfreertos_riscv.a:*(.sdata.*))

* 可以看出这里是优化 libfreertos_riscv.a

*/

la gp, __global_pointer$

/* 恢复到当前选项配置

*总结一下:在.option push和.optionpop 之间做了两件事情

*1.关中断

*2.将ld文件中__global_pointer$ 赋值给gp寄存器,优化libfreertos_risc-v.a

*/

.optionpop

/*将 ld文件中_sp_main 值赋值给sp寄存器

* sp:栈指针 寄存器 Stack poninter

*

*. = . +__stack_size;

* PROVIDE(_sp_main = . );

* __freertos_irq_stack_top= .;

* 这里的_sp_main 就是 __freertos_irq_stack_top指定freertos 中断 栈地址

* 关于freertos 在risc-v上的移植可以查阅:

* https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html

*/

la sp, _sp_main

#ifndefRUN_IN_RAM

/* Load boot2 partition address */

/* 这里定义的立即数在ld文件中有定义 是boot2的分区表地址

*__boot2_pt_addr_src 地址在BOOT2_PT_ADDR = 0x42049C00 分区表flash存储地址

* __boot2_pt_addr_start 分区表内存起始地址

* __boot2_pt_addr_end分区表内存结束地址

*/

la a0, __boot2_pt_addr_src

la a1, __boot2_pt_addr_start

la a2, __boot2_pt_addr_end

/* bgeu a1,a2,2f 2f表示本地标签,执行2:后的程序,翻译成C伪代码:

*if(a1 >=a2)

* jump 2:

*/

bgeu a1, a2, 2f

/* __boot2_pt_addr_start值< __boot2_pt_addr_end 值 拷贝flash分区表到内存 */

1:

/* 从a0寄存器读值赋值给t0 */

lw t0, (a0)

/* 把t0寄存器值存入寄存器a1,保留最右侧的32bit */

sw t0, (a1)

/* a0 = a0+4 */

addi a0, a0, 4

/* a1 = a1+4 */

addi a1, a1, 4

/* [a1]小于[a2] 的话跳转到1:*/

bltu a1, a2, 1b

/*翻译成C伪代码

While(__boot2_pt_addr_start < __boot2_pt_addr_end)

*__boot2_pt_addr_start++ = *__boot2_pt_addr_src++

*/

/* __boot2_pt_addr_start值 >= __boot2_pt_addr_end 值 */

2:

/* Load boot2 flashCfg address */

/* 跳转到 hal_boot2_get_flash_addr 处执行代码 */

jal hal_boot2_get_flash_addr

la a1, __boot2_flashCfg_start

la a2, __boot2_flashCfg_end

/* 也是判断跳转 */

bgeu a1, a2, 2f

/* 拷贝flash参数表到内存 */

1:

lw t0, (a0)

sw t0, (a1)

addi a0, a0, 4

addi a1, a1, 4

bltu a1, a2, 1b

2:

#endif

/* Load data section */

/*

*_data_load 加载程序地址LMA

*_data_run 运行程序地址 VMA

* _data_run_end

* 拷贝 LMA程序 到 VMA 地址段

*/

la a0, _data_load

la a1, _data_run

la a2, _data_run_end

bgeu a1, a2, 2f

1:

lw t0, (a0)

sw t0, (a1)

addi a0, a0, 4

addi a1, a1, 4

bltu a1, a2, 1b

2:

/* Clear bss section */

/* .bss section 清零 */

la a0, __bss_start

la a1, __bss_end

bgeu a0, a1, 3f

1:

sw zero, (a0)

addi a0, a0, 4

bltu a0, a1, 1b

/* Clear bss section */

/* wifi .bss section 清零 */

la a0, __wifi_bss_start

la a1, __wifi_bss_end

bgeu a0, a1, 3f

1:

sw zero, (a0)

addi a0, a0, 4

bltu a0, a1, 1b

3:

/* Call global constructors */

#if0

la a0, __libc_fini_array

call atexit

call __libc_init_array

#endif

#ifndef__riscv_float_abi_soft

/* Enable FPU */

li t0, MSTATUS_FS

csrs mstatus, t0 //将mstatus 寄存器MSTATUS_FS 位置1 开FPU

csrr t1, mstatus//读取mstatus值到t0寄存器

and t1, t1, t0 //[t1] = [t1] &[ t0]

beqz t1, 1f //如果[t1] == 0 jump 1:

fssr x0 //x0也是zero寄存器,初始化浮点数寄存器为0

1:

#endif

#ifdefined(ENABLE_SMP)

smp_resume(t0, t1)

csrr a0, mhartid

bnez a0, 2f

#endif

auipc ra, 0

addi sp, sp, -16

#if__riscv_xlen == 32

sw ra, 8(sp)

#else

sd ra, 8(sp)

#endif

#ifdefBL602_MATTER_SUPPORT

call setup_heap

#endif

//call global obj constructors

//初始化__preinit_array_,__init_array_区域函数

la s1, __preinit_array_start

la s2, __preinit_array_end

li s3, 4 //[s3] = 4

1:

bgeu s1, s2, 2f

lw a3, (s1) //s1 赋值给a3

jalr a3

add s1, s1, s3

j 1b

2:

la s1, __init_array_start

la s2, __init_array_end

li s3, 4

1:

bgeu s1, s2, 2f

lw a3, (s1)

jalr a3

add s1, s1, s3

j 1b

2:

/* argc = argv = 0 */

li a0, 0

li a1, 0

/* 跳转到 bfl_main 函数 */

call bfl_main

#if 0

tail exit

#endif

1:

j 1b

#ifdefined(ENABLE_SMP)

2:

la t0, trap_entry

csrw mtvec, t0

csrr a0, mhartid

la t1, _sp_main

slli t0, a0, 10

sub sp, t1, t0

auipc ra, 0

addi sp, sp, -16

#if__riscv_xlen == 32

sw ra, 8(sp)

#else

sd ra, 8(sp)

#endif

call secondary_main

tail exit

1:

j 1b

#endif

.cfi_endproc

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懂IT的嵌入式工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值