FreeRTOS — 任务栈大小确定及其溢出检测
以下内容转载自安富莱电子:http://forum.armfly.com/forum.php
给任务分配多大的栈空间,一直是初学者比较头疼的问题, 下面就主要讲解如何解决此问题。
1 任 务 栈 大 小 的 确 定
在基于 RTOS 的应用设计中,每个任务都需要自己的栈空间,应用不同,每个任务需要的栈大小也是不同的。将如下的几个选项简单的累加就可以得到一个粗略的栈大小:
一般来说,用户可以事先给任务分配一个大的栈空间,然后通过调试的方法打印任务栈的使用情况,运行一段时间就会有个大概的范围了。这种方法比较简单且实用些。
2 、什 么 是 栈 溢 出
栈溢出 — 简单的说就是用户分配的栈空间不够用了,溢出了。举一个简单的实例,栈生长方向从高地址向低地址生长(M4 和 M3 是这种方式)。
(1) 上图标识 1 的位置是 RTOS 的某个任务调用了函数 test()前的 SP 栈指针位置。
(2) 上图标识 2 的位置是调用了函数 test 需要保存返回地址到栈空间。这一步不是必须的,对于 M3和 M4 内核是先将其保存到 LR 寄存器中,如果 LR 寄存器中有保存上一级函数的返回地址,需要将 LR 寄存器中的内容先入栈。
(3) 上图标识 3 的位置是局部变量 int i 和 int array[10]占用的栈空间,但申请了栈空间后已经越界了。这个就是所谓的栈溢出了。如果用户在函数 test 中通过数组 array 修改了这部分越界区的数据且这部分越界的栈空间暂时没有用到或者数据不是很重要,情况还不算严重,但是如果存储的是关键数据,会直接导致系统崩溃。
(4) 上图标识 4 的位置是局部变量申请了栈空间后,栈指针向下偏移(返回地址+变量 i+10 个数组元素)*4 =48 个字节。
(5) 上图标识 5 的位置可能是其它任务的栈空间,也可能是全局变量或者其它用途的存储区,如果 test函数在使用中还有用到栈的地方就会从这里申请,这部分越界的空间暂时没有用到或者数据不是很重要,情况还不算严重,但是如果存储的是关键数据,会直接导致系统崩溃。
3 、FreeRTOS的 栈 溢 出 检 测 机 制
FreeRTOS 提供了两种栈溢出检测机制,这两种检测都是在任务切换时才会进行:
方法一
在任务切换时检测任务栈指针是否过界了,如果过界了,在任务切换的时候会触发栈溢出钩子函数。
void vApplicationStackOverflowHook( TaskHandle_t xTask,signed char *pcTaskName );
用户可以在钩子函数里面做一些处理。这种方法不能保证所有的栈溢出都能检测到。比如任务在执行的过程中出现过栈溢出。任务切换前栈指针又恢复到了正常水平,这种情况在任务切换的时候是检测不到的。又比如任务栈溢出后,把这部分栈区的数据修改了,这部分栈区的数据不重要或者暂时没有用到还好,但如果是重要数据被修改将直接导致系统进入硬件异常,这种情况下,栈溢出检测功能也是检测不到的。
使用方法一需要用户在 FreeRTOSConfig.h 文件中配置如下宏定义:
#define configCHECK_FOR_STACK_OVERFLOW 1
方法二
任务创建的时候将任务栈所有数据初始化为 0xa5,任务切换时进行任务栈检测的时候会检测末尾的 16 个字节是否都是 0xa5,通过这种方式来检测任务栈是否溢出了。相比方法一,这种方法的速度稍慢些,但是这样就有效地避免了方法一里面的部分情况。不过依然不能保证所有的栈溢出都能检测到,比如任务栈末尾的 16 个字节没有用到,即没有被修改,但是任务栈已经溢出了,这种情况是检测不到的。另外任务栈溢出后,任务栈末尾的 16 个字节没有修改,但是溢出部分的栈区数据被修改了,这部分栈区的数据不重要或者暂时没有用到还好,但如果是重要数据被修改将直接导致系统进入硬件异常,这种情况下,栈溢出检测功能也是检测不到的。
使用方法二需要用户在 FreeRTOSConfig.h 文件中配置如下宏定义:
#define configCHECK_FOR_STACK_OVERFLOW 2
除了 FreeRTOS 提供的这两种栈溢出检测机制,还有其它的栈溢出检测机制,可以在 Mircrium 官方发布的:这个博文中学习。
钩子函数
钩子函数的主要作用就是对原有函数的功能进行扩展,用户可以根据自己的需要往里面添加相关的测试代码,可以在 FreeRTOS 工程中检索这个钩子函数 vApplicationStackOverflowHook 所在的位置。
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并,获取更多隐藏干货,QQ交流群:859800032 微信公众号:Crystal软件学堂
作者:Liu_Jing bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |