Cortex-M0 代码解析——01基本操作
1. 从复位到main初始化配置代码理解
看过Keil工程中的startup文件都知道,代码段起始是栈地址,随后是ResetHandle中断地址。
通过工具查看编译后的bin文件,获取ResetHandle地址,从而能够代码继续更进。比如:
(我代码起始地址配置了0x1000)
在ResetHandle中,对于Cortex-M3比如stm32标准库而言,会提供时钟初始化等操作。Cortex-M0看各家芯片厂商如何配置的。随后都会调用如下代码进行跳转(其中__main中的代码,)
1.1 __main中做了什么?
随后继续跟进,在__main中其实本质上是执行了如下几个操作:
- 若有代码需要放于RAM中运行,则会进行代码重定向。(也即将相关的代码从code中搬移到ram区域)
- 将data区数据,搬移到ram中,则该部分变量可读可写。
- bss段清0。
汇编执行流程如下图所示:
其中,一些简单的汇编理解,这里不再赘述。因为我觉得有耐心看我写的这篇文章的人,必定对汇编是有一定的了解的。其中特别关键的就是最下面那两个参数。(稍后有详细的计算说明)
我们查看keil编译后的map文件的时候,有两个重要的地址。见下:
(这个是我在另一个工程中摘出来的,地址和上述汇编不同,理解概念就好。不用纠结细节)
Region$$Table$$Base 0x000043ec Number 0 anon$$obj.o(Region$$Table)
Region$$Table$$Limit 0x0000440c Number 0 anon$$obj.o(Region$$Table)
汇编中的那两个参数便于此有关,从上面的汇编代码执行流程可以看出,
Region_Table_Base = 0x10B8 + 0x25D8 = 0x3690
Region_Table_Limit = 0x10B8 + 0x2608 = 0x36C0
共48字节。也即12个字。
其中,Region_Table_Base是一个基地址。从该地址处开始,以如下结构的方式进行顺序排列,到Region_Table_Limit为止。
- addr_src: 待搬移数据的源地址
- addr_des: 待搬移数据的目的地址
- len: 搬移的长度
- copy_function: 数据搬移函数地址
从上面的数据中,可以看出相关的参数和对应的搬移函数的地址。也即调用了3个函数,进行了三种数据的搬移。
0x10C0——将放于ram中运行的代码段进行搬移,也即下图中的__scatterload_copy,第一次执行完毕,之后会返回的__scatterload_null标签的地址处继续执行。
0x132E——是压缩数据的搬移,该部分通过压缩算法(应该是keil实现的吧?),将代码中data段被压缩的数据,解压缩后,搬移到相应的ram对应的空间中去。该部分的压缩和解压缩算法,下一个章节再详细描述(>@aaa@qq.com< 现在都晚上11点了,想睡觉了)
0x10DC——bss段清零函数
1.2 执行完上述搬移之后,进入__rt_entry
这部分代码中,主要执行配置栈和堆空间大小以及相关标准库的初始化等操作,这部分我没有太过于详细的理解。就不再说明了。最终进入main函数,开始执行开发者的代码。(简单介绍完毕 &_&)
2. 补充点题外话
Total RO Size (Code + RO Data) 9228 ( 9.01kB)
Total RW Size (RW Data + ZI Data) 5128 ( 5.01kB)
Total ROM Size (Code + RO Data + RW Data) 9344 ( 9.13kB)
代码占用空间大小(常见都是下载到flash中的代码)就是ROM_Size
占用RAM空间大小为 RW_Size + Stack_Size + Heap_Size,其中堆和栈的大小都是在startup文件中配置的。
(当然了,还是那句话,这个是另一个工程中的map文件,大小的细节就不要在意啦。)
好的,简单介绍到这里,下一章节再做补充。
上一篇: 汇编语言 第14章实验