RT-1052-Cortex-M内核启动文件_main分析

这篇文章梳理了RT1052的启动过程

从Reset_Handler直至main

问题:分析RT1052启动流程的时候,卡在分散加载文件在启动的时候到底是怎么调用的。结果把问题点盯在启动文件的_main函数中。
可能自己比较菜吧,死活找不到这函数的定义。没办法,分析试着分析一下map文件。起码map文件中有一些链接信息
__Vectors_End 0x60002400 Data 0 startup_mimxrt1052.o(RESET)
__main 0x60002401 Thumb Code 0 entry.o(.ARM.Collect$$ 00000000 ) m a i n s t k 0 x 60002401 T h u m b C o d e 0 e n t r y 4. o ( . A R M . C o l l e c t 00000000) _main_stk 0x60002401 Thumb Code 0 entry4.o(.ARM.Collect 00000003 ) m a i n s c a t t e r l o a d 0 x 60002405 T h u m b C o d e 0 e n t r y 5. o ( . A R M . C o l l e c t 00000003) _main_scatterload 0x60002405 Thumb Code 0 entry5.o(.ARM.Collect KaTeX parse error: Expected group after '_' at position 15: 00000004) _̲_main_after_sca… 00000004 ) m a i n c l o c k 0 x 60002409 T h u m b C o d e 0 e n t r y 7 b . o ( . A R M . C o l l e c t 00000004) _main_clock 0x60002409 Thumb Code 0 entry7b.o(.ARM.Collect 00000008 ) m a i n c p p i n i t 0 x 60002409 T h u m b C o d e 0 e n t r y 8 b . o ( . A R M . C o l l e c t 00000008) _main_cpp_init 0x60002409 Thumb Code 0 entry8b.o(.ARM.Collect 0000000 A ) m a i n i n i t 0 x 60002409 T h u m b C o d e 0 e n t r y 9 a . o ( . A R M . C o l l e c t 0000000A) _main_init 0x60002409 Thumb Code 0 entry9a.o(.ARM.Collect KaTeX parse error: Expected group after '_' at position 15: 0000000B) _̲_rt_final_cpp …KaTeX parse error: Expected group after '_' at position 15: 0000000D) _̲_rt_final_exit …KaTeX parse error: Expected 'EOF', got '\Keil' at position 417: …助文档,找到一段话。文档在C:\̲K̲e̲i̲l̲_v5\ARM\Hlp\DUI… 00000000 ) m a i n s t k 0 x 60002401 T h u m b C o d e 0 e n t r y 4. o ( . A R M . C o l l e c t 00000000) _main_stk 0x60002401 Thumb Code 0 entry4.o(.ARM.Collect 00000003 ) m a i n s c a t t e r l o a d 0 x 60002405 T h u m b C o d e 0 e n t r y 5. o ( . A R M . C o l l e c t 00000003) _main_scatterload 0x60002405 Thumb Code 0 entry5.o(.ARM.Collect KaTeX parse error: Expected group after '_' at position 15: 00000004) _̲_main_after_sca… 00000004 ) m a i n c l o c k 0 x 60002409 T h u m b C o d e 0 e n t r y 7 b . o ( . A R M . C o l l e c t 00000004) _main_clock 0x60002409 Thumb Code 0 entry7b.o(.ARM.Collect 00000008 ) m a i n c p p i n i t 0 x 60002409 T h u m b C o d e 0 e n t r y 8 b . o ( . A R M . C o l l e c t 00000008) _main_cpp_init 0x60002409 Thumb Code 0 entry8b.o(.ARM.Collect 0000000 A ) m a i n i n i t 0 x 60002409 T h u m b C o d e 0 e n t r y 9 a . o ( . A R M . C o l l e c t 0000000A) _main_init 0x60002409 Thumb Code 0 entry9a.o(.ARM.Collect KaTeX parse error: Expected group after '_' at position 15: 0000000B) _̲_rt_final_cpp …KaTeX parse error: Expected group after '_' at position 15: 0000000D) _̲_rt_final_exit …$$0000000F)
Reset_Handler 0x60002415 Thumb Code 24 startup_mimxrt1052.o(.text)
 _main入口:

直接就进入了_main_scatterload函数,_main_stk被跳过不执行了。

_main_scatterload函数

首先就是加载0x60005068到r4
再就是加载0x60005088到r5
这两个数据是干嘛的?看map文件,这部分存放的就是程序链接的时候存放在flash的RW段数据。这段汇编的作用就是初始化RW段和ZI段数据。

Region$$Table$$Base                      0x60005068   Number         0  anon$$obj.o(Region$$Table)
Region$$Table$$Limit                     0x60005088   Number         0  anon$$obj.o(Region$$Table)

散列加载文件信息
0x60005068 0x60005088 散列加载文件信息结束地址
0x60005069 0x20000000 RW段运行时域起始地址
0x60005070 0x0000001C RW段大小
0x60005074 0x60004ca0 __scatterload_copy入口地址
0x60005078 0x600050a4 不知道什么东西
0x6000507c 0x2000001c ZI段运行时域起始地址
0x60005080 0x00000024 ZI段大小
0x60005084 0x60004cb0 __scatterload_null入口地址
搞定之后就真的跳转到熟悉的main函数了

其实在链接的时候还有很多和函数生成,不过在现在没有被用到就不在分析。道理都一样,以后就大致跟着流程走一遍就可以捋清了

重新梳理一遍启动文件执行流程

放上代码
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main

            CPSID   I               ; Mask interrupts
            LDR     R0, =0xE000ED08	;0xE000ED08 VTOR RW -b Vector Table Offset Register,摘自CM7参考手册
			;告诉CM7当异常发生时去哪里找异常向量入口(异常向量入口重定向)
            LDR     R1, =__Vectors	;异常向量首地址
			;__Vectors指向的数据为-> DCD     |Image$$ARM_LIB_STACK$$ZI$$Limit|
			;即从分散加载文件中连接计算出来的栈顶地址
            STR     R1, [R0]		;将r1寄存器的值传送到地址值为r0的(存储器)内存
            LDR     R2, [R1]		;将存储器地址为R1的字数据读入寄存器R2。
            MSR     MSP, R2			;设置栈顶
            LDR     R0, =SystemInit	
            BLX     R0				;跳转SystemInit函数
            CPSIE   i               ; Unmask interrupts
            LDR     R0, =__main
            BX      R0
            ENDP

上电系统进入boot ROM,经过初始化,判断启动设置后进入Reset_Handler 
屏蔽中断
设置CM7异常向量表入口
设置栈顶
跳转SystemInit:初始化浮点运算单元,关闭看门狗,关闭Systick时钟,设置ICACHE,DCACHE
这个函数想再分析一波,想一下,程序执行到这里的时候并没有初始化什么C语言的准备环境,比如RW段初始化,ZI段初始化。仅仅是初始化了栈顶。为什么这个函数可以正常运行?

答:是位置无关码,这个函数并没有定义什么已经初始化的变量,没有调用全局变量,没有静态变量。所有操作都是设置寄存器。所以这个函数并不依赖RW+ZI段。所以这个函数可以正常运行。

怎么利用SystemInit函数?

答:可以在这个函数中加入初始化外扩的SDRAM,然后把需要放在SDRAM的段通过分散加载文件进行配置。等_main函数执行的时候就可以实现RW+ZI段的初始化了

跳转_main:具体动作上面分析了
进入真正main函数

作者:weixin_42264572
来源:CSDN
原文:https://blog.csdn.net/weixin_42264572/article/details/84948044
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/qq_43234066/article/details/89556248