1 /* 2 * FreeRTOS Kernel V11.1.0 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 char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 65 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 66 } \ 67 } while( 0 ) 68 69 #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 70 /*-----------------------------------------------------------*/ 71 72 #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) 73 74 /* Only the current stack state is to be checked. */ 75 #define taskCHECK_FOR_STACK_OVERFLOW() \ 76 do { \ 77 \ 78 /* Is the currently saved stack pointer within the stack limit? */ \ 79 if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ 80 { \ 81 char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 82 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 83 } \ 84 } while( 0 ) 85 86 #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 87 /*-----------------------------------------------------------*/ 88 89 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) 90 91 #define taskCHECK_FOR_STACK_OVERFLOW() \ 92 do { \ 93 const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ 94 const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \ 95 \ 96 if( ( pulStack[ 0 ] != ulCheckValue ) || \ 97 ( pulStack[ 1 ] != ulCheckValue ) || \ 98 ( pulStack[ 2 ] != ulCheckValue ) || \ 99 ( pulStack[ 3 ] != ulCheckValue ) ) \ 100 { \ 101 char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 102 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 103 } \ 104 } while( 0 ) 105 106 #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 107 /*-----------------------------------------------------------*/ 108 109 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) 110 111 #define taskCHECK_FOR_STACK_OVERFLOW() \ 112 do { \ 113 int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ 114 static const uint8_t ucExpectedStackBytes[] = { 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 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 117 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 118 tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ 119 \ 120 \ 121 pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ 122 \ 123 /* Has the extremity of the task stack ever been written over? */ \ 124 if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ 125 { \ 126 char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 127 vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 128 } \ 129 } while( 0 ) 130 131 #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 132 /*-----------------------------------------------------------*/ 133 134 /* Remove stack overflow macro if not being used. */ 135 #ifndef taskCHECK_FOR_STACK_OVERFLOW 136 #define taskCHECK_FOR_STACK_OVERFLOW() 137 #endif 138 139 140 141 #endif /* STACK_MACROS_H */ 142