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次切换时候就发生了堆栈溢出。

最新文章

  1. Unity里的Mesh属性
  2. iOS-申请邓白氏编码的超详细流程介绍
  3. codeforces Gargari and Bishops(很好的暴力)
  4. golang 文件读取
  5. Ubuntu安装sougou输入法
  6. 【转】div弹出窗口的制作
  7. 一个页面多Table多分页的问题
  8. Android开发之创建桌面快捷方式
  9. Django Model数据访问Making queries
  10. clear:both后margin-top不起作用
  11. C# 实现 Hyper-V 虚拟机 管理
  12. python基础—函数嵌套与闭包
  13. Unity 资源管理插件
  14. 使用log4j记录日志
  15. Unity 网络编程(Socket)应用
  16. Android应用图标微技巧,8.0系统中应用图标的适配
  17. Java设计模式(11)外观模式(Facade模式)
  18. 使用命令wsimport构建WebService客户端
  19. centos中如何查看tomcat的版本
  20. web项目的路径问题

热门文章

  1. 个人博客开发之 ueditor 安装
  2. RL for Robots
  3. gradle配置flavors上传nexus服务器
  4. 支付宝热补丁技术— AndFix原理[阿里Hao]
  5. ps -ef | grep java 查看所有关于java的进程
  6. rest-framework框架的基本组件分析
  7. SQL.Cookbook 读书笔记3 操作多个表
  8. HDU4781(2013成都站A题)
  9. 【BZOJ2286】[Sdoi2011]消耗战 虚树
  10. influxDB聚合类函数