BL IOT SDK启动链接及FreeRTOS简要分析
本文简要分析bl iot SDK的start.S文件的初始化过程,FreeRTOS以及链接脚本。
start.S
该文件路径:components/platform/soc/bl602/bl602/evb/src/boot/gcc/start.S
- 关闭中断
li t0, MSTATUS_MIE
csrc mstatus, t0
- 初始化GP寄存器
la gp, __global_pointer
GP附近的数据会通过GP寄存器相对寻址来访问,GP的值在链接时决定,不可更改。
- 初始化栈指针
la sp, _sp_main
- 读取boot2中约定好的partition地址来设置sdk中的boot2_partition_table变量,该变量放置在指定的section中
la a0, __boot2_pt_addr_src
la a1, __boot2_pt_addr_start
la a2, __boot2_pt_addr_end
- 读取boot2中约定好的flash地址来设置sdk中的boot2_flashCfg变量,该变量放置在指定的section中
jal hal_boot2_get_flash_addr
la a1, __boot2_flashCfg_start
la a2, __boot2_flashCfg_end
- 初始化data段
la a0, _data_load
la a1, _data_run
la a2, _data_run_end
- 初始化bss段
la a0, __bss_start
la a1, __bss_end
- 初始化main入口地址
li a0, 0
li a1, 0
call bfl_main
FreeRTOS
FreeRTOS由Richard Barry开发,是一个开源的、可移植的、小型的嵌入式实时操作系统内核。FreeRTOS既支持抢占式多任务,也支持协作式多任务,SDK中源码路径:components/platform/soc/bl602/freertos_riscv_ram。
- 中断入口
- SDK中components/platform/soc/bl602/freertos_riscv_ram/portable/GCC/RISC-V/portASM.S里的freertos_risc_v_trap_handler。
flash_rom.ld
该文件路径:components/platform/soc/bl602/bl602/evb/ld/flash_rom.ld
- 设置输出文件的machine architecture(体系结构)
OUTPUT_ARCH( "riscv" )
- 设置入口地址
ENTRY( bl602_start )
- MEMORY命令
MEMORY
{
rom (rxai!w) : ORIGIN = 0x21015000, LENGTH = 44K
flash (rxai!w) : ORIGIN = 0x23000000, LENGTH = 4M
ram_tcm (wxa) : ORIGIN = 0x4200C000, LENGTH = (16K + 16K + 48K + 64K + 64K + 8K - __EM_SIZE) /*put itcm with dtam and also OCRAM*/
ram_wifi (wxa) : ORIGIN = 0x42042000 - __EM_SIZE, LENGTH = (8K + 104K - 64K - 8K) /*leave 8K left for BLE*/
}
例:rom表示存储区域名,(rxai!w)表示该存储区域的属性,ATTR属性内可以出现以下7个字符, R 只读section W 读/写section X 可执行section A ‘可分配的’section I 初始化了的section L 同I ! 不满足该字符之后的任何一个属性的section ORIGIN :关键字,区域的开始地址,可简写成org或o LENGTH :关键字,区域的大小,可简写成len或l
- SECTIONS命令
- 在链接脚本中定义了.init段,.text段,.rodata段,.wifibss段,.romdata段,.data段,.boot2段,.bss段,.stack段。
- 例:
- .init段
.init : { KEEP (*(SORT_NONE(.init))) } > flash
KEEP()关键字强制连接器保留.init段, > flash表示:将输出的.init段放置在flash中
- .rodata段
.rodata : { *(.rdata) *(.rodata .rodata.*) *(.sdata2.*) /* static cli cmds */ . = ALIGN(4); _bl_static_cli_cmds_start = .; KEEP(*(.static_cli_cmds)) *(.static_cli_cmds) _bl_static_cli_cmds_end = .; ... ... ... } > flash
其中花括号外面的.rodata表示输出段的名字,花括号中表示输入的段。 整个代码段表示:所有文件的.rdata段,.rodata段,.rodata.*段,.sdata2.*段等段输出到.rodata段中,并将其放置在flash中。 . = ALIGN(4); .表示当前地址,ALIGN(4):4字节对齐。
- PROVIDE命令
该关键字用于定义这类符号:在目标文件内被引用,但没有在任何目标文件内被定义的符号。 例:
PROVIDE( _ld_bl_static_cli_cmds_start = _bl_static_cli_cmds_start );
PROVIDE( _ld_bl_static_cli_cmds_end = _bl_static_cli_cmds_end );
_ld_bl_static_cli_cmds_start和_ld_bl_static_cli_cmds_end在sdk中的aos_cli_init()函数中被引用。_bl_static_cli_cmds_start和_bl_static_cli_cmds_end在上文中已经定义了。