/*\r
- FreeRTOS V9.0.0rc2 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
*/\r
#define tskSTACK_FILL_BYTE ( 0xa5U )\r
\r
+/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using\r
+dynamically allocated RAM, in which case when any task is deleted it is known\r
+that both the task's stack and TCB need to be freed. Sometimes the\r
+FreeRTOSConfig.h settings only allow a task to be created using statically\r
+allocated RAM, in which case when any task is deleted it is known that neither\r
+the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h\r
+settings allow a task to be created using either statically or dynamically\r
+allocated RAM, in which case a member of the TCB is used to record whether the\r
+stack and/or TCB were allocated statically or dynamically, so when a task is\r
+deleted the RAM that was allocated dynamically is freed again and no attempt is\r
+made to free the RAM that was allocated statically.\r
+tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a\r
+task to be created using either statically or dynamically allocated RAM. Note\r
+that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with\r
+a statically allocated stack and a dynamically allocated TCB. */\r
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )\r
+#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )\r
+#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )\r
+#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )\r
+\r
/*\r
* Macros used by vListTask to indicate which state a task is in.\r
*/\r
volatile uint8_t ucNotifyState;\r
#endif\r
\r
- #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
- uint8_t ucStaticallyAllocated; /* Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */\r
+ /* See the comments above the definition of\r
+ tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */\r
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */\r
#endif\r
\r
#if( INCLUDE_xTaskAbortDelay == 1 )\r
* Called after a Task_t structure has been allocated either statically or\r
* dynamically to fill in the structure's members.\r
*/\r
-static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,\r
+ const char * const pcName,\r
+ const uint32_t ulStackDepth,\r
+ void * const pvParameters,\r
+ UBaseType_t uxPriority,\r
+ TaskHandle_t * const pxCreatedTask,\r
+ TCB_t *pxNewTCB,\r
+ const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
\r
/*\r
* Called after a new task has been created and initialised to place the task\r
\r
#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
\r
- TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,\r
+ const char * const pcName,\r
+ const uint32_t ulStackDepth,\r
+ void * const pvParameters,\r
+ UBaseType_t uxPriority,\r
+ StackType_t * const puxStackBuffer,\r
+ StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
{\r
TCB_t *pxNewTCB;\r
TaskHandle_t xReturn;\r
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. */\r
pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;\r
\r
- #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
{\r
/* Tasks can be created statically or dynamically, so note this\r
task was created statically in case the task is later deleted. */\r
- pxNewTCB->ucStaticallyAllocated = pdTRUE;\r
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;\r
}\r
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
\r
- prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB );\r
+ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );\r
prvAddNewTaskToReadyList( pxNewTCB );\r
}\r
else\r
#endif /* SUPPORT_STATIC_ALLOCATION */\r
/*-----------------------------------------------------------*/\r
\r
+#if( portUSING_MPU_WRAPPERS == 1 )\r
+\r
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )\r
+ {\r
+ TCB_t *pxNewTCB;\r
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;\r
+\r
+ configASSERT( pxTaskDefinition->puxStackBuffer );\r
+\r
+ if( pxTaskDefinition->puxStackBuffer != NULL )\r
+ {\r
+ /* Allocate space for the TCB. Where the memory comes from depends\r
+ on the implementation of the port malloc function and whether or\r
+ not static allocation is being used. */\r
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );\r
+\r
+ if( pxNewTCB != NULL )\r
+ {\r
+ /* Store the stack location in the TCB. */\r
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;\r
+\r
+ /* Tasks can be created statically or dynamically, so note\r
+ this task had a statically allocated stack in case it is\r
+ later deleted. The TCB was allocated dynamically. */\r
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;\r
+\r
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,\r
+ pxTaskDefinition->pcName,\r
+ ( uint32_t ) pxTaskDefinition->usStackDepth,\r
+ pxTaskDefinition->pvParameters,\r
+ pxTaskDefinition->uxPriority,\r
+ pxCreatedTask, pxNewTCB,\r
+ pxTaskDefinition->xRegions );\r
+\r
+ prvAddNewTaskToReadyList( pxNewTCB );\r
+ xReturn = pdPASS;\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* portUSING_MPU_WRAPPERS */\r
+/*-----------------------------------------------------------*/\r
+\r
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
\r
- BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+ BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,\r
+ const char * const pcName,\r
+ const uint16_t usStackDepth,\r
+ void * const pvParameters,\r
+ UBaseType_t uxPriority,\r
+ TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
{\r
TCB_t *pxNewTCB;\r
BaseType_t xReturn;\r
\r
if( pxNewTCB != NULL )\r
{\r
- #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
{\r
/* Tasks can be created statically or dynamically, so note this\r
task was created dynamically in case it is later deleted. */\r
- pxNewTCB->ucStaticallyAllocated = pdFALSE;\r
+ pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;\r
}\r
#endif /* configSUPPORT_STATIC_ALLOCATION */\r
\r
- prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB );\r
+ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );\r
prvAddNewTaskToReadyList( pxNewTCB );\r
xReturn = pdPASS;\r
}\r
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
/*-----------------------------------------------------------*/\r
\r
-static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,\r
+ const char * const pcName,\r
+ const uint32_t ulStackDepth,\r
+ void * const pvParameters,\r
+ UBaseType_t uxPriority,\r
+ TaskHandle_t * const pxCreatedTask,\r
+ TCB_t *pxNewTCB,\r
+ const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
{\r
StackType_t *pxTopOfStack;\r
UBaseType_t x;\r
{\r
vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );\r
}\r
+ #else\r
+ {\r
+ /* Avoid compiler warning about unreferenced parameter. */\r
+ ( void ) xRegions;\r
+ }\r
#endif\r
\r
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )\r
/* The Idle task is created using user provided RAM - obtain the\r
address of the RAM then create the idle task. */\r
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );\r
- xIdleTaskHandle = xTaskCreateStatic( prvIdleTask, "IDLE", ulIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
+ xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,\r
+ "IDLE",\r
+ ulIdleTaskStackSize,\r
+ ( void * ) NULL,\r
+ ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),\r
+ pxIdleTaskStackBuffer,\r
+ pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
\r
if( xIdleTaskHandle != NULL )\r
{\r
#else\r
{\r
/* The Idle task is being created using dynamically allocated RAM. */\r
- xReturn = xTaskCreate( prvIdleTask, "IDLE", configMINIMAL_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
+ xReturn = xTaskCreate( prvIdleTask,\r
+ "IDLE", configMINIMAL_STACK_SIZE,\r
+ ( void * ) NULL,\r
+ ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),\r
+ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
}\r
#endif /* configSUPPORT_STATIC_ALLOCATION */\r
\r
\r
/* If configGENERATE_RUN_TIME_STATS is defined then the following\r
macro must be defined to configure the timer/counter used to generate\r
- the run time counter time base. */\r
+ the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS\r
+ is set to 0 and the following line fails to build then ensure you do not\r
+ have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your\r
+ FreeRTOSConfig.h file. */\r
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();\r
\r
/* Setting up the timer tick is hardware specific and thus in the\r
/* This line will only be reached if the kernel could not be started,\r
because there was not enough FreeRTOS heap to create the idle task\r
or the timer task. */\r
- configASSERT( xReturn );\r
+ configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );\r
}\r
\r
/* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,\r
mtCOVERAGE_TEST_MARKER();\r
}\r
}\r
- xTaskResumeAll();\r
+ ( void ) xTaskResumeAll();\r
\r
return xReturn;\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
-BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )\r
+void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )\r
{\r
TCB_t *pxUnblockedTCB;\r
-BaseType_t xReturn;\r
\r
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by\r
the event flags implementation. */\r
\r
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )\r
{\r
- /* Return true if the task removed from the event list has\r
- a higher priority than the calling task. This allows\r
- the calling task to know if it should force a context\r
- switch now. */\r
- xReturn = pdTRUE;\r
-\r
- /* Mark that a yield is pending in case the user is not using the\r
- "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */\r
+ /* The unblocked task has a priority above that of the calling task, so\r
+ a context switch is required. This function is called with the\r
+ scheduler suspended so xYieldPending is set so the context switch\r
+ occurs immediately that the scheduler is resumed (unsuspended). */\r
xYieldPending = pdTRUE;\r
}\r
- else\r
- {\r
- xReturn = pdFALSE;\r
- }\r
-\r
- return xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
pxTaskStatus->eCurrentState = eBlocked;\r
}\r
}\r
- xTaskResumeAll();\r
+ ( void ) xTaskResumeAll();\r
}\r
}\r
#endif /* INCLUDE_vTaskSuspend */\r
\r
static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )\r
{\r
- volatile TCB_t *pxNextTCB, *pxFirstTCB;\r
+ configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;\r
UBaseType_t uxTask = 0;\r
\r
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
}\r
#endif /* configUSE_NEWLIB_REENTRANT */\r
\r
- #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )\r
{\r
- /* The task can only have been allocated dynamically - free it\r
- again. */\r
+ /* The task can only have been allocated dynamically - free both\r
+ the stack and TCB. */\r
vPortFree( pxTCB->pxStack );\r
vPortFree( pxTCB );\r
}\r
- #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
+ #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )\r
{\r
/* The task could have been allocated statically or dynamically, so\r
- check before attempting to free the memory. */\r
- if( pxTCB->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
+ check what was statically allocated before trying to free the\r
+ memory. */\r
+ if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )\r
{\r
+ /* Both the stack and TCB were allocated dynamically, so both\r
+ must be freed. */\r
vPortFree( pxTCB->pxStack );\r
vPortFree( pxTCB );\r
}\r
+ else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )\r
+ {\r
+ /* Only the stack was statically allocated, so the TCB is the\r
+ only memory that must be freed. */\r
+ vPortFree( pxTCB );\r
+ }\r
else\r
{\r
+ /* Neither the stack nor the TCB were allocated dynamically, so\r
+ nothing needs to be freed. */\r
+ configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )\r
mtCOVERAGE_TEST_MARKER();\r
}\r
}\r