FreeRtos堆栈检测应用
Free rtos每个任务都有自己的栈空间,每个任务需要的栈大小也是不同的。如果堆栈过小就会造成栈溢出,有时候栈溢出发生在某种特定顺序的任务切换中,比较难检测出。所以前期测试和监控任务栈用量就显得尤其重要。
- FreeRTOSConfig.h文件中配置宏定义:
#define configCHECK_FOR_STACK_OVERFLOW 2
#define INCLUDE_uxTaskGetStackHighWaterMark 1
- 在任务切换时检测任务栈指针是否过界了,如果过界了,在任务切换的时候会触发栈溢出钩子函数。
void vApplicationStackOverflowHook( TaskHandle_t xTask,signed char *pcTaskName );
- 用户可以在钩子函数里面做一些处理。
- 任务创建的时候将任务栈所有数据初始化为0xa5,任务切换时进行任务栈检测的时候会检测末尾的16个字节是否都是0xa5,通过这种方式来检测任务栈是否溢出了。相比方法一,这种方法的速度稍慢些,但是这样就有效地避免了方法一里面的部分情况。不过依然不能保证所有的栈溢出都能检测到,比如任务栈末尾的16个字节没有用到,即没有被修改,但是任务栈已经溢出了,这种情况是检测不到的。另外任务栈溢出后,任务栈末尾的16个字节没有修改,但是溢出部分的栈区的数据修改了,这部分栈区的数据不重要或者暂时没有用到还不会有什么问题,但如果是重要数据被修改将直接导致系统进入硬件异常,这种情况下,栈溢出检测功能也是检测不到的。
- 溢出检测的实现原理:
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
\
if( ( pulStack[ ] != ulCheckValue ) || \
( pulStack[ ] != ulCheckValue ) || \
( pulStack[ ] != ulCheckValue ) || \
( pulStack[ ] != ulCheckValue ) ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
} #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
- 实现用户的钩子函数:
/**
* @brief if task overflow, it will run here.
* @param [IN]task handle.
* @param [IN]task name string pointer.
* @retval None
*/
void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
{
while()
{
printf("task %s is stack overflow. \r\n", pcTaskName);
vTaskDelay();
}
}
- 测试每个任务的堆栈大小:
/**
* @brief check all task stack and get the remain stack size.
* @param None.
* @retval None
*/
void CheckTaskStack(void)
{
uint8_t i = ;
float stack_usage = ; DEBUG_PRINT("\r\n------------------------------------\r\n");
for(i=; i<APP_TASK_NUMS; i++)
{
TaskConfigStruct[i].stack_remain = uxTaskGetStackHighWaterMark( TaskConfigStruct[i].handle );
stack_usage = 100.0f*((float)TaskConfigStruct[i].stack_max -
(float)TaskConfigStruct[i].stack_remain )/ (float)TaskConfigStruct[i].stack_max;
DEBUG_PRINT("> id=%d, name=%8s, stack usage=%5.2f%%, free/all=%4d/%4d.\r\n",
TaskConfigStruct[i].id, TaskConfigStruct[i].name, stack_usage,
TaskConfigStruct[i].stack_remain, TaskConfigStruct[i].stack_max );
}
DEBUG_PRINT("------------------------------------\r\n\r\n");
}
- 测试结果,还剩余4个u32空间,溢出检测的方法2刚好是检查最后的4个数据,此时恰好不会触发overflow。

/**
* @brief check all task stack and get the remain stack size.
* @param None.
* @retval None
*/
void CheckTaskStack(void)
{
uint8_t i = ;
uint8_t i2 = ; // test stack overflow
float stack_usage = ; DEBUG_PRINT("\r\n------------------------------------\r\n");
for(i=; i<APP_TASK_NUMS; i++)
{
TaskConfigStruct[i].stack_remain = uxTaskGetStackHighWaterMark( TaskConfigStruct[i].handle );
stack_usage = 100.0f*((float)TaskConfigStruct[i].stack_max -
(float)TaskConfigStruct[i].stack_remain )/ (float)TaskConfigStruct[i].stack_max;
DEBUG_PRINT("> id=%d, name=%8s, stack usage=%5.2f%%, free/all=%4d/%4d.\r\n",
TaskConfigStruct[i].id, TaskConfigStruct[i].name, stack_usage,
TaskConfigStruct[i].stack_remain, TaskConfigStruct[i].stack_max );
}
DEBUG_PRINT("------------------------------------\r\n\r\n");
}
- 测试结果:再次定义局部变量uint8_t i2, 任务切换时候压栈会把i2入栈,此时会触发溢出检测。测试发现,任务在第2次切换时候就发生了堆栈溢出。

FreeRtos堆栈检测应用的更多相关文章
- FREERTOS 手册阅读笔记
郑重声明,版权所有! 转载需说明. FREERTOS堆栈大小的单位是word,不是byte. 根据处理器架构优化系统的任务优先级不能超过32,If the architecture optimized ...
- STM32 使用 FreeRTOS过程记录
资源:http://blog.csdn.net/zhzht19861011/article/category/6191478 资源:可以下载安富莱的STM32-V5开发版资料中的FreeRTOS教程, ...
- 嵌入式学习笔记(综合提高篇 第二章) -- FreeRTOS的移植和应用
1.1 资料准备和分析 上章节通过实现双机通讯,了解如何设计和实现自定义协议,不过对于嵌入式系统来说,当然不仅仅包含协议,还有其它很多需要深入学习了解的知识,下面将列出我在工作和学习上遇到的嵌入 ...
- FreeRTOS config开始的宏
FreeRTOSConfig.h系统配置文件中可以自定义,FreeRTOS.h中定义默认值 configAPPLICATION_ALLOCATED_HEAP 默认情况下FreeRTOS的堆内存是由编译 ...
- FreeRTOS相关转载-(朱工的专栏)
FreeRTOS系列第1篇---为什么选择FreeRTOS? 1.为什么学习RTOS? 作为基于ARM7.Cortex-M3硬件开发的嵌入式工程师,我一直反对使用RTOS.不仅因为不恰当的使用RTOS ...
- FreeRTOS系列第20篇---FreeRTOS信号量API函数
FreeRTOS的信号量包括二进制信号量.计数信号量.相互排斥信号量(以后简称相互排斥量)和递归相互排斥信号量(以后简称递归相互排斥量).我们能够把相互排斥量和递归相互排斥量看成特殊的信号量. 信号量 ...
- 10.3-uC/OS-III内部任务管理(TCB)
任务控制块 TCB 1.任务控制块是被uC/OS-III用于维护任务的一个结构体.每个任务都必须有自己的 TCB. uC/OS-III 在 RAM 中分配 TCB.当调用uC/OS-III提供的与任务 ...
- C++编译器详解(一)
C/C++编译器-cl.exe的命令选项 和在IDE中编译相比,命令行模式编译速度更快,并可以避免被IDE产生的一些附加信息所干扰,本文将介绍微软C/C++编译器命令行模式设定和用法. 1.设置环境变 ...
- VC6.0编译器设置
主要通过VC的菜单项Project->Settings->C/C++页来完成.我们可以看到这一页的最下面Project Options中的内容,一般如下:/nologo /MDd /W3 ...
随机推荐
- 【转】Web前端开发:为何选择MVVM而非MVC
在Web中充斥着所谓的MVC框架,而在我看来,因为一些关键性的技术原因,MVC在Web前端开发中根本无法使用(对的,是无法,而不是不该) 在Web中充斥着所谓的MVC框架,而在我看来,因为一些关键性的 ...
- Hibernate使用xml文件的每个类层次一张表
通过这种继承策略,我们可以通过单表映射整个层次结构. 这里,在表中创建一个额外的列(也称为discriminator列)来标识该类. 让我们先了解问题.下面给出的整个层次类映射到数据库的一个表中图解说 ...
- Sping 的 BeanFactory 容器
Sping 的 BeanFactory 容器 这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.B ...
- 猜数字游戏-python
题目: 用python写一个猜数字的游戏,游戏规则如下: 1.由一个人随机写一个整数1-99(如:21) 2.一群小伙伴轮流猜数字,如第一个人猜一个数(如:48),则缩小范围至(1-48) 3.如第二 ...
- 读取文件之<绝对路径>与<相对路径>
前言:字符流.字节流读取文件,下面的代码是在网上找到的一个各种文件读取方式,还算比较详细,分享给大家. public class ReadFromFile { /** * 以字节为单位读取文件,常用于 ...
- Scala之模式匹配(Patterns Matching)
前言 首先.我们要在一開始强调一件非常重要的事:Scala的模式匹配发生在但绝不仅限于发生在match case语句块中.这是Scala模式匹配之所以重要且实用的一个关键因素!我们会在文章的后半部分具 ...
- ios 制作自已的framework
本文转载至 http://blog.csdn.net/chen505358119/article/details/9190731 ios中我们写的代码有时不愿意让别人看到,可能对它进行封装,生成一 ...
- linux 终端操作快捷键
熟练使用快捷键可以很大的提高效率,以下列出一些常用的快捷键命令方便随时查阅 1. 移动光标 Ctrl + a 标移到行首.它在多数文本编辑器和 Mozilla 的 URL 字段内可以使用.Ctrl + ...
- 一个有趣的IP不同的问题?
1.我们已经知道了内网和外网的显示是不同的. 2.今天发现了我的飞Q传输上显示的ip和电脑上网络中显示的ip不同,但是传输文件是可以的,至于这个问题目前没有找到合理的解释,解释这个问题,但是这样就奇怪 ...
- Springboot中jar 重复冲突 导致 静态资源加载问题!
这个jar 其实在common 中也是存在的 ,当时没注意看,就导入进来了,然后 css js 等一些静态资源全部不能加载!具体原因我没去深挖!后面找个时间深挖下,先填坑!