stm32如何了解栈的使用情况

随着项目变得复杂,有时候系统会莫名卡死,原因之一很可能就是栈溢出了。而栈溢出不一定会立刻出问题,所以不容易及时发现。那如何了解栈的使用情况呢?下面就使用嵌入式操作系统和裸机系统分别介绍查看方法。

嵌入式操作系统(FreeRTOS)

这里以FreeRTOS系统为例,它提供了获取栈使用量的函数和栈溢出时的回调函数,直接调用和配置即可。

这个函数会获取task运行过程中栈空间的最小剩余量,这个值越小栈越接近溢出,根据这个值调整栈空间的大小,一般预留20%左右的余量。

FreeRTOS还提供了栈溢出钩子函数,发生栈溢出时调用,它只能做一些善后工作,无法恢复系统,

想要调用钩子函数,还需要在FreeRTOSConfig.h中定义下面的宏

这个宏的值可以是1、2、3(较新的版本才会有3),1检测栈指针是否越界,2检测栈区最后的20字节是否被覆盖,3检测ISR的栈。实测1会直接触发系统的HardFault并调用HardFault_Handler回调函数,2会调用钩子函数,推荐设置成2,3不会调用钩子函数。建议在HardFault回调中也输出信息,

裸机系统

对于裸机系统,可以自己定义函数检测。用特定的字符填充栈区,后面通过这些字符判断栈的使用情况

栈的信息在ld链接文件中定义,ld中的=是设置变量的地址,而不是变量的值,所以引用的时候需要加&。栈指针指向的是栈区已使用的末端地址,而不是未使用的首地址,所以要先减再赋值。

stack_init函数可以在main中最开始调用,不过会破坏进入main的调用栈数据,由于嵌入式系统进入main后一般不会返回,所以不影响程序的运行。如果不想破坏可以把这个函数放到startup文件中的Reset_Handler函数内SystemInit之前,这样完全不会影响后边程序运行的栈区数据。

之后从栈区开始逐个比较栈区数据和填充数据,如果不一样说明这个地址的数据被入栈操作覆盖,这样便可以得出栈的最大使用量。

调用时尽量放到程序执行的末尾,让所有函数都执行一次,这样才能获得较准确的栈最大使用量。

读取sp寄存器可以获得当前栈指针位置,获取当前栈使用情况

标准库的printf有多层函数调用,尤其打印浮点数时,有log打印和没log打印栈的使用情况是不同的,所以有时候栈溢出程序异常时,去掉printf就能正常运行。如果必须输出log,除了调大栈空间,也可以使用其它轻量级的printf库,比如FreeRTOS的printf-stdarg.c,这些库可以一定程度优化栈的使用,不过一般不支持浮点。

相关推荐
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
Lester_11015 天前
STM32霍尔传感器输入口设置为复用功能输入口时,还能用GPIO函数直接读取IO的状态吗
stm32·单片机·嵌入式硬件·电机控制
LCG元5 天前
低功耗显示方案:STM32L0驱动OLED,动态波形绘制与优化
stm32·嵌入式硬件·信息可视化
三佛科技-187366133975 天前
120W小体积碳化硅电源方案(LP8841SC极简方案12V10A/24V5A输出)
单片机·嵌入式硬件
z20348315205 天前
STM32F103系列单片机定时器介绍(二)
stm32·单片机·嵌入式硬件
古译汉书5 天前
【IoT死磕系列】Day 7:只传8字节怎么控机械臂?学习工业控制 CANopen 的“对象字典”(附企业级源码)
数据结构·stm32·物联网·http
Alaso_shuang5 天前
STM32 核心输入、输出模式
stm32·单片机·嵌入式硬件
脚后跟5 天前
AI助力嵌入式物联网项目全栈开发
嵌入式硬件·物联网·ai编程
2501_918126915 天前
stm32死锁是怎么实现的
stm32·单片机·嵌入式硬件·学习·个人开发
z20348315205 天前
STM32F103系列单片机定时器介绍(一)
stm32·单片机