每个任务都有一个自己的堆栈,如果任务使用xTaskCreate()创建,则任务堆栈会自动从堆内存上创建。如果使用xTaskCreateStatic()创建,则堆栈由开发者自己确定并提供。堆栈溢出是影响系统稳定性的一个常见因素,freeRTOS提供两种可选的用于检测和纠正堆栈溢出的机制。使用配置选项configCHECK_FOR_STACK_OVERFLOW设置。

注意,这些选择只在那些内存映射不是分段的架构上有效。同时,某些处理器会在freeRTOS检测到堆栈溢出之前就产生了一个错误或者异常。应用程序必须保证堆栈溢出的钩子函数使能设置configCHECK_FOR_STACK_OVERFLOW不为0,并且提供如下形式的钩子函数:

  1. void vApplicationStackOverflowHook( TaskHandle_t xTask,
  2. signed char *pcTaskName );

通过参数xTaskpcTaskName,开发者可以确定是哪个任务堆栈发生溢出,从而进行相应处理。需要注意的是,根据堆栈的溢出程度不同,这些参数本身可能也是不正确的,在这种情况下可以通过访问当前任务控制块pxCurrentTCB来获取堆栈溢出任务信息。

堆栈溢出检测

方法1

在每次RTOS内核进行上下文的切换时,任务的堆栈可能会达到最大值。因此,内核检测堆栈指针(stack poiter)来判断当前堆栈是否溢出。

这种方法很快速,但是无法保证捕捉到所有的堆栈溢出。将configCHECK_FOR_STACK_OVERFLOW设置为1,使用这种检测方法。

方法2

这个方法比较有趣,在每个任务创建时,将它的堆栈用特定数值填充。因此,当堆栈没有溢出时,堆栈最后的内存数据应该始终是初始的填充值。freeRTOS通过检测堆栈的最后16个字节的数据是否发生改变,来确定堆栈是否溢出。

相比方法1,这个方法效率要低,但是仍然很快速。同样无法保证能捕捉到所有的堆栈溢出,例如溢出时,后16个字节覆写的就是填充值。

configCHECK_FOR_STACK_OVERFLOW设置为2,将和方法1一起使用,无法单独使用方法2。