前言
为了给后边的工作打下基础,需要先了解下程序的框架,和程序执行的过程。本文以UART_Demo为例进行讲解。
前提是已经搭建好开发环境,见https://bbs.elecfans.com/jishu_2286222_1_1.html,打开UART_Demo工程。
链接脚本
从工程设置的链接器设置里找
找到链接文件如下
打开该文件
从如下信息可以看出,0x00000000处放置的就是中断向量
.vectors : { KEEP(*(.vectors )) }
. = 0x00000000;
从数据手册的第4章可以看到
128 KB instruc
tion local memory (ILM)
SRAM就是位于该地址处
从如下信息可以看出,
NDS_SAG_LMA_FLASH = 0x20000000 ;
. = 0x20000000;
PROVIDE (BIN_BEGIN = .);
对应的是 FLASH存储程序使用,有效1MB,
对应 PROVIDE (FLASH_SIZE = 0x0100000);
从以下信息可以看出
PROVIDE (_STACK_TOP = 0x00a0000);
栈指针指向的是DLM_CPU的高地址处。
其他的BSS,DATA段等的分配都可以类似的去分析。
启动代码
前面通过链接脚本找到向量段.vectors
所以搜索.vectors
双击如下搜索到的结果
可以找到启动代码如下telink_b91m_driver_sdkchipB91bootcstartup_flash.S
.global _RESET_ENTRY
和link文件的ENTRY(_RESET_ENTRY)对应,是程序的入口
_RESET_ENTRY:
j _START
第一条指令就是跳转到_START执行
后面就是相关的初始化操作
比如初始化栈指针,其中_STACK_TOP是link文件中的符号
/* Initialize stack pointer */
la t0, _STACK_TOP
mv sp, t0
比如初始化DATA段,可以对照link文件查看段地址
/* Move Data from flash to sram */
_IDATA_INIT:
la t1, _DATA_LMA_START
la t2, _DATA_VMA_START
la t3, _DATA_VMA_END
_IDATA_INIT_BEGIN:
bleu t3, t2, _IZERO_BSS
lw t0, 0(t1)
sw t0, 0(t2)
addi t1, t1, 4
addi t2, t2, 4
j _IDATA_INIT_BEGIN
比如初始化BSS段,可以对照link文件查看段地址
/* Zero .bss section in sram */
_IZERO_BSS:
lui t0, 0
la t2, _BSS_VMA_START
la t3, _BSS_VMA_END
_IZERO_BSS_BEGIN:
bleu t3, t2, _IZERO_AES
sw t0, 0(t2)
addi t2, t2, 4
j _IZERO_BSS_BEGIN
以上操作不同的芯片都是类似的,一通百通,了解一个芯片其他的芯片也就都僚机了。至于其他芯片相关的操作可以对照手册去理解,这里不再解释。
进入用户代码
最后进入main函数,进入用户代码
la t0, main
jalr t0
总结 该芯片是RISC-V内核的,所以与其他RISC-V芯片的启动执行过程也是一样的,了解一种就可以知道其他的。学习嵌入式需要有融会贯通举一反三的能力,因为芯片内核架构众多,芯片类型更是千万。所以上述分析主要是介绍分析思路,细节介绍的不多,更多的细节需要自行去根据手册进行分析。