There are a total of three bugs.
Two bugs are found in StaticTaskt which are evident comparing the definition of StaticTaskt in FreeRTOS.h and TCB_t in task.c. This causes a false stack overflow failure because the stack overflow check fails on the first byte (ucDelayAborted is written as pdFALSE or pdTRUE). These may also cause weird behaviour with xTaskAbortDelayalthough I have not verified this.
typedef struct xSTATICTCB
#if ( portUSINGMPUWRAPPERS == 1 )
StaticListItemt xDummy3[ 2 ];
uint8t ucDummy7[ configMAXTASKNAMELEN ];
#if ( portSTACKGROWTH > 0 )
#if ( portCRITICALNESTINGINTCB == 1 )
#if ( configUSETRACEFACILITY == 1 )
UBaseTypet uxDummy10[ 2 ];
#if ( configUSEMUTEXES == 1 )
UBaseTypet uxDummy12[ 2 ];
#if ( configUSEAPPLICATIONTASKTAG == 1 )
#if( configNUMTHREADLOCALSTORAGEPOINTERS > 0 )
void *pvDummy15[ configNUMTHREADLOCALSTORAGEPOINTERS ];
#if ( configGENERATERUNTIMESTATS == 1 )
#if ( configUSENEWLIBREENTRANT == 1 )
struct _reent xDummy17;
#if ( configUSETASKNOTIFICATIONS == 1 )
#if( ( configSUPPORTSTATICALLOCATION == 1 ) && ( configSUPPORTDYNAMICALLOCATION == 1 ) )
- StaticTaskt should have the last uxDummy20 conditional compile flag changed to the following to include the ports with portUSINGMPU_WRAPPERS enabled:
#if( ( ( configSUPPORTSTATICALLOCATION == 1 ) && ( configSUPPORTDYNAMICALLOCATION == 1 ) ) || ( portUSINGMPUWRAPPERS == 1 ) )
- StaticTaskt should add a missing ucDummy21 to account for ucDelayAborted if INCLUDExTaskAbortDelay is enabled:
#if( INCLUDExTaskAbortDelay == 1 )
- Additionally, there is a very misleading comment in xTaskCreateStatic() in tasks.c:
TaskHandlet xTaskCreateStatic( TaskFunctiont pxTaskCode,
const char * const pcName,
const uint32t ulStackDepth,
void * const pvParameters,
StackTypet * const puxStackBuffer,
StaticTaskt * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
configASSERT( puxStackBuffer != NULL );
configASSERT( pxTaskBuffer != NULL );
if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
/* The memory used for the task's TCB and stack are passed into this
function - use them. */
pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
The size most certainly is NOT checked by an assert. A compile-time assert is preferable:
Staticassert( sizeof(StaticTaskt) == sizeof(TCBt), "StaticTaskt must be same size as TCBt" );
Or at least a run-time assert would be OK:
configASSERT( sizeof(StaticTaskt) == sizeof(TCBt) );
Hope this helps someone and can make it into the next rev of FreeRTOS.
Thanks for taking the time to point this out. I have updated the StaticTask_t structure accordingly and will post a 'known issue'.
I will have to check the assert() - there definitely used to be one but the issue was getting it through all the compilers we use without warnings being generated a "condition is always false" warning.
if( configASSERT_DEFINED == 1 )
/* Sanity check that the size of the structure used to declare a
variable of type StaticTaskt equals the size of the real task
volatile sizet xSize = sizeof( StaticTask_t );
configASSERT( xSize == sizeof( tskTCB ) );
endif /* configASSERT_DEFINED */
Which is how it was done with the static queue structure.
No problem, keep up the great work!