Cortex-M3启动深度解析
Cortex-Mx启动,备忘,以免将来忘记。
中断向量表不用说,从重置中断开始吧
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
这里一共就执行了两个函数,SystemInit和__main。
我们一般在SystemInit里面配置系统时钟,这里跳过。
__main是我们今天的重点。
__main: 0x080000C0 4804 LDR r0,[pc,#16] ; @0x080000D4 0x080000C2 4685 MOV sp,r0 #设置栈顶 _main_scatterload: 0x080000C4 F000F956 BL.W __scatterload (0x08000374) #分散加载(拷贝初始值、清零变量) __main_after_scatterload: 0x080000C8 F000F8D4 BL.W __cpp_initialize__aeabi_ (0x08000274) #C++初始化(全局对象构造函数执行) _main_cpp_init: 0x080000CC 4800 LDR r0,[pc,#0] ; @0x080000D0 0x080000CE 4700 BX r0 #进入C++的main函数
分散加载这里将会初始化我们的全局静态变量
.text:00000000 __scatterload_rt2 .text:00000000 LDR R4, =Region$Table$Base .text:00000002 MOVS R5, #1 .text:00000004 LDR R6, =Region$Table$Limit .text:00000006 B loc_14 .text:00000008 ; --------------------------------------------------------------------------- .text:00000008 .text:00000008 loc_8 ; CODE XREF: __scatterload_rt2+16j .text:00000008 LDR R3, [R4,#0xC] .text:0000000A LDMIA R4!, {R0-R2} .text:0000000C ORRS R3, R5 .text:0000000E SUBS R4, #0xC .text:00000010 BLX R3 .text:00000012 ADDS R4, #0x10 .text:00000014 .text:00000014 loc_14 ; CODE XREF: __scatterload_rt2+6j .text:00000014 CMP R4, R6 .text:00000016 BCC loc_8 .text:00000018 BL __main_after_scatterload
可能汇编看起来不是很直观,我们配合看F5得到的反编译C代码
void _scatterload_rt2() { _DWORD *i; // r4@1 for ( i = &Region__Table__Base; (_UNKNOWN *)i < &Region__Table__Limit; i += 4 ) ((void (__fastcall *)(_DWORD, _DWORD, _DWORD))(i[3] | 1))(*i, i[1], i[2]); _main_after_scatterload(); JUMPOUT(&Region__Table__Base); }
从上面看出,有一张区域表,每4个int作为一段,每一段前三个为参数,第四个为函数指针。
经过调试得知:
第一个函数是__scatterload_copy,从某个Flash地址把数据拷贝给RAM里面的变量,也就是带有初始值的全局变量;
第二个函数是__scatterload_zeroinit,顾名思义,就是全局变量清零,只要没有初始值的全局变量,都清零,堆空间和栈空间一块清。
而在汇编文件里面我们有AREA HEAP, NOINIT, READWRITE, ALIGN=3。显然其中的NOINIT并没有生效
ER_IROM1:0800D704 Region$Table$Base DCD 0x800D72C ; #要拷贝的初始值来源,紧跟在固件源代码后面 DATA XREF: ER_IROM1:__scatterload_rt2o ER_IROM1:0800D704 ; ER_IROM1:off_8000390o ER_IROM1:0800D708 DCD 0x20000000 #要复制初始值的起始地址 ER_IROM1:0800D70C DCD 0xCC #带有初始值的区域大小 ER_IROM1:0800D710 DCD __scatterload_copy ER_IROM1:0800D714 DCD 0x800D7F8 ER_IROM1:0800D718 DCD 0x200000CC #要清零的变量起始地址 ER_IROM1:0800D71C DCD 0x132C #要清零的变量大小 ER_IROM1:0800D720 DCD __scatterload_zeroinit ER_IROM1:0800D724 EXPORT SHT$INIT_ARRAY$Base
因此,针对__scatterload_zeroinit而言,为了加快启动速度,建议堆空间设得尽量小,然后在SmartOS系统初始化的时候再重新设置堆空间
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
分类:
物联网
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构