1,问题点
从M3权威指南中关于复位序列的描述可以得知,复位后硬件自动将0x0000_0000处的值传给MSP,将0x0000_0004传给PC。PC会将数据视作地址,从给定的地址取值令开始执行。我们知道传入PC的地址是复位中断处理函数的地址。后面就是一系统初始化,直到main运行。
但不是很了解MSP如何获取了正确的栈地址。
例如如下的启动文件,可以看到向量表中首地址定义的是 DCD sfe[CSTACK].
我们根据理论,这个的值必然就是栈底地址。接下来,我们分析如何实现该值的获取。
2,SFE命令说明
这里参考了IAR提供的汇编开发手册。大概意思sfe可以获取到给定section的结尾的下一个字节的地址。
举例说明,比如CSTACK段的起始地址是0x000,大小是0x400,那么他的真实结束地址是0x400-1.(因为起始地址从0x000开始的)。
SFE的效果就是得到了CSTACK段结束地址的下一个字节的地址,那就是0x400。结合我们常说的栈的特点,是从高地址向低地址生长。并且当数据入栈时,先要有SP-1,再存入数据。所以初始化栈顶在0x400位置,则不会浪费任何空间。
3,CSTACK的来源
在链接脚本中,我们对RAM进行了划分,配置了栈的起始地址和大小。如下CSTACK段是在链接文件中自定义的,人为划分了RAM区域。从map文件中,可以看到CSTACK段的起始地址是0x2001_a600。
sfe[CSTACK],获取到的值应该就是0x2001_b000。该数据将传递给MSP。
define region CSTACK_region = mem:[from m_cstack_start to m_cstack_end];
define block CSTACK with alignment = 8, size = __stack_size__ { };
place in CSTACK_region { block CSTACK };