@[Apollo2(Cortex-M4)MCU启动文件详解]
Apollo2(Cortex-M4)MCU启动文件详解
最近项目中用到超低功耗半导体解决方案领先厂商Ambiq Micro的Apollo2 MCU,该MCU是基于ARM公司的Cortex-M4架构。因此,借此机会分析一下启动文件,文章有什么错误欢迎大家批评、指正。
详细分析汇编启动代码
1、汇编语言------------EQU
EQU伪指令,作用是左边的符号名代表右边的表达式,相当于C语言中的#define。这里定义Stack这个符号表示数值0x00002300。其实,后面对栈区的存储大小会用到此值。通过查看编译后生成的.map文件也会发现栈的设置大小。
Stack EQU 0x00002300
通过下面的.map文件可以发现STACK的大小为8960,转换成16进制正是上面设置的0x00002300。注:.map文件五个字段含义如下:
- Symbol Name:符号名称
- Value:存储对应的地址;
- Ov Type:符号对应的类型。符号类型大概有几种:Number、Section、Thumb Code、Data等;全局、静态变量等位于0x2000xxxx的内存RAM中。
- Size:存储大小。我们怀疑内存溢出,可以查看代码存储大小来分析。
- Object(Section):段目标。这里一般指所在模块(所在源文件)。
STACK 0x10005008 Section 8960 startup_keil.o(STACK)
定义Heap符号的大小,这里会在后面堆大小设置时,设置为0。
Heap EQU 0x00000000
查看.map文件,得到如下:
HEAP 0x10004440 Section 0 startup_keil.o (HEAP)
注:DATA与EQU区别如下:EQU 将数值或者寄存器名赋值给一个指定的符号名;DATA 用于将一个内部的RAM地址赋值给指定的符号名。
注:堆(heap)和栈(stack)的区别:
堆:由malloc函数分配的空间所在的地址区域,地址由低向高增长;
栈:自动分配的地址,函数调用的时候所使用的地址空间,地址由高向低减少;
在C/C++程序占用的内存分为以下部分:
栈区:由编译器自动分配和释放,用来存放函数的参数值和局部变量的值,其操作方式类似于数据结构中的栈;
堆区:由程序员分配和释放,如果程序员没有释放,在程序结束时会有OS回收,。与数据结构中的堆是不一样的;
全局区(静态区):初始化的全局变量和静态变量存放在这一块,程序结束时由系统释放;
文字常量区:常量字符串就放在这里,程序结束时由系统释放;
程序代码区:用来存放二进制代码;
2、汇编语言------------AREA伪指令
AREA用于定义一个代码段或者数据段,下面代码的意思开辟一段名为STACK的内存单元,其中NOINIT表示该内存单元不进行初始化,ALIGN=3表示以2的3次方进行对齐,在默认的ELF可执行文件的代码段和数据段是按照字对齐的。__initial_sp表示栈空间顶地址,是汇编代码的地址标号。__heap_limit堆空间结束地址。
AREA STACK, NOINIT, READWRITE, ALIGN=3
StackMem
SPACE Stack
__initial_sp
AREA HEAP, NOINIT