STM32 内存分布探究

时间:2018-07-04
  本人在运行ucos时遇到一个非常奇怪的问题,运行一段时间后就会莫名进入hardfault函数,导致系统死机。后来根据对堆栈调试,发现每次调用的函数都不一样,甚是费解。通过map文件得出结论,原来在系统初始化的时候在flash里面读出了系统配置参数,在系统运行过程中会写flash,而flash定义的地址与程序代码存储的位置发生了重叠,一写数据就擦掉了一些函数,当调用到这些函数的时候就会发生未知指令的错误。把这个参数存储地址定义的分开些就会解决这个问题。可是,开始这个地址写好了,随着程序代码不断增多,消耗的片上flash也会增大,是个动态增长的过程,不注意很有可能发生冲突。所以在项目开发过程中定期检查定义的参数存储地址,或者干脆把参数存储地址定义在程序地址之前。
    今天详细了解一下编译后的STM32工程,堆栈内存分布情况,有助于对堆栈大小分配的理解。打开一个基于STM32f103RET6的工程,具有512KB内置flash,以及64KBSRAM,通过map文件可以看出:
  名称
  位置
  地址
  备注
  RESET复位向量
  Flash
  0x08000000
  上电执行的条代码
  库函数代码段
  Flash
  0x08000144
  在程序中调用的库函数,例如字符串处理函数、内存分配函数等
  用户自定义函数代码段
  Flash
  0x08001110
  工程模板函数库、用户自定义函数编译后的代码,以函数名首字母排
  .constdata
  Flash
  0x0800d07c-0x0800d680
  用户定义的常量
  剩余空间
  Flash
  名称
  位置
  地址
  备注
  .data
  SRAM
  0x20000000
  数据段,以及初始化的全局变量
  .bss
  SRAM
  0x20000268
  未初始化的全局变量
  HEAP(堆)
  SRAM
  0x200033e8
  启动文件定义的堆空间开始,程序调用malloc自由分配的内存在堆上
  STACK(栈)
  SRAM
  0x200073e8
  启动文件定义的栈空间开始,各个函数中的局部变量空间分配到栈上
  剩余空间
  SRAM
  例如在这个工程中,flash自定义参数存储地址,不要定义在0x0800d680之前。
  另外,还可以看出在SRAM里,分配存储的是全局变量区,未初始化变量区,堆以及栈。要注意的是,如果堆和栈定义的过小,程序默认定义都不大,一旦使用了一个较大的局部变量,有可能造成栈空间溢出,覆盖掉堆空间甚至上面的全局变量区,造成系统出错的问题。例如在做IAP的过程中,每当向flash写入512个字节时,由于大容量STM32片上flash块大小为2K,写之前要先读出,调用写函数的时候就自动创建一个2K大小的局部变量,由于栈是向上增长的,自然会覆盖堆以及全局变量区,造成未知的错误。根据片上SRAM的资源,将堆和栈适当调大一些为好,比如各设置为4K大小。
上一篇:行业功耗蓝牙SoC NCV-RSL10增强您的汽车设计
下一篇:对51单片机累加器A的逻辑操作指令及使用举例

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料