FreeRTOS之任务堆栈溢出检查机制的补充

简介

在FreeRTOS中,每个任务都拥有自己的堆栈,该堆栈的大小由创建任务时xTaskCreate函数的函数参数所决定。

但当任务所使用的堆栈空间超出分配给它的空间时,则会发生堆栈溢出,堆栈溢出可能修改超过合法访问地址范围外的数据,严重时会导致Hardfault令系统崩溃。

如何设定合理的任务堆栈大小以避免发生堆栈溢出问题呢?
首先我们需要根据任务函数运行过程中的理论堆栈使用最大值,在任务创建时设定一个合理的任务堆栈大小,并实际运行程序进行测试,来确保系统运行过程中不会发生堆栈溢出。

剩余堆栈大小获取

在FreeRTOS中,也提供了一些API函数用来检测任务堆栈的使用情况,例如:

uxTaskGetStackHighWaterMark (TaskHandle_t xTask)

——返回自任务运行以来剩余可用堆栈空间的最小值
要使用上述函数,需要在FreeRTOSConfig.h头文件中使能宏

#define INCLUDE_uxTaskGetStackHighWaterMark      1

该函数会返回任务运行过程中剩余可用堆栈空间的最小值,即任务运行过程中堆栈最大使用量时还剩余多少空间,如果函数返回0则说明可能发生了任务堆栈溢出。在应用中调用该函数可以帮助了解任务堆栈的一个实际使用情况。

钩子函数设置

FreeRTOS中还提供了两种堆栈溢出检测方式,需要在FreeRTOSconfig.h头文件中通过宏#define configCHECK_FOR_STACK_OVERFLOW 来进行选择使能:

#define configCHECK_FOR_STACK_OVERFLOW       1

在这里插入图片描述
两种检测方式在检测原理上存在一些差别,检测方式1是检测运行过程中的任务栈指针,检测方式2则是检测初始化后的数据在运行过程中是否被修改。
如果任务堆栈溢出检测函数检测到发生了堆栈溢出,则会调用对应的钩子函数(钩子函数需用户手动创建),用户可以在钩子函数中执行想要的操作例如打印发生错误的任务名等。

void vApplicationStackOverflowHook (TaskHandle_t xTask, signed char *pcTaskName) 
{
		printf("T Task %s find stack overflow", pcTaskName);
}

内核在什么时候执行任务堆栈溢出检测:
在FreeRTOS源码 tasks.c 文件中可以查到taskCHECK_FOR_STACK_OVERFLOW在 void vTaskSwitchContext( void )函数中被调用,也就是在任务上下文切换的时候做检测。从这点可以看出软件检测栈溢出的方式具有一定的滞后性,需要在任务发生上下文切换时才会进行,任务堆栈溢出时并不能马上检测到问题。

任务堆栈溢出检测存在的局限性:
如上文所述,只有在发生任务上下文切换时才会执行任务堆栈溢出检测,发生如下错误情形时则无法检测到了:

  • 任务执行的过程中出现过栈溢出,但任务切换前栈指针又恢复到了正常水平。
  • 任务栈末尾的 16 个字节没有用到,即不会被修改,但是任务栈已经溢出了
  • 任务栈溢出后,把系统中的重要数据修改了导致系统直接进入Hardfault
    FreeRTOS提供的堆栈溢出检测会引入任务上下文切换的开销,因此仅推荐在应用开发或者测试阶段使用。虽然存在一定的局限性,但大多常见情况下这些检测机制依然是非常实用的功能,可以帮助用户减少代码中的错误并提高应用程序代码的质量。

总结

#define configCHECK_FOR_STACK_OVERFLOW                1  //打开堆溢出钩子函数
#define configUSE_MALLOC_FAILED_HOOK                  1  //打开malloc失败钩子函数
 
 
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
    LOG_ERR(GTK_DBG_APP_SYS, "stack overflow:%s", pcTaskName);
    ASSERT(0);
}
 
 
void vApplicationMallocFailedHook( void )
{
    LOG_ERR(GTK_DBG_APP_SYS, "malloc error");
    ASSERT(0);
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路过的小熊~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值