Free rtos每个任务都有自己的栈空间,每个任务需要的栈大小也是不同的。如果堆栈过小就会造成栈溢出,有时候栈溢出发生在某种特定顺序的任务切换中,比较难检测出。所以前期测试和监控任务栈用量就显得尤其重要。
#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");
}
/**
* @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");
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章