STM32 XIP启动过程-RW和ZI数据搬移讲解
最近在RISC-V架构下基于某芯片实现XIP方式的flash代码启动,这部分代码对于我是可见的,联想到之前一直很困惑STM32的引导程序在哪里实现得将RW复制到RAM中,并RAM中初始化ZI的,写下自己的分享。以下仅针对stm32XIP模式,也就是flash启动进行讲解
引导程序
嵌入式上电后需要对需要对系统硬件和软件运行环境进行初始化,这些工作往往是由汇编语音编写的引导程序完成。引导程序是嵌入式系统上电后运行的第一段软件代码,对于嵌入式系统来说,引导程序非常关键。引导程序执行的操作依赖于开发的嵌入式系统的软硬件特性,一般的流程包括:初始化硬件、设置异常和中断向量表、把程序复制到片上RAM、完成代码重映射等,最后跳转到main入口函数。
对于CM3和CM4来说
主要做了以下工作:
1、初始化堆栈指针 SP=_initial_sp
2、初始化 PC 指针=Reset_Handler
3、初始化中断向量表
4、配置系统时钟
5、调用 C 库函数_main 初始化用户堆栈,从而最终调用 main 函数去到 C 的世界
XIP模式下RW和ZI动作
首先代码分为加载域和执行域,我们(烧录)加载代码后,代码及 RW 都被保存在 ROM 区(也就是stm32的nor flash)。当程序开始运行时,内核直接从 ROM 中读取代码,并且在执行主体代码前,会先执行一段加载代码,它
把 RW 节数据从 ROM 复制到 RAM, 并且在 RAM 加入 ZI 节,ZI 节的数据都被初始化为0。加载完后 RAM 区准备完毕,正式开始执行主程序。
.s启动文件上代码如下:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
SystemInit()代码无非是一些寄存器初始化和配置向量表偏移,我们仍然没有看到关于RW和ZI的一段,因此我们怀疑是不是__main这个调用的C库函数除了执行对堆栈的初始化还执行了这个操作,接下来我们对某工程进行反汇编,程序中具有一段名为“__scatterload”的分散加载代码,需要注意的是,这段代码它是由 armlink 链接器自动生成的!
这段分散加载代码包含了拷贝过程(LDM 复制指令),而 LDM 指令的操作数中包含了加载的源地址,这些地址中包含了内部 FLASH 存储的 RW-data 数据。而 “__scatterload ”的代码会被“__main”函数调用,__main 在启动文件中的“Reset_Handler”会被调用,因而,在main()函数执行前,已经完成了分散加载过程,随后进入我们熟悉的世界~~
附:我们查看map文件:
符号映像表(Image Symbol Table)中有 __scatterload 指令在flash的存储位置。
Global Symbols
Symbol Name Value Ov Type Size Object(Section)
__Vectors_Size 0x000001ac Number 0 startup_stm32f429xx.o ABSOLUTE
__Vectors 0x08000000 Data 4 startup_stm32f429xx.o(RESET)
__Vectors_End 0x080001ac Data 0 startup_stm32f429xx.o(RESET)
__main 0x080001ad Thumb Code 8 __main.o(!!!main)
__scatterload 0x080001b5 Thumb Code 0 __scatter.o(!!!scatter)
__scatterload_rt2 0x080001b5 Thumb Code 44 __scatter.o(!!!scatter)
__scatterload_rt2_thumb_only 0x080001b5 Thumb Code 0 __scatter.o(!!!scatter)
__scatterload_null 0x080001c3 Thumb Code 0 __scatter.o(!!!scatter)
__scatterload_copy 0x080001e9 Thumb Code 26 __scatter_copy.o
在存储器映射索引中,scatter 在flash的位置。
Memory Map of the image
Image Entry point : 0x080001ad
Load Region LR_IROM1 (Base: 0x08000000, Size: 0x000011dc, Max: 0x00100000, ABSOLUTE)
Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x000011bc, Max: 0x00100000, ABSOLUTE)
Base Addr Size Type Attr Idx E Section Name Object
0x08000000 0x000001ac Data RO 470 RESET startup_stm32f429xx.o
0x080001ac 0x00000008 Code RO 1896 * !!!main c_w.l(__main.o)
0x080001b4 0x00000034 Code RO 2051 !!!scatter c_w.l(__scatter.o)
0x080001e8 0x0000001a Code RO 2053 !!handler_copy c_w.l(__scatter_copy.o)
本文地址:https://blog.csdn.net/u011116085/article/details/108779179
上一篇: 什么是处暑?过处暑吃什么菜?