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,这些库可以一定程度优化栈的使用,不过一般不支持浮点。

相关推荐
ytttr8734 小时前
基于STM32和W5500芯片的Modbus TCP协议栈实现
stm32·嵌入式硬件
上大科技蔡生5 小时前
CS5715:2.7V~26V宽输入,单节锂电池适用,最高36V输出,省掉电感电流检测电阻,软启动时间可调,异步升压DCDC控制器
单片机·嵌入式硬件·dcdc
芯思路5 小时前
STM32开发学习笔记之三【按键】
笔记·stm32·学习
CQ_YM5 小时前
51单片机(1)
单片机·嵌入式硬件·51单片机
qq_401700415 小时前
单片机之ADC(模拟数字转换器)
单片机·嵌入式硬件
无事好时节6 小时前
51 单片机GPIO / 按键 / 中断 / 定时器 / PWM
单片机·嵌入式硬件
一枝小雨7 小时前
【OTA专题】17 打通Bootloader与App逻辑之间的通信
stm32·单片机·嵌入式·流程图·freertos·ota·bootloader
2401_8633186310 小时前
基于单片机的家庭防盗报警系统
单片机·嵌入式硬件
一枝小雨10 小时前
【OTA专题】18 OTA性能优化:优化bootloader存储空间与固件完整性校验(CRC)
stm32·单片机·性能优化·嵌入式·freertos·ota·bootloader
iYun在学C10 小时前
驱动程序(注册字符设备)
linux·嵌入式硬件