前言
为了给后边的工作打下基础,需要先了解下程序的框架,和程序执行的过程。本文以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芯片的启动执行过程也是一样的,了解一种就可以知道其他的。学习嵌入式需要有融会贯通举一反三的能力,因为芯片内核架构众多,芯片类型更是千万。所以上述分析主要是介绍分析思路,细节介绍的不多,更多的细节需要自行去根据手册进行分析。
|