1 /* 2 * FreeRTOS Kernel V10.6.2 3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * https://www.FreeRTOS.org 25 * https://github.com/FreeRTOS 26 * 27 */ 28 29 #ifndef STACK_MACROS_H 30 #define STACK_MACROS_H 31 32 /* 33 * Call the stack overflow hook function if the stack of the task being swapped 34 * out is currently overflowed, or looks like it might have overflowed in the 35 * past. 36 * 37 * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check 38 * the current stack state only - comparing the current top of stack value to 39 * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 40 * will also cause the last few stack bytes to be checked to ensure the value 41 * to which the bytes were set when the task was created have not been 42 * overwritten. Note this second test does not guarantee that an overflowed 43 * stack will always be recognised. 44 */ 45 46 /*-----------------------------------------------------------*/ 47 48 /* 49 * portSTACK_LIMIT_PADDING is a number of extra words to consider to be in 50 * use on the stack. 51 */ 52 #ifndef portSTACK_LIMIT_PADDING 53 #define portSTACK_LIMIT_PADDING 0 54 #endif 55 56 #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) 57 58 /* Only the current stack state is to be checked. */ 59 #define taskCHECK_FOR_STACK_OVERFLOW() \ 60 do { \ 61 /* Is the currently saved stack pointer within the stack limit? */ \ 62 if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \ 63 { \ 64 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 65 } \ 66 } while( 0 ) 67 68 #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 69 /*-----------------------------------------------------------*/ 70 71 #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) 72 73 /* Only the current stack state is to be checked. */ 74 #define taskCHECK_FOR_STACK_OVERFLOW() \ 75 do { \ 76 \ 77 /* Is the currently saved stack pointer within the stack limit? */ \ 78 if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ 79 { \ 80 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 81 } \ 82 } while( 0 ) 83 84 #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 85 /*-----------------------------------------------------------*/ 86 87 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) 88 89 #define taskCHECK_FOR_STACK_OVERFLOW() \ 90 do { \ 91 const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ 92 const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \ 93 \ 94 if( ( pulStack[ 0 ] != ulCheckValue ) || \ 95 ( pulStack[ 1 ] != ulCheckValue ) || \ 96 ( pulStack[ 2 ] != ulCheckValue ) || \ 97 ( pulStack[ 3 ] != ulCheckValue ) ) \ 98 { \ 99 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 100 } \ 101 } while( 0 ) 102 103 #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 104 /*-----------------------------------------------------------*/ 105 106 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) 107 108 #define taskCHECK_FOR_STACK_OVERFLOW() \ 109 do { \ 110 int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ 111 static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 112 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 113 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 114 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 115 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ 116 \ 117 \ 118 pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ 119 \ 120 /* Has the extremity of the task stack ever been written over? */ \ 121 if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ 122 { \ 123 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ 124 } \ 125 } while( 0 ) 126 127 #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 128 /*-----------------------------------------------------------*/ 129 130 /* Remove stack overflow macro if not being used. */ 131 #ifndef taskCHECK_FOR_STACK_OVERFLOW 132 #define taskCHECK_FOR_STACK_OVERFLOW() 133 #endif 134 135 136 137 #endif /* STACK_MACROS_H */ 138