cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)

以Cortex-M3 SoC芯片的hello_world软件仿真为例:

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(1)

我们先以keil编译结果为例说明,gcc的编译另文讲。

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(2)

放大看:

Program Size:

Code=664

RO-data=224

RW-data=8

ZI-data=864

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(3)

  • ① Code为一堆ARM指令代码,存放在eflash;
  • ② RO DATA为只读数据;
  • ③ RW DATA为非0初始化的全局和静态变量,需从flash搬运到sram;
  • ④ ZI DATA(zero initialize)为0初始化的内存区的大小(包含0初始化的全局和静态变量 堆区 栈区)。

简单的说,程序运行时,

芯片FLASH占用的空间为:Code RO Data RW Data,

芯片RAM 占用的空间为:RW Data ZI Data;

打开hex文件,看一下前四个字节0x2000_0368。

很惊喜,hex文件的前4个字节为主堆栈指针MSP的初值。

主堆栈指针大小:

0x2000_0368 - 0x2000_0000(SRAM起始地址)

= 0x368(十进制872),

刚好是 RW-data(8) ZI-data(864) = 872 的大小。

这就解释了MSP主堆栈指针是怎么产生的疑惑了。同时,也证明了RAM的大小确实=RW ZI的大小。

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(4)

理论上初始化时给堆栈指针赋值为RAM的最高地址即可,如下图,初始化时给堆栈指针赋值0x2000_0000 0x10000 = 0x2001_0000;

但是用keil编译时,keil并不是按RAM的最高地址生成的HEX前4字节(也即MSP的初值),而是按照:

全局和静态变量的容量 Heap_Size Stack_Size三者之和,作为HEX文件的前4字节。

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(5)

通常还是把0x10000 0x2000_0000(RAM起始地址)作为MSP的初值更好,但keil不是这么做的,keil仅把这个值用作编译检测:检查全局和局部静态变量(含0初始化和非0初始化两部分)所占的空间 堆区 栈区,它们所占空间之和是否超过了上图红框里0x10000值,如果超了就编译报错。

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(6)

cortex-m3的引脚(MCUCortex-M3SoC的主栈指针)(7)

Heap Size:

keil编译时,会把C库函数支持的malloc、free所需的内存指向heap内存区,当我们不断的malloc吃内存堆时,malloc函数会检测程序已吃掉的内存堆是否超过了Heap_Size,超了的话就会返回NULL。

如果我们不打算使用C库提供的动态内存分配,而打算使用自己写的内存堆管理程序,甚至干脆不打算使用动态内配功能,这些情况下,没有用到标准库的malloc,直接设置heap size为0即可。

补充一下,还有个重要问题,中断向量表中的向量值是多少呢?怎么指向中断服务函数的入口地址呢?

比如复位中断服务函数:Reset_Handler,这个函数的命名不能是随意的,中断服务函数的命名必须和xx_start.s里面对应的向量名相同,这样cpu才能从向量表中查找到对应中断的中断服务函数的入口地址,也就是说,从向量表中对应中断位置读出的向量值就是PC值,CPU从该PC值地址去取中断服务函数指令。

还有一点,xx_start.s里面对应的向量名后面都有个WEAK,也就是各中断服务函数都可以被软件人员开发的中断服务函数自动覆盖。

感谢阅读文章,如果文章有用,麻烦点个“在看”或转发分享。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页