freertos栈溢出检测原理
- RTOS
- 2024-05-24
- 203热度
- 0评论
- portSTACK_GROWTH > 0:栈向上生长
- portSTACK_GROWTH < 0: 栈向下生长,本章使用栈向下生长
打开 configRECORD_STACK_HIGH_ADDRESS 1,将PCB中将打开pxEndOfStack,结构如下。
adress:0+ulStackDepth ------------------- pxEndOfStack(栈底)
|XXXXXXXXXXXXXXXXXX|
adress:0+x --------------------pxTopOfStack(栈顶) / StkCur(当前栈)
| |
| |
| |
adress:0 ------------------- pxStack / pxTaskStatus->pxStackBase / StkBot
栈溢出检测原理
configCHECK_FOR_STACK_OVERFLOW 1
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
/* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
/* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
因为栈是向下生长的,所有判断pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack即表示溢出。
configCHECK_FOR_STACK_OVERFLOW > 1
打开tskSET_NEW_STACKS_TO_KNOWN_VALUE =1
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
#define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
#else
#define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
#endif
将栈填充为 0xa5
prvInitialiseNewTask
#if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
{
/* Fill the stack with a known value to assist debugging. */
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
}
#endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
通过比较栈顶的值是否不等于0xa5a5a5a5来判断栈溢出,前面讲栈都填充为0xa5。
#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[ 0 ] != ulCheckValue ) || \
( pulStack[ 1 ] != ulCheckValue ) || \
( pulStack[ 2 ] != ulCheckValue ) || \
( pulStack[ 3 ] != ulCheckValue ) ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/
所以两种检测方法,第一种是通过比较pxTopOfStack的是否小于起始地址,第二种是看填充的数据是否被修改。