summaryrefslogtreecommitdiff
path: root/freertos
diff options
context:
space:
mode:
authorDominik Sliwa <dominik.sliwa@toradex.com>2017-05-16 14:31:59 +0200
committerDominik Sliwa <dominik.sliwa@toradex.com>2017-05-16 14:31:59 +0200
commitc9d5d6b248a12f7c6b66d8a64b93fb0c8c6cae4d (patch)
treedc9f3329f9fd2fc67aa8202b2d3cb4e537deb17d /freertos
parentd0e5a94a55334b0a27652959fba5066f56128135 (diff)
ksd:ksdk update to 2.2
This include FreeRTOS update to version 9.0.0 Signed-off-by: Dominik Sliwa <dominik.sliwa@toradex.com>
Diffstat (limited to 'freertos')
-rw-r--r--freertos/Source/croutine.c2
-rw-r--r--freertos/Source/event_groups.c115
-rw-r--r--freertos/Source/include/FreeRTOS.h373
-rw-r--r--freertos/Source/include/StackMacros.h8
-rw-r--r--freertos/Source/include/croutine.h64
-rw-r--r--freertos/Source/include/deprecated_definitions.h2
-rw-r--r--freertos/Source/include/event_groups.h157
-rw-r--r--freertos/Source/include/freertos_tasks_c_additions.h125
-rw-r--r--freertos/Source/include/list.h34
-rw-r--r--freertos/Source/include/mpu_prototypes.h177
-rw-r--r--freertos/Source/include/mpu_wrappers.h170
-rw-r--r--freertos/Source/include/portable.h6
-rw-r--r--freertos/Source/include/projdefs.h11
-rw-r--r--freertos/Source/include/queue.h301
-rw-r--r--freertos/Source/include/semphr.h505
-rw-r--r--freertos/Source/include/stdint.readme27
-rw-r--r--freertos/Source/include/task.h424
-rw-r--r--freertos/Source/include/timers.h322
-rw-r--r--freertos/Source/list.c2
-rw-r--r--freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_generic.h122
-rw-r--r--freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_lptmr.c260
-rw-r--r--freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_systick.c273
-rw-r--r--freertos/Source/portable/GCC/ARM_CM3/port.c481
-rw-r--r--freertos/Source/portable/GCC/ARM_CM3/portmacro.h105
-rw-r--r--freertos/Source/portable/MemMang/heap_1.c20
-rw-r--r--freertos/Source/portable/MemMang/heap_2.c17
-rw-r--r--freertos/Source/portable/MemMang/heap_3.c6
-rw-r--r--freertos/Source/portable/MemMang/heap_4.c8
-rw-r--r--freertos/Source/portable/MemMang/heap_5.c6
-rw-r--r--freertos/Source/portable/readme.txt19
-rw-r--r--freertos/Source/queue.c750
-rw-r--r--freertos/Source/readme.txt17
-rw-r--r--freertos/Source/tasks.c2486
-rw-r--r--freertos/Source/timers.c285
34 files changed, 5052 insertions, 2628 deletions
diff --git a/freertos/Source/croutine.c b/freertos/Source/croutine.c
index ccc9bb2..993e09b 100644
--- a/freertos/Source/croutine.c
+++ b/freertos/Source/croutine.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
diff --git a/freertos/Source/event_groups.c b/freertos/Source/event_groups.c
index dad975f..b8df5fd 100644
--- a/freertos/Source/event_groups.c
+++ b/freertos/Source/event_groups.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -87,14 +87,6 @@ header files above, but not in this file, in order to generate the correct
privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
-#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( configUSE_TIMERS == 0 )
- #error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available.
-#endif
-
-#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 )
- #error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available.
-#endif
-
/* The following bit fields convey control information in a task's event list
item value. It is important they don't clash with the
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
@@ -119,6 +111,9 @@ typedef struct xEventGroupDefinition
UBaseType_t uxEventGroupNumber;
#endif
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
+ #endif
} EventGroup_t;
/*-----------------------------------------------------------*/
@@ -131,28 +126,83 @@ typedef struct xEventGroupDefinition
* wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits.
*/
-static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits );
+static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
-EventGroupHandle_t xEventGroupCreate( void )
-{
-EventGroup_t *pxEventBits;
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
- pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
- if( pxEventBits != NULL )
+ EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
{
- pxEventBits->uxEventBits = 0;
- vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
- traceEVENT_GROUP_CREATE( pxEventBits );
+ EventGroup_t *pxEventBits;
+
+ /* A StaticEventGroup_t object must be provided. */
+ configASSERT( pxEventGroupBuffer );
+
+ /* The user has provided a statically allocated event group - use it. */
+ pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
+
+ if( pxEventBits != NULL )
+ {
+ pxEventBits->uxEventBits = 0;
+ vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
+
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Both static and dynamic allocation can be used, so note that
+ this event group was created statically in case the event group
+ is later deleted. */
+ pxEventBits->ucStaticallyAllocated = pdTRUE;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ traceEVENT_GROUP_CREATE( pxEventBits );
+ }
+ else
+ {
+ traceEVENT_GROUP_CREATE_FAILED();
+ }
+
+ return ( EventGroupHandle_t ) pxEventBits;
}
- else
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ EventGroupHandle_t xEventGroupCreate( void )
{
- traceEVENT_GROUP_CREATE_FAILED();
+ EventGroup_t *pxEventBits;
+
+ /* Allocate the event group. */
+ pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
+
+ if( pxEventBits != NULL )
+ {
+ pxEventBits->uxEventBits = 0;
+ vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
+
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* Both static and dynamic allocation can be used, so note this
+ event group was allocated statically in case the event group is
+ later deleted. */
+ pxEventBits->ucStaticallyAllocated = pdFALSE;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ traceEVENT_GROUP_CREATE( pxEventBits );
+ }
+ else
+ {
+ traceEVENT_GROUP_CREATE_FAILED();
+ }
+
+ return ( EventGroupHandle_t ) pxEventBits;
}
- return ( EventGroupHandle_t ) pxEventBits;
-}
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
@@ -588,7 +638,26 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
- vPortFree( pxEventBits );
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+ {
+ /* The event group can only have been allocated dynamically - free
+ it again. */
+ vPortFree( pxEventBits );
+ }
+ #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ {
+ /* The event group could have been allocated statically or
+ dynamically, so check before attempting to free the memory. */
+ if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+ {
+ vPortFree( pxEventBits );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
( void ) xTaskResumeAll();
}
diff --git a/freertos/Source/include/FreeRTOS.h b/freertos/Source/include/FreeRTOS.h
index 82e6ce7..e2fe75e 100644
--- a/freertos/Source/include/FreeRTOS.h
+++ b/freertos/Source/include/FreeRTOS.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -103,6 +103,15 @@ extern "C" {
/* Definitions specific to the port being used. */
#include "portable.h"
+/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */
+#ifndef configUSE_NEWLIB_REENTRANT
+ #define configUSE_NEWLIB_REENTRANT 0
+#endif
+
+/* Required if struct _reent is used. */
+#if ( configUSE_NEWLIB_REENTRANT == 1 )
+ #include <reent.h>
+#endif
/*
* Check all the required application specific macros have been defined.
* These macros are application specific and (as downloaded) are defined
@@ -129,82 +138,102 @@ extern "C" {
#error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
+#ifndef configUSE_16_BIT_TICKS
+ #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configMAX_PRIORITIES
+ #error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
+#endif
+
+#ifndef configUSE_CO_ROUTINES
+ #define configUSE_CO_ROUTINES 0
+#endif
+
#ifndef INCLUDE_vTaskPrioritySet
- #error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+ #define INCLUDE_vTaskPrioritySet 0
#endif
#ifndef INCLUDE_uxTaskPriorityGet
- #error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+ #define INCLUDE_uxTaskPriorityGet 0
#endif
#ifndef INCLUDE_vTaskDelete
- #error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+ #define INCLUDE_vTaskDelete 0
#endif
#ifndef INCLUDE_vTaskSuspend
- #error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+ #define INCLUDE_vTaskSuspend 0
#endif
#ifndef INCLUDE_vTaskDelayUntil
- #error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+ #define INCLUDE_vTaskDelayUntil 0
#endif
#ifndef INCLUDE_vTaskDelay
- #error Missing definition: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+ #define INCLUDE_vTaskDelay 0
#endif
-#ifndef configUSE_16_BIT_TICKS
- #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#ifndef INCLUDE_xTaskGetIdleTaskHandle
+ #define INCLUDE_xTaskGetIdleTaskHandle 0
#endif
-#ifndef configMAX_PRIORITIES
- #error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
+#ifndef INCLUDE_xTaskAbortDelay
+ #define INCLUDE_xTaskAbortDelay 0
#endif
-#ifndef configUSE_CO_ROUTINES
- #define configUSE_CO_ROUTINES 0
+#ifndef INCLUDE_xQueueGetMutexHolder
+ #define INCLUDE_xQueueGetMutexHolder 0
#endif
-#if configUSE_CO_ROUTINES != 0
- #ifndef configMAX_CO_ROUTINE_PRIORITIES
- #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
- #endif
+#ifndef INCLUDE_xSemaphoreGetMutexHolder
+ #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
#endif
-#ifndef INCLUDE_xTaskGetIdleTaskHandle
- #define INCLUDE_xTaskGetIdleTaskHandle 0
+#ifndef INCLUDE_xTaskGetHandle
+ #define INCLUDE_xTaskGetHandle 0
#endif
-#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle
- #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark
+ #define INCLUDE_uxTaskGetStackHighWaterMark 0
#endif
-#ifndef INCLUDE_xQueueGetMutexHolder
- #define INCLUDE_xQueueGetMutexHolder 0
+#ifndef INCLUDE_eTaskGetState
+ #define INCLUDE_eTaskGetState 0
#endif
-#ifndef INCLUDE_xSemaphoreGetMutexHolder
- #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
+#ifndef INCLUDE_xTaskResumeFromISR
+ #define INCLUDE_xTaskResumeFromISR 1
#endif
-#ifndef INCLUDE_pcTaskGetTaskName
- #define INCLUDE_pcTaskGetTaskName 0
+#ifndef INCLUDE_xTimerPendFunctionCall
+ #define INCLUDE_xTimerPendFunctionCall 0
#endif
-#ifndef configUSE_APPLICATION_TASK_TAG
- #define configUSE_APPLICATION_TASK_TAG 0
+#ifndef INCLUDE_xTaskGetSchedulerState
+ #define INCLUDE_xTaskGetSchedulerState 0
#endif
-#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
- #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
+#ifndef INCLUDE_xTaskGetCurrentTaskHandle
+ #define INCLUDE_xTaskGetCurrentTaskHandle 0
#endif
-#ifndef INCLUDE_uxTaskGetStackHighWaterMark
- #define INCLUDE_uxTaskGetStackHighWaterMark 0
+#if configUSE_CO_ROUTINES != 0
+ #ifndef configMAX_CO_ROUTINE_PRIORITIES
+ #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
+ #endif
#endif
-#ifndef INCLUDE_eTaskGetState
- #define INCLUDE_eTaskGetState 0
+#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK
+ #define configUSE_DAEMON_TASK_STARTUP_HOOK 0
+#endif
+
+#ifndef configUSE_APPLICATION_TASK_TAG
+ #define configUSE_APPLICATION_TASK_TAG 0
+#endif
+
+#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
+ #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
#endif
#ifndef configUSE_RECURSIVE_MUTEXES
@@ -243,18 +272,6 @@ extern "C" {
#error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
#endif
-#ifndef INCLUDE_xTaskResumeFromISR
- #define INCLUDE_xTaskResumeFromISR 1
-#endif
-
-#ifndef INCLUDE_xEventGroupSetBitFromISR
- #define INCLUDE_xEventGroupSetBitFromISR 0
-#endif
-
-#ifndef INCLUDE_xTimerPendFunctionCall
- #define INCLUDE_xTimerPendFunctionCall 0
-#endif
-
#ifndef configASSERT
#define configASSERT( x )
#define configASSERT_DEFINED 0
@@ -279,15 +296,6 @@ extern "C" {
#endif /* configUSE_TIMERS */
-#ifndef INCLUDE_xTaskGetSchedulerState
- #define INCLUDE_xTaskGetSchedulerState 0
-#endif
-
-#ifndef INCLUDE_xTaskGetCurrentTaskHandle
- #define INCLUDE_xTaskGetCurrentTaskHandle 0
-#endif
-
-
#ifndef portSET_INTERRUPT_MASK_FROM_ISR
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#endif
@@ -315,6 +323,7 @@ extern "C" {
#if ( configQUEUE_REGISTRY_SIZE < 1 )
#define vQueueAddToRegistry( xQueue, pcName )
#define vQueueUnregisterQueue( xQueue )
+ #define pcQueueGetName( xQueue )
#endif
#ifndef portPOINTER_SIZE_TYPE
@@ -366,7 +375,7 @@ extern "C" {
/* Called when a task attempts to take a mutex that is already held by a
lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task
that holds the mutex. uxInheritedPriority is the priority the mutex holder
- inherits (the priority of the task that is attempting to obtain the
+ will inherit (the priority of the task that is attempting to obtain the
muted. */
#define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority )
#endif
@@ -399,12 +408,19 @@ extern "C" {
#define configCHECK_FOR_STACK_OVERFLOW 0
#endif
+#ifndef configRECORD_STACK_HIGH_ADDRESS
+ #define configRECORD_STACK_HIGH_ADDRESS 0
+#endif
/* The following event macros are embedded in the kernel API calls. */
#ifndef traceMOVED_TASK_TO_READY_STATE
#define traceMOVED_TASK_TO_READY_STATE( pxTCB )
#endif
+#ifndef tracePOST_MOVED_TASK_TO_READY_STATE
+ #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
+#endif
+
#ifndef traceQUEUE_CREATE
#define traceQUEUE_CREATE( pxNewQueue )
#endif
@@ -506,7 +522,7 @@ extern "C" {
#endif
#ifndef traceTASK_DELAY_UNTIL
- #define traceTASK_DELAY_UNTIL()
+ #define traceTASK_DELAY_UNTIL( x )
#endif
#ifndef traceTASK_DELAY
@@ -679,14 +695,6 @@ extern "C" {
#define portYIELD_WITHIN_API portYIELD
#endif
-#ifndef pvPortMallocAligned
- #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) )
-#endif
-
-#ifndef vPortFreeAligned
- #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )
-#endif
-
#ifndef portSUPPRESS_TICKS_AND_SLEEP
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
#endif
@@ -727,10 +735,6 @@ extern "C" {
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
#endif
-#ifndef configUSE_NEWLIB_REENTRANT
- #define configUSE_NEWLIB_REENTRANT 0
-#endif
-
#ifndef configUSE_STATS_FORMATTING_FUNCTIONS
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#endif
@@ -771,6 +775,31 @@ extern "C" {
#define portTICK_TYPE_IS_ATOMIC 0
#endif
+#ifndef configSUPPORT_STATIC_ALLOCATION
+ /* Defaults to 0 for backward compatibility. */
+ #define configSUPPORT_STATIC_ALLOCATION 0
+#endif
+
+#ifndef configSUPPORT_DYNAMIC_ALLOCATION
+ /* Defaults to 1 for backward compatibility. */
+ #define configSUPPORT_DYNAMIC_ALLOCATION 1
+#endif
+
+/* Sanity check the configuration. */
+#if( configUSE_TICKLESS_IDLE != 0 )
+ #if( INCLUDE_vTaskSuspend != 1 )
+ #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
+ #endif /* INCLUDE_vTaskSuspend */
+#endif /* configUSE_TICKLESS_IDLE */
+
+#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
+ #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1.
+#endif
+
+#if( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) )
+ #error configUSE_MUTEXES must be set to 1 to use recursive mutexes
+#endif
+
#if( portTICK_TYPE_IS_ATOMIC == 0 )
/* Either variables of tick type cannot be read atomically, or
portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
@@ -810,6 +839,10 @@ V8 if desired. */
#define xCoRoutineHandle CoRoutineHandle_t
#define pdTASK_HOOK_CODE TaskHookFunction_t
#define portTICK_RATE_MS portTICK_PERIOD_MS
+ #define pcTaskGetTaskName pcTaskGetName
+ #define pcTimerGetTimerName pcTimerGetName
+ #define pcQueueGetQueueName pcQueueGetName
+ #define vTaskGetTaskInfo vTaskGetInfo
/* Backward compatibility within the scheduler code only - these definitions
are not really required but are included for completeness. */
@@ -819,14 +852,212 @@ V8 if desired. */
#define xList List_t
#endif /* configENABLE_BACKWARD_COMPATIBILITY */
+#if( configUSE_ALTERNATIVE_API != 0 )
+ #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0
+#endif
+
/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even
if floating point hardware is otherwise supported by the FreeRTOS port in use.
-This constant is not supported by all FreeRTOS ports that include floating
+This constant is not supported by all FreeRTOS ports that include floating
point support. */
#ifndef configUSE_TASK_FPU_SUPPORT
#define configUSE_TASK_FPU_SUPPORT 1
#endif
+/*
+ * In line with software engineering best practice, FreeRTOS implements a strict
+ * data hiding policy, so the real structures used by FreeRTOS to maintain the
+ * state of tasks, queues, semaphores, etc. are not accessible to the application
+ * code. However, if the application writer wants to statically allocate such
+ * an object then the size of the object needs to be know. Dummy structures
+ * that are guaranteed to have the same size and alignment requirements of the
+ * real objects are used for this purpose. The dummy list and list item
+ * structures below are used for inclusion in such a dummy structure.
+ */
+struct xSTATIC_LIST_ITEM
+{
+ TickType_t xDummy1;
+ void *pvDummy2[ 4 ];
+};
+typedef struct xSTATIC_LIST_ITEM StaticListItem_t;
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+struct xSTATIC_MINI_LIST_ITEM
+{
+ TickType_t xDummy1;
+ void *pvDummy2[ 2 ];
+};
+typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t;
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+typedef struct xSTATIC_LIST
+{
+ UBaseType_t uxDummy1;
+ void *pvDummy2;
+ StaticMiniListItem_t xDummy3;
+} StaticList_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the Task structure used internally by
+ * FreeRTOS is not accessible to application code. However, if the application
+ * writer wants to statically allocate the memory required to create a task then
+ * the size of the task object needs to be know. The StaticTask_t structure
+ * below is provided for this purpose. Its sizes and alignment requirements are
+ * guaranteed to match those of the genuine structure, no matter which
+ * architecture is being used, and no matter how the values in FreeRTOSConfig.h
+ * are set. Its contents are somewhat obfuscated in the hope users will
+ * recognise that it would be unwise to make direct use of the structure members.
+ */
+typedef struct xSTATIC_TCB
+{
+ void *pxDummy1;
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ xMPU_SETTINGS xDummy2;
+ #endif
+ StaticListItem_t xDummy3[ 2 ];
+ UBaseType_t uxDummy5;
+ void *pxDummy6;
+ uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ];
+ #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+ void *pxDummy8;
+ #endif
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ UBaseType_t uxDummy9;
+ #endif
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy10[ 2 ];
+ #endif
+ #if ( configUSE_MUTEXES == 1 )
+ UBaseType_t uxDummy12[ 2 ];
+ #endif
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ void *pxDummy14;
+ #endif
+ #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+ void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+ #endif
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ uint32_t ulDummy16;
+ #endif
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ struct _reent xDummy17;
+ #endif
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ uint32_t ulDummy18;
+ uint8_t ucDummy19;
+ #endif
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t uxDummy20;
+ #endif
+
+} StaticTask_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the Queue structure used internally by
+ * FreeRTOS is not accessible to application code. However, if the application
+ * writer wants to statically allocate the memory required to create a queue
+ * then the size of the queue object needs to be know. The StaticQueue_t
+ * structure below is provided for this purpose. Its sizes and alignment
+ * requirements are guaranteed to match those of the genuine structure, no
+ * matter which architecture is being used, and no matter how the values in
+ * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope
+ * users will recognise that it would be unwise to make direct use of the
+ * structure members.
+ */
+typedef struct xSTATIC_QUEUE
+{
+ void *pvDummy1[ 3 ];
+
+ union
+ {
+ void *pvDummy2;
+ UBaseType_t uxDummy2;
+ } u;
+
+ StaticList_t xDummy3[ 2 ];
+ UBaseType_t uxDummy4[ 3 ];
+ uint8_t ucDummy5[ 2 ];
+
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucDummy6;
+ #endif
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ void *pvDummy7;
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy8;
+ uint8_t ucDummy9;
+ #endif
+
+} StaticQueue_t;
+typedef StaticQueue_t StaticSemaphore_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the event group structure used
+ * internally by FreeRTOS is not accessible to application code. However, if
+ * the application writer wants to statically allocate the memory required to
+ * create an event group then the size of the event group object needs to be
+ * know. The StaticEventGroup_t structure below is provided for this purpose.
+ * Its sizes and alignment requirements are guaranteed to match those of the
+ * genuine structure, no matter which architecture is being used, and no matter
+ * how the values in FreeRTOSConfig.h are set. Its contents are somewhat
+ * obfuscated in the hope users will recognise that it would be unwise to make
+ * direct use of the structure members.
+ */
+typedef struct xSTATIC_EVENT_GROUP
+{
+ TickType_t xDummy1;
+ StaticList_t xDummy2;
+
+ #if( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy3;
+ #endif
+
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucDummy4;
+ #endif
+
+} StaticEventGroup_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the software timer structure used
+ * internally by FreeRTOS is not accessible to application code. However, if
+ * the application writer wants to statically allocate the memory required to
+ * create a software timer then the size of the queue object needs to be know.
+ * The StaticTimer_t structure below is provided for this purpose. Its sizes
+ * and alignment requirements are guaranteed to match those of the genuine
+ * structure, no matter which architecture is being used, and no matter how the
+ * values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in
+ * the hope users will recognise that it would be unwise to make direct use of
+ * the structure members.
+ */
+typedef struct xSTATIC_TIMER
+{
+ void *pvDummy1;
+ StaticListItem_t xDummy2;
+ TickType_t xDummy3;
+ UBaseType_t uxDummy4;
+ void *pvDummy5[ 2 ];
+ #if( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy6;
+ #endif
+
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucDummy7;
+ #endif
+
+} StaticTimer_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/freertos/Source/include/StackMacros.h b/freertos/Source/include/StackMacros.h
index e7c63e2..13c6b82 100644
--- a/freertos/Source/include/StackMacros.h
+++ b/freertos/Source/include/StackMacros.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -75,13 +75,13 @@
* out is currently overflowed, or looks like it might have overflowed in the
* past.
*
- * Setting configCHECK_FOR_STACK_OVERFLOW to 1 causes the macro to check
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
* the current stack state only - comparing the current top of stack value to
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
- * also causes the last few stack bytes to be checked to ensure the value
+ * will also cause the last few stack bytes to be checked to ensure the value
* to which the bytes were set when the task was created have not been
* overwritten. Note this second test does not guarantee that an overflowed
- * stack is always be recognized.
+ * stack will always be recognised.
*/
/*-----------------------------------------------------------*/
diff --git a/freertos/Source/include/croutine.h b/freertos/Source/include/croutine.h
index 8876865..4f003a0 100644
--- a/freertos/Source/include/croutine.h
+++ b/freertos/Source/include/croutine.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -107,7 +107,7 @@ typedef struct corCoRoutineControlBlock
UBaseType_t uxIndex
);</pre>
*
- * Creates a new co-routine and adds it to the list of co-routines that are
+ * Create a new co-routine and add it to the list of co-routines that are
* ready to run.
*
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
@@ -115,7 +115,7 @@ typedef struct corCoRoutineControlBlock
* documentation for more information.
*
* @param uxPriority The priority with respect to other co-routines at which
- * the co-routine runs.
+ * the co-routine will run.
*
* @param uxIndex Used to distinguish between different co-routines that
* execute the same function. See the example below and the co-routine section
@@ -130,7 +130,7 @@ typedef struct corCoRoutineControlBlock
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
- // This may not be necessary for constant variables.
+ // This may not be necessary for const variables.
static const char cLedToFlash[ 2 ] = { 5, 6 };
static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
@@ -139,7 +139,7 @@ typedef struct corCoRoutineControlBlock
for( ;; )
{
- // This co-routine delays for a fixed period, then toggles
+ // This co-routine just delays for a fixed period, then toggles
// an LED. Two co-routines are created using this function, so
// the uxIndex parameter is used to tell the co-routine which
// LED to flash and how int32_t to delay. This assumes xQueue has
@@ -158,7 +158,7 @@ typedef struct corCoRoutineControlBlock
uint8_t ucParameterToPass;
TaskHandle_t xHandle;
- // Creates two co-routines at priority 0. The first is given index 0
+ // Create two co-routines at priority 0. The first is given index 0
// so (from the code above) toggles LED 5 every 200 ticks. The second
// is given index 1 so toggles LED 6 every 400 ticks.
for( uxIndex = 0; uxIndex < 2; uxIndex++ )
@@ -178,21 +178,21 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPri
*<pre>
void vCoRoutineSchedule( void );</pre>
*
- * Runs a co-routine.
+ * Run a co-routine.
*
* vCoRoutineSchedule() executes the highest priority co-routine that is able
- * to run. The co-routine executes until it either blocks, yields or is
+ * to run. The co-routine will execute until it either blocks, yields or is
* preempted by a task. Co-routines execute cooperatively so one
* co-routine cannot be preempted by another, but can be preempted by a task.
*
- * If an application comprises of both tasks and co-routines, the
+ * If an application comprises of both tasks and co-routines then
* vCoRoutineSchedule should be called from the idle task (in an idle task
* hook).
*
* Example usage:
<pre>
- // This idle task hook schedules a co-routine each time it is called.
- // The rest of the idle task executes between co-routine calls.
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
void vApplicationIdleHook( void )
{
vCoRoutineSchedule();
@@ -288,9 +288,9 @@ void vCoRoutineSchedule( void );
*<pre>
crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre>
*
- * Delays a co-routine for a fixed period of time.
+ * Delay a co-routine for a fixed period of time.
*
- * crDELAY can only be called from the co-routine function itself, not
+ * crDELAY can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
@@ -308,7 +308,7 @@ void vCoRoutineSchedule( void );
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
- // This may not be necessary for constant variables.
+ // This may not be necessary for const variables.
// We are to delay for 200ms.
static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
@@ -363,7 +363,7 @@ void vCoRoutineSchedule( void );
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
- * @param pxQueue The handle of the queue on which the data is posted.
+ * @param pxQueue The handle of the queue on which the data will be posted.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
@@ -379,8 +379,8 @@ void vCoRoutineSchedule( void );
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
* below).
*
- * @param pxResult The variable pointed to by pxResult is set to pdPASS if
- * data was successfully posted onto the queue, otherwise it is set to an
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully posted onto the queue, otherwise it will be set to an
* error defined within ProjDefs.h.
*
* Example usage:
@@ -462,7 +462,7 @@ void vCoRoutineSchedule( void );
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
- * @param pxQueue The handle of the queue from which the data is received.
+ * @param pxQueue The handle of the queue from which the data will be received.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
@@ -477,8 +477,8 @@ void vCoRoutineSchedule( void );
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
* crQUEUE_SEND example).
*
- * @param pxResult The variable pointed to by pxResult is set to pdPASS if
- * data was successfully retrieved from the queue, otherwise it is set to
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully retrieved from the queue, otherwise it will be set to
* an error code as defined within ProjDefs.h.
*
* Example usage:
@@ -554,8 +554,8 @@ void vCoRoutineSchedule( void );
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
@@ -608,9 +608,9 @@ void vCoRoutineSchedule( void );
// Obtain the character from the UART.
cRxedChar = UART_RX_REG;
- // Post the character onto a queue. xCRWokenByPost is pdFALSE
+ // Post the character onto a queue. xCRWokenByPost will be pdFALSE
// the first time around the loop. If the post causes a co-routine
- // to be woken (unblocked) then xCRWokenByPost is set to pdTRUE.
+ // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
// In this manner we can ensure that if more than one co-routine is
// blocked on the queue only one is woken by this ISR no matter how
// many characters are posted to the queue.
@@ -651,15 +651,15 @@ void vCoRoutineSchedule( void );
*
* @param xQueue The handle to the queue on which the item is to be posted.
*
- * @param pvBuffer A pointer to a buffer into which the received item is
- * placed. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from the queue into
+ * @param pvBuffer A pointer to a buffer into which the received item will be
+ * placed. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from the queue into
* pvBuffer.
*
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
- * co-routine to unblock *pxCoRoutineWoken gets set to pdTRUE, otherwise
- * *pxCoRoutineWoken remains unchanged.
+ * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
+ * *pxCoRoutineWoken will remain unchanged.
*
* @return pdTRUE an item was successfully received from the queue, otherwise
* pdFALSE.
@@ -693,12 +693,12 @@ void vCoRoutineSchedule( void );
}
// Enable the UART Tx interrupt to cause an interrupt in this
- // hypothetical UART. The interrupt obtains the character
+ // hypothetical UART. The interrupt will obtain the character
// from the queue and send it.
ENABLE_RX_INTERRUPT();
// Increment to the next character then block for a fixed period.
- // cCharToTx maintains its value across the delay as it is
+ // cCharToTx will maintain its value across the delay as it is
// declared static.
cCharToTx++;
if( cCharToTx > 'x' )
@@ -721,7 +721,7 @@ void vCoRoutineSchedule( void );
while( UART_TX_REG_EMPTY() )
{
// Are there any characters in the queue waiting to be sent?
- // xCRWokenByPos is automatically set to pdTRUE if a co-routine
+ // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
// is woken by the post - ensuring that only a single co-routine is
// woken no matter how many times we go around this loop.
if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
diff --git a/freertos/Source/include/deprecated_definitions.h b/freertos/Source/include/deprecated_definitions.h
index c339193..4ea816c 100644
--- a/freertos/Source/include/deprecated_definitions.h
+++ b/freertos/Source/include/deprecated_definitions.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
diff --git a/freertos/Source/include/event_groups.h b/freertos/Source/include/event_groups.h
index 8b8ca88..7331c91 100644
--- a/freertos/Source/include/event_groups.h
+++ b/freertos/Source/include/event_groups.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -74,6 +74,7 @@
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
#endif
+/* FreeRTOS includes. */
#include "timers.h"
#ifdef __cplusplus
@@ -101,7 +102,7 @@ extern "C" {
* variable for the same purpose. This is particularly important with respect
* to when a bit within an event group is to be cleared, and when bits have to
* be set and then tested atomically - as is the case where event groups are
- * used to create a synchronization point between multiple tasks (a
+ * used to create a synchronisation point between multiple tasks (a
* 'rendezvous').
*
* \defgroup EventGroup
@@ -121,10 +122,10 @@ extern "C" {
*/
typedef void * EventGroupHandle_t;
-/*
+/*
* The type that holds event bits always matches TickType_t - therefore the
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
- * 32 bits if set to 0.
+ * 32 bits if set to 0.
*
* \defgroup EventBits_t EventBits_t
* \ingroup EventGroup
@@ -137,7 +138,17 @@ typedef TickType_t EventBits_t;
EventGroupHandle_t xEventGroupCreate( void );
</pre>
*
- * Create a new event group. This function cannot be called from an interrupt.
+ * Create a new event group.
+ *
+ * Internally, within the FreeRTOS implementation, event groups use a [small]
+ * block of memory, in which the event group's structure is stored. If an event
+ * groups is created using xEventGropuCreate() then the required memory is
+ * automatically dynamically allocated inside the xEventGroupCreate() function.
+ * (see http://www.freertos.org/a00111.html). If an event group is created
+ * using xEventGropuCreateStatic() then the application writer must instead
+ * provide the memory that will get used by the event group.
+ * xEventGroupCreateStatic() therefore allows an event group to be created
+ * without using any dynamic memory allocation.
*
* Although event groups are not related to ticks, for internal implementation
* reasons the number of bits available for use in an event group is dependent
@@ -173,7 +184,62 @@ typedef TickType_t EventBits_t;
* \defgroup xEventGroupCreate xEventGroupCreate
* \ingroup EventGroup
*/
-EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * event_groups.h
+ *<pre>
+ EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
+ </pre>
+ *
+ * Create a new event group.
+ *
+ * Internally, within the FreeRTOS implementation, event groups use a [small]
+ * block of memory, in which the event group's structure is stored. If an event
+ * groups is created using xEventGropuCreate() then the required memory is
+ * automatically dynamically allocated inside the xEventGroupCreate() function.
+ * (see http://www.freertos.org/a00111.html). If an event group is created
+ * using xEventGropuCreateStatic() then the application writer must instead
+ * provide the memory that will get used by the event group.
+ * xEventGroupCreateStatic() therefore allows an event group to be created
+ * without using any dynamic memory allocation.
+ *
+ * Although event groups are not related to ticks, for internal implementation
+ * reasons the number of bits available for use in an event group is dependent
+ * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
+ * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
+ * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
+ * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
+ * event bits within an event group.
+ *
+ * @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
+ * StaticEventGroup_t, which will be then be used to hold the event group's data
+ * structures, removing the need for the memory to be allocated dynamically.
+ *
+ * @return If the event group was created then a handle to the event group is
+ * returned. If pxEventGroupBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ // StaticEventGroup_t is a publicly accessible structure that has the same
+ // size and alignment requirements as the real event group structure. It is
+ // provided as a mechanism for applications to know the size of the event
+ // group (which is dependent on the architecture and configuration file
+ // settings) without breaking the strict data hiding policy by exposing the
+ // real event group internals. This StaticEventGroup_t variable is passed
+ // into the xSemaphoreCreateEventGroupStatic() function and is used to store
+ // the event group's data structures
+ StaticEventGroup_t xEventGroupBuffer;
+
+ // Create the event group without dynamically allocating any memory.
+ xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
+ </pre>
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
+#endif
/**
* event_groups.h
@@ -200,16 +266,16 @@ EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
- * uxBitsToWaitFor that are set within the event group is cleared before
+ * uxBitsToWaitFor that are set within the event group will be cleared before
* xEventGroupWaitBits() returns if the wait condition was met (if the function
* returns for a reason other than a timeout). If xClearOnExit is set to
* pdFALSE then the bits set in the event group are not altered when the call to
* xEventGroupWaitBits() returns.
*
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
- * xEventGroupWaitBits() returns when either all the bits in uxBitsToWaitFor
+ * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
* are set or the specified block time expires. If xWaitForAllBits is set to
- * pdFALSE then xEventGroupWaitBits() returns when any one of the bits set
+ * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
* in uxBitsToWaitFor is set or the specified block time expires. The block
* time is specified by the xTicksToWait parameter.
*
@@ -220,7 +286,7 @@ EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupWaitBits() returned because its timeout
- * expired then not all the bits being waited for are set. If
+ * expired then not all the bits being waited for will be set. If
* xEventGroupWaitBits() returned because the bits it was waiting for were set
* then the returned value is the event group value before any bits were
* automatically cleared in the case that xClearOnExit parameter was set to
@@ -242,7 +308,7 @@ EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
xEventGroup, // The event group being tested.
BIT_0 | BIT_4, // The bits within the event group to wait for.
pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
- pdFALSE, // Don't wait for both bits, either bit works.
+ pdFALSE, // Don't wait for both bits, either bit will do.
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
@@ -303,17 +369,17 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
- // called. Both are now clear (not set).
+ // called. Both will now be clear (not set).
}
else if( ( uxBits & BIT_0 ) != 0 )
{
- // Bit 0 was set before xEventGroupClearBits() was called. It is
- // now clear.
+ // Bit 0 was set before xEventGroupClearBits() was called. It will
+ // now be clear.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
- // Bit 4 was set before xEventGroupClearBits() was called. It is
- // now clear.
+ // Bit 4 was set before xEventGroupClearBits() was called. It will
+ // now be clear.
}
else
{
@@ -340,8 +406,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* while interrupts are disabled, so protects event groups that are accessed
* from tasks by suspending the scheduler rather than disabling interrupts. As
* a result event groups cannot be accessed directly from an interrupt service
- * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
- * timer task to have the clear operation performed in the context of the timer
+ * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
+ * timer task to have the clear operation performed in the context of the timer
* task.
*
* @param xEventGroup The event group in which the bits are to be cleared.
@@ -350,8 +416,8 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
* and bit 0 set uxBitsToClear to 0x09.
*
- * @return If the request to execute the function was posted successfully then
- * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE is returned
+ * @return If the request to execute the function was posted successfully then
+ * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
@@ -376,7 +442,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
}
}
</pre>
- * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
+ * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
@@ -395,7 +461,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
* is a version that can be called from an interrupt.
*
- * Setting bits in an event group automatically unblocks tasks that are
+ * Setting bits in an event group will automatically unblock tasks that are
* blocked waiting for the bits.
*
* @param xEventGroup The event group in which the bits are to be set.
@@ -408,10 +474,10 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
* xEventGroupSetBits() returns. There are two reasons why the returned value
* might have the bits specified by the uxBitsToSet parameter cleared. First,
* if setting a bit results in a task that was waiting for the bit leaving the
- * blocked state then it is possible the bit is cleared automatically
+ * blocked state then it is possible the bit will be cleared automatically
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
* unblocked (or otherwise Ready state) task that has a priority above that of
- * the task that called xEventGroupSetBits() executes and may change the
+ * the task that called xEventGroupSetBits() will execute and may change the
* event group value before the call to xEventGroupSetBits() returns.
*
* Example usage:
@@ -470,7 +536,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed in
- * interrupts or from critical sections. Therefore xEventGroupSetBitFromISR()
+ * interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
* sends a message to the timer task to have the set operation performed in the
* context of the timer task - where a scheduler lock is used in place of a
* critical section.
@@ -482,17 +548,17 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* and bit 0 set uxBitsToSet to 0x09.
*
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
- * results in a message being sent to the timer daemon task. If the
+ * will result in a message being sent to the timer daemon task. If the
* priority of the timer daemon task is higher than the priority of the
* currently running task (the task the interrupt interrupted) then
- * *pxHigherPriorityTaskWoken is set to pdTRUE by
+ * *pxHigherPriorityTaskWoken will be set to pdTRUE by
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
* requested before the interrupt exits. For that reason
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
- * @return If the request to execute the function was posted successfully then
- * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE is returned
+ * @return If the request to execute the function was posted successfully then
+ * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
@@ -521,8 +587,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
if( xResult == pdPASS )
{
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
- // switch should be requested. The macro used is port specific and
- // is either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ // switch should be requested. The macro used is port specific and
+ // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// refer to the documentation page for the port being used.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
@@ -549,13 +615,13 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* Atomically set bits within an event group, then wait for a combination of
* bits to be set within the same event group. This functionality is typically
* used to synchronise multiple tasks, where each task has to wait for the other
- * tasks to reach a synchronization point before proceeding.
+ * tasks to reach a synchronisation point before proceeding.
*
* This function cannot be used from an interrupt.
*
- * The function returns before its block time expires if the bits specified
+ * The function will return before its block time expires if the bits specified
* by the uxBitsToWait parameter are set, or become set within that time. In
- * this case all the bits specified by uxBitsToWait is automatically
+ * this case all the bits specified by uxBitsToWait will be automatically
* cleared before the function returns.
*
* @param xEventGroup The event group in which the bits are being tested. The
@@ -577,7 +643,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupSync() returned because its timeout
- * expired then not all the bits being waited for are set. If
+ * expired then not all the bits being waited for will be set. If
* xEventGroupSync() returned because all the bits it was waiting for were
* set then the returned value is the event group value before any bits were
* automatically cleared.
@@ -605,15 +671,15 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
// Perform task functionality here.
// Set bit 0 in the event flag to note this task has reached the
- // sync point. The other two tasks set the other two bits defined
- // by ALL_SYNC_BITS. All three tasks have reached the synchronization
+ // sync point. The other two tasks will set the other two bits defined
+ // by ALL_SYNC_BITS. All three tasks have reached the synchronisation
// point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
// for this to happen.
uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
{
- // All three tasks reached the synchronization point before the call
+ // All three tasks reached the synchronisation point before the call
// to xEventGroupSync() timed out.
}
}
@@ -626,14 +692,14 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
// Perform task functionality here.
// Set bit 1 in the event flag to note this task has reached the
- // synchronization point. The other two tasks set the other two
+ // synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
- // synchronization point when all the ALL_SYNC_BITS are set. Wait
+ // synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
// xEventGroupSync() was called with an indefinite block time, so
- // this task only reaches here if the synchronization was made by all
+ // this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value.
}
}
@@ -645,14 +711,14 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
// Perform task functionality here.
// Set bit 2 in the event flag to note this task has reached the
- // synchronization point. The other two tasks set the other two
+ // synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
- // synchronization point when all the ALL_SYNC_BITS are set. Wait
+ // synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
// xEventGroupSync() was called with an indefinite block time, so
- // this task only reaches here if the synchronization was made by all
+ // this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value.
}
}
@@ -706,7 +772,7 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEG
</pre>
*
* Delete an event group that was previously created by a call to
- * xEventGroupCreate(). Tasks that are blocked on the event group are
+ * xEventGroupCreate(). Tasks that are blocked on the event group will be
* unblocked and obtain 0 as the event group's value.
*
* @param xEventGroup The event group being deleted.
@@ -717,6 +783,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
+
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
#endif
diff --git a/freertos/Source/include/freertos_tasks_c_additions.h b/freertos/Source/include/freertos_tasks_c_additions.h
new file mode 100644
index 0000000..e4bf7ea
--- /dev/null
+++ b/freertos/Source/include/freertos_tasks_c_additions.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 NXP
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* freertos_tasks_c_additions.h Rev. 1.2 */
+#ifndef FREERTOS_TASKS_C_ADDITIONS_H
+#define FREERTOS_TASKS_C_ADDITIONS_H
+
+#include <stdint.h>
+
+#if (configUSE_TRACE_FACILITY == 0)
+#error "configUSE_TRACE_FACILITY must be enabled"
+#endif
+
+#define FREERTOS_DEBUG_CONFIG_MAJOR_VERSION 1
+#define FREERTOS_DEBUG_CONFIG_MINOR_VERSION 1
+
+/* NOTE!!
+ * Default to a FreeRTOS version which didn't include these macros. FreeRTOS
+ * v7.5.3 is used here.
+ */
+#ifndef tskKERNEL_VERSION_BUILD
+#define tskKERNEL_VERSION_BUILD 3
+#endif
+#ifndef tskKERNEL_VERSION_MINOR
+#define tskKERNEL_VERSION_MINOR 5
+#endif
+#ifndef tskKERNEL_VERSION_MAJOR
+#define tskKERNEL_VERSION_MAJOR 7
+#endif
+
+/* NOTE!!
+ * The configFRTOS_MEMORY_SCHEME macro describes the heap scheme using a value
+ * 1 - 5 which corresponds to the following schemes:
+ *
+ * heap_1 - the very simplest, does not permit memory to be freed
+ * heap_2 - permits memory to be freed, but not does coalescence adjacent free
+ * blocks.
+ * heap_3 - simply wraps the standard malloc() and free() for thread safety
+ * heap_4 - coalesces adjacent free blocks to avoid fragmentation. Includes
+ * absolute address placement option
+ * heap_5 - as per heap_4, with the ability to span the heap across
+ * multiple nonOadjacent memory areas
+ */
+#ifndef configFRTOS_MEMORY_SCHEME
+#define configFRTOS_MEMORY_SCHEME 3 /* thread safe malloc */
+#endif
+
+#if ((configFRTOS_MEMORY_SCHEME > 5) || (configFRTOS_MEMORY_SCHEME < 1))
+#error "Invalid configFRTOS_MEMORY_SCHEME setting!"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const uint8_t FreeRTOSDebugConfig[];
+
+/* NOTES!!
+ * IAR documentation is confusing. It suggests the data must be statically
+ * linked, and the #pragma placed immediately before the symbol definition.
+ * The IAR supplied examples violate both "rules", so this is a best guess.
+ */
+#if defined(__GNUC__)
+const uint8_t FreeRTOSDebugConfig[] __attribute__((section(".rodata"))) =
+#elif defined(__CC_ARM)
+const uint8_t FreeRTOSDebugConfig[] __attribute__((used)) =
+#elif defined(__IAR_SYSTEMS_ICC__)
+#pragma required=FreeRTOSDebugConfig
+const uint8_t FreeRTOSDebugConfig[] =
+#endif
+{
+ FREERTOS_DEBUG_CONFIG_MAJOR_VERSION,
+ FREERTOS_DEBUG_CONFIG_MINOR_VERSION,
+ tskKERNEL_VERSION_MAJOR,
+ tskKERNEL_VERSION_MINOR,
+ tskKERNEL_VERSION_BUILD,
+ configFRTOS_MEMORY_SCHEME,
+ offsetof(struct tskTaskControlBlock, pxTopOfStack),
+#if (tskKERNEL_VERSION_MAJOR > 8)
+ offsetof(struct tskTaskControlBlock, xStateListItem),
+#else
+ offsetof(struct tskTaskControlBlock, xGenericListItem),
+#endif
+ offsetof(struct tskTaskControlBlock, xEventListItem),
+ offsetof(struct tskTaskControlBlock, pxStack),
+ offsetof(struct tskTaskControlBlock, pcTaskName),
+ offsetof(struct tskTaskControlBlock, uxTCBNumber),
+ offsetof(struct tskTaskControlBlock, uxTaskNumber),
+ configMAX_TASK_NAME_LEN,
+ configMAX_PRIORITIES,
+ 0 /* pad to 32-bit boundary */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FREERTOS_TASKS_C_ADDITIONS_H
diff --git a/freertos/Source/include/list.h b/freertos/Source/include/list.h
index 06287f1..a080d27 100644
--- a/freertos/Source/include/list.h
+++ b/freertos/Source/include/list.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -115,16 +115,16 @@
* deemed to be as intended. That said, as compiler technology advances, and
* especially if aggressive cross module optimisation is used (a use case that
* has not been exercised to any great extend) then it is feasible that the
- * volatile qualifier is needed for correct optimisation. It is expected
+ * volatile qualifier will be needed for correct optimisation. It is expected
* that a compiler removing essential code because, without the volatile
* qualifier on the list structure members and with aggressive cross module
- * optimisation, the compiler deemed the code unnecessary results in
+ * optimisation, the compiler deemed the code unnecessary will result in
* complete and obvious failure of the scheduler. If this is ever experienced
* then the volatile qualifier can be inserted in the relevant places within the
* list structures by simply defining configLIST_VOLATILE to volatile in
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
* If configLIST_VOLATILE is not defined then the preprocessor directives below
- * simply #define configLIST_VOLATILE away completely.
+ * will simply #define configLIST_VOLATILE away completely.
*
* To use volatile list structure members then add the following line to
* FreeRTOSConfig.h (without the quotes):
@@ -141,7 +141,7 @@ extern "C" {
/* Macros that can be used to place known values within the list structures,
then check that the known values do not get corrupted during the execution of
the application. These may catch the list data structures being overwritten in
-memory. They do not catch data errors caused by incorrect configuration or
+memory. They will not catch data errors caused by incorrect configuration or
use of FreeRTOS.*/
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
/* Define the macros to do nothing. */
@@ -168,7 +168,7 @@ use of FreeRTOS.*/
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
- /* Define macros that assert if one of the structure members does not
+ /* Define macros that will assert if one of the structure members does not
contain its expected value. */
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
@@ -282,8 +282,8 @@ typedef struct xLIST
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
/*
- * Access macro to determine if a list contains any items. The macro
- * only has the value true if the list is empty.
+ * Access macro to determine if a list contains any items. The macro will
+ * only have the value true if the list is empty.
*
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
* \ingroup LinkedList
@@ -397,7 +397,7 @@ void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
/*
- * Insert a list item into a list. The item is inserted into the list in
+ * Insert a list item into a list. The item will be inserted into the list in
* a position determined by its item value (descending item value order).
*
* @param pxList The list into which the item is to be inserted.
@@ -410,16 +410,16 @@ void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/*
- * Insert a list item into a list. The item is inserted in a position
- * such that it is the last item within the list returned by multiple
+ * Insert a list item into a list. The item will be inserted in a position
+ * such that it will be the last item within the list returned by multiple
* calls to listGET_OWNER_OF_NEXT_ENTRY.
*
- * The list member pvIndex is used to walk through a list. Calling
- * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list.
+ * The list member pxIndex is used to walk through a list. Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
* Placing an item in a list using vListInsertEnd effectively places the item
- * in the list position pointed to by pvIndex. This means that every other
- * item within the list is returned by listGET_OWNER_OF_NEXT_ENTRY before
- * the pvIndex parameter again points to the item being inserted.
+ * in the list position pointed to by pxIndex. This means that every other
+ * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
+ * the pxIndex parameter again points to the item being inserted.
*
* @param pxList The list into which the item is to be inserted.
*
@@ -434,7 +434,7 @@ void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) P
* Remove an item from a list. The list item has a pointer to the list that
* it is in, so only the list item need be passed into the function.
*
- * @param uxListRemove The item to be removed. The item removes itself from
+ * @param uxListRemove The item to be removed. The item will remove itself from
* the list pointed to by it's pxContainer parameter.
*
* @return The number of items that remain in the list after the list item has
diff --git a/freertos/Source/include/mpu_prototypes.h b/freertos/Source/include/mpu_prototypes.h
new file mode 100644
index 0000000..8f7500b
--- /dev/null
+++ b/freertos/Source/include/mpu_prototypes.h
@@ -0,0 +1,177 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * When the MPU is used the standard (non MPU) API functions are mapped to
+ * equivalents that start "MPU_", the prototypes for which are defined in this
+ * header files. This will cause the application code to call the MPU_ version
+ * which wraps the non-MPU version with privilege promoting then demoting code,
+ * so the kernel code always runs will full privileges.
+ */
+
+
+#ifndef MPU_PROTOTYPES_H
+#define MPU_PROTOTYPES_H
+
+/* MPU versions of tasks.h API function. */
+BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
+TaskHandle_t MPU_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 );
+BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
+void MPU_vTaskDelete( TaskHandle_t xTaskToDelete );
+void MPU_vTaskDelay( const TickType_t xTicksToDelay );
+void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement );
+BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask );
+UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t xTask );
+eTaskState MPU_eTaskGetState( TaskHandle_t xTask );
+void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
+void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
+void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend );
+void MPU_vTaskResume( TaskHandle_t xTaskToResume );
+void MPU_vTaskStartScheduler( void );
+void MPU_vTaskSuspendAll( void );
+BaseType_t MPU_xTaskResumeAll( void );
+TickType_t MPU_xTaskGetTickCount( void );
+UBaseType_t MPU_uxTaskGetNumberOfTasks( void );
+char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery );
+TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery );
+UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
+TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask );
+void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue );
+void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex );
+BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
+TaskHandle_t MPU_xTaskGetIdleTaskHandle( void );
+UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime );
+void MPU_vTaskList( char * pcWriteBuffer );
+void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer );
+BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue );
+BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask );
+BaseType_t MPU_xTaskIncrementTick( void );
+TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void );
+void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );
+BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );
+void MPU_vTaskMissedYield( void );
+BaseType_t MPU_xTaskGetSchedulerState( void );
+
+/* MPU versions of queue.h API function. */
+BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition );
+BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek );
+UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+void MPU_vQueueDelete( QueueHandle_t xQueue );
+QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType );
+QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue );
+QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount );
+QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue );
+void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore );
+BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait );
+BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex );
+void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName );
+void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue );
+const char * MPU_pcQueueGetName( QueueHandle_t xQueue );
+QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType );
+QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType );
+QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength );
+BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
+BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
+QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait );
+BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue );
+void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber );
+UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue );
+uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue );
+
+/* MPU versions of timers.h API function. */
+TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction );
+TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer );
+void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer );
+void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
+BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer );
+TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void );
+BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait );
+const char * MPU_pcTimerGetName( TimerHandle_t xTimer );
+TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer );
+TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer );
+BaseType_t MPU_xTimerCreateTimerTask( void );
+BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait );
+
+/* MPU versions of event_group.h API function. */
+EventGroupHandle_t MPU_xEventGroupCreate( void );
+EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer );
+EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
+EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait );
+void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup );
+UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup );
+
+#endif /* MPU_PROTOTYPES_H */
+
diff --git a/freertos/Source/include/mpu_wrappers.h b/freertos/Source/include/mpu_wrappers.h
index cc8a91a..78f5a9a 100644
--- a/freertos/Source/include/mpu_wrappers.h
+++ b/freertos/Source/include/mpu_wrappers.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -74,84 +74,108 @@
only for ports that are using the MPU. */
#ifdef portUSING_MPU_WRAPPERS
- /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is defined when this file is
+ /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
included from queue.c or task.c to prevent it from having an effect within
those files. */
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
- #define xTaskGenericCreate MPU_xTaskGenericCreate
- #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
- #define vTaskDelete MPU_vTaskDelete
- #define vTaskDelayUntil MPU_vTaskDelayUntil
- #define vTaskDelay MPU_vTaskDelay
- #define uxTaskPriorityGet MPU_uxTaskPriorityGet
- #define vTaskPrioritySet MPU_vTaskPrioritySet
- #define eTaskGetState MPU_eTaskGetState
- #define vTaskSuspend MPU_vTaskSuspend
- #define vTaskResume MPU_vTaskResume
- #define vTaskSuspendAll MPU_vTaskSuspendAll
- #define xTaskResumeAll MPU_xTaskResumeAll
- #define xTaskGetTickCount MPU_xTaskGetTickCount
- #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
- #define vTaskList MPU_vTaskList
- #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
- #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
- #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
- #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
- #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
- #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
- #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
- #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
- #define uxTaskGetSystemState MPU_uxTaskGetSystemState
- #define xTaskGenericNotify MPU_xTaskGenericNotify
- #define xTaskNotifyWait MPU_xTaskNotifyWait
- #define ulTaskNotifyTake MPU_ulTaskNotifyTake
-
- #define xQueueGenericCreate MPU_xQueueGenericCreate
- #define xQueueCreateMutex MPU_xQueueCreateMutex
- #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
- #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
- #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
- #define xQueueGenericSend MPU_xQueueGenericSend
- #define xQueueAltGenericSend MPU_xQueueAltGenericSend
- #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive
- #define xQueueGenericReceive MPU_xQueueGenericReceive
- #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
- #define vQueueDelete MPU_vQueueDelete
- #define xQueueGenericReset MPU_xQueueGenericReset
- #define xQueueCreateSet MPU_xQueueCreateSet
- #define xQueueSelectFromSet MPU_xQueueSelectFromSet
- #define xQueueAddToSet MPU_xQueueAddToSet
- #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
- #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
- #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
-
- #define pvPortMalloc MPU_pvPortMalloc
- #define vPortFree MPU_vPortFree
- #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize
- #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks
- #define xPortGetMinimumEverFreeHeapSize MPU_xPortGetMinimumEverFreeHeapSize
-
- #if configQUEUE_REGISTRY_SIZE > 0
- #define vQueueAddToRegistry MPU_vQueueAddToRegistry
- #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
+ /*
+ * Map standard (non MPU) API functions to equivalents that start
+ * "MPU_". This will cause the application code to call the MPU_
+ * version, which wraps the non-MPU version with privilege promoting
+ * then demoting code, so the kernel code always runs will full
+ * privileges.
+ */
+
+ /* Map standard tasks.h API functions to the MPU equivalents. */
+ #define xTaskCreate MPU_xTaskCreate
+ #define xTaskCreateStatic MPU_xTaskCreateStatic
+ #define xTaskCreateRestricted MPU_xTaskCreateRestricted
+ #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
+ #define vTaskDelete MPU_vTaskDelete
+ #define vTaskDelay MPU_vTaskDelay
+ #define vTaskDelayUntil MPU_vTaskDelayUntil
+ #define xTaskAbortDelay MPU_xTaskAbortDelay
+ #define uxTaskPriorityGet MPU_uxTaskPriorityGet
+ #define eTaskGetState MPU_eTaskGetState
+ #define vTaskGetInfo MPU_vTaskGetInfo
+ #define vTaskPrioritySet MPU_vTaskPrioritySet
+ #define vTaskSuspend MPU_vTaskSuspend
+ #define vTaskResume MPU_vTaskResume
+ #define vTaskSuspendAll MPU_vTaskSuspendAll
+ #define xTaskResumeAll MPU_xTaskResumeAll
+ #define xTaskGetTickCount MPU_xTaskGetTickCount
+ #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
+ #define pcTaskGetName MPU_pcTaskGetName
+ #define xTaskGetHandle MPU_xTaskGetHandle
+ #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
+ #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
+ #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
+ #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
+ #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
+ #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
+ #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
+ #define uxTaskGetSystemState MPU_uxTaskGetSystemState
+ #define vTaskList MPU_vTaskList
+ #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
+ #define xTaskGenericNotify MPU_xTaskGenericNotify
+ #define xTaskNotifyWait MPU_xTaskNotifyWait
+ #define ulTaskNotifyTake MPU_ulTaskNotifyTake
+ #define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
+
+ #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
+ #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
+ #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
+ #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
+
+ /* Map standard queue.h API functions to the MPU equivalents. */
+ #define xQueueGenericSend MPU_xQueueGenericSend
+ #define xQueueGenericReceive MPU_xQueueGenericReceive
+ #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
+ #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
+ #define vQueueDelete MPU_vQueueDelete
+ #define xQueueCreateMutex MPU_xQueueCreateMutex
+ #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
+ #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
+ #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
+ #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
+ #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
+ #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
+ #define xQueueGenericCreate MPU_xQueueGenericCreate
+ #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
+ #define xQueueCreateSet MPU_xQueueCreateSet
+ #define xQueueAddToSet MPU_xQueueAddToSet
+ #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
+ #define xQueueSelectFromSet MPU_xQueueSelectFromSet
+ #define xQueueGenericReset MPU_xQueueGenericReset
+
+ #if( configQUEUE_REGISTRY_SIZE > 0 )
+ #define vQueueAddToRegistry MPU_vQueueAddToRegistry
+ #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
+ #define pcQueueGetName MPU_pcQueueGetName
#endif
- #define xTimerCreate MPU_xTimerCreate
- #define pvTimerGetTimerID MPU_pvTimerGetTimerID
- #define vTimerSetTimerID MPU_vTimerSetTimerID
- #define xTimerIsTimerActive MPU_xTimerIsTimerActive
- #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
- #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
- #define pcTimerGetTimerName MPU_pcTimerGetTimerName
- #define xTimerGenericCommand MPU_xTimerGenericCommand
-
- #define xEventGroupCreate MPU_xEventGroupCreate
- #define xEventGroupWaitBits MPU_xEventGroupWaitBits
- #define xEventGroupClearBits MPU_xEventGroupClearBits
- #define xEventGroupSetBits MPU_xEventGroupSetBits
- #define xEventGroupSync MPU_xEventGroupSync
- #define vEventGroupDelete MPU_vEventGroupDelete
+ /* Map standard timer.h API functions to the MPU equivalents. */
+ #define xTimerCreate MPU_xTimerCreate
+ #define xTimerCreateStatic MPU_xTimerCreateStatic
+ #define pvTimerGetTimerID MPU_pvTimerGetTimerID
+ #define vTimerSetTimerID MPU_vTimerSetTimerID
+ #define xTimerIsTimerActive MPU_xTimerIsTimerActive
+ #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
+ #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
+ #define pcTimerGetName MPU_pcTimerGetName
+ #define xTimerGetPeriod MPU_xTimerGetPeriod
+ #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
+ #define xTimerGenericCommand MPU_xTimerGenericCommand
+
+ /* Map standard event_group.h API functions to the MPU equivalents. */
+ #define xEventGroupCreate MPU_xEventGroupCreate
+ #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
+ #define xEventGroupWaitBits MPU_xEventGroupWaitBits
+ #define xEventGroupClearBits MPU_xEventGroupClearBits
+ #define xEventGroupSetBits MPU_xEventGroupSetBits
+ #define xEventGroupSync MPU_xEventGroupSync
+ #define vEventGroupDelete MPU_vEventGroupDelete
/* Remove the privileged function macro. */
#define PRIVILEGED_FUNCTION
diff --git a/freertos/Source/include/portable.h b/freertos/Source/include/portable.h
index 86bac91..b9f8be3 100644
--- a/freertos/Source/include/portable.h
+++ b/freertos/Source/include/portable.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -154,7 +154,7 @@ typedef struct HeapRegion
/*
* Used to define multiple heap regions for use by heap_5.c. This function
* must be called before any calls to pvPortMalloc() - not creating a task,
- * queue, semaphore, mutex, software timer, event group, and so on, results in
+ * queue, semaphore, mutex, software timer, event group, etc. will result in
* pvPortMalloc being called.
*
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
@@ -196,7 +196,7 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
*/
#if( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION;
- void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) PRIVILEGED_FUNCTION;
+ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
#endif
#ifdef __cplusplus
diff --git a/freertos/Source/include/projdefs.h b/freertos/Source/include/projdefs.h
index ffe46f4..0b63fd8 100644
--- a/freertos/Source/include/projdefs.h
+++ b/freertos/Source/include/projdefs.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -76,8 +76,12 @@
*/
typedef void (*TaskFunction_t)( void * );
-/* Converts a time in milliseconds to a time in ticks. */
-#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
+/* Converts a time in milliseconds to a time in ticks. This macro can be
+overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
+definition here is not suitable for your application. */
+#ifndef pdMS_TO_TICKS
+ #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
+#endif
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
@@ -107,6 +111,7 @@ typedef void (*TaskFunction_t)( void * );
itself. */
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
+#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
diff --git a/freertos/Source/include/queue.h b/freertos/Source/include/queue.h
index 0e1d0d6..30be360 100644
--- a/freertos/Source/include/queue.h
+++ b/freertos/Source/include/queue.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -123,14 +123,26 @@ typedef void * QueueSetMemberHandle_t;
);
* </pre>
*
- * Creates a new queue instance. This allocates the storage required by the
- * new queue and returns a handle for the queue.
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory. The first block is used to hold the queue's data structures. The
+ * second block is used to hold items placed into the queue. If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html
*
* @param uxQueueLength The maximum number of items that the queue can contain.
*
- * @param uxItemSize The number of bytes each item in the queue requires.
+ * @param uxItemSize The number of bytes each item in the queue will require.
* Items are queued by copy, not by reference, so this is the number of bytes
- * that is copied for each posted item. Each item on the queue must be
+ * that will be copied for each posted item. Each item on the queue must be
* the same size.
*
* @return If the queue is successfully create then a handle to the newly
@@ -170,7 +182,95 @@ typedef void * QueueSetMemberHandle_t;
* \defgroup xQueueCreate xQueueCreate
* \ingroup QueueManagement
*/
-#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
+#endif
+
+/**
+ * queue. h
+ * <pre>
+ QueueHandle_t xQueueCreateStatic(
+ UBaseType_t uxQueueLength,
+ UBaseType_t uxItemSize,
+ uint8_t *pucQueueStorageBuffer,
+ StaticQueue_t *pxQueueBuffer
+ );
+ * </pre>
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory. The first block is used to hold the queue's data structures. The
+ * second block is used to hold items placed into the queue. If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item. Each item on the queue must be
+ * the same size.
+ *
+ * @param pucQueueStorageBuffer If uxItemSize is not zero then
+ * pucQueueStorageBuffer must point to a uint8_t array that is at least large
+ * enough to hold the maximum number of items that can be in the queue at any
+ * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is
+ * zero then pucQueueStorageBuffer can be NULL.
+ *
+ * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
+ * will be used to hold the queue's data structure.
+ *
+ * @return If the queue is created then a handle to the created queue is
+ * returned. If pxQueueBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ };
+
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+
+ // xQueueBuffer will hold the queue structure.
+ StaticQueue_t xQueueBuffer;
+
+ // ucQueueStorage will hold the items posted to the queue. Must be at least
+ // [(queue length) * ( queue item size)] bytes long.
+ uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1;
+
+ // Create a queue capable of containing 10 uint32_t values.
+ xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+ ITEM_SIZE // The size of each item in the queue
+ &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+ &xQueueBuffer ); // The buffer that will hold the queue structure.
+
+ // The queue is guaranteed to be created successfully as no dynamic memory
+ // allocation is used. Therefore xQueue1 is now a handle to a valid queue.
+
+ // ... Rest of task code.
+ }
+ </pre>
+ * \defgroup xQueueCreateStatic xQueueCreateStatic
+ * \ingroup QueueManagement
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* queue. h
@@ -192,13 +292,13 @@ typedef void * QueueSetMemberHandle_t;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for space to become available on the queue, should it already
- * be full. The call returns immediately if this is set to 0 and the
+ * be full. The call will return immediately if this is set to 0 and the
* queue is full. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
*
@@ -274,13 +374,13 @@ typedef void * QueueSetMemberHandle_t;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for space to become available on the queue, should it already
- * be full. The call returns immediately if this is set to 0 and the queue
+ * be full. The call will return immediately if this is set to 0 and the queue
* is full. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
*
@@ -358,13 +458,13 @@ typedef void * QueueSetMemberHandle_t;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for space to become available on the queue, should it already
- * be full. The call returns immediately if this is set to 0 and the
+ * be full. The call will return immediately if this is set to 0 and the
* queue is full. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
*
@@ -441,13 +541,13 @@ typedef void * QueueSetMemberHandle_t;
* @param xQueue The handle of the queue to which the data is being sent.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes are copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and
* therefore has the same return values as xQueueSendToFront(). However, pdPASS
- * is the only value that can be returned because xQueueOverwrite() writes
+ * is the only value that can be returned because xQueueOverwrite() will write
* to the queue even when the queue is already full.
*
* Example usage:
@@ -460,7 +560,7 @@ typedef void * QueueSetMemberHandle_t;
// Create a queue to hold one uint32_t value. It is strongly
// recommended *not* to use xQueueOverwrite() on queues that can
- // contain more than one value, and doing so triggers an assertion
+ // contain more than one value, and doing so will trigger an assertion
// if configASSERT() is defined.
xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
@@ -525,13 +625,13 @@ typedef void * QueueSetMemberHandle_t;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for space to become available on the queue, should it already
- * be full. The call returns immediately if this is set to 0 and the
+ * be full. The call will return immediately if this is set to 0 and the
* queue is full. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
*
@@ -607,7 +707,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
* provided. The number of bytes copied into the buffer was defined when
* the queue was created.
*
- * Successfully received items remain on the queue so is returned again
+ * Successfully received items remain on the queue so will be returned again
* by the next call, or a call to xQueueReceive().
*
* This macro must not be used in an interrupt service routine. See
@@ -617,14 +717,14 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
* @param xQueue The handle to the queue from which the item is to be
* received.
*
- * @param pvBuffer Pointer to the buffer into which the received item is
- * copied.
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time
* of the call. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
- * xQueuePeek() returns immediately if xTicksToWait is 0 and the queue
+ * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
* is empty.
*
* @return pdTRUE if an item was successfully received from the queue,
@@ -703,14 +803,14 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
* provided. The number of bytes copied into the buffer was defined when
* the queue was created.
*
- * Successfully received items remain on the queue and are returned again
+ * Successfully received items remain on the queue so will be returned again
* by the next call, or a call to xQueueReceive().
*
* @param xQueue The handle to the queue from which the item is to be
* received.
*
- * @param pvBuffer Pointer to the buffer into which the received item is
- * copied.
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
*
* @return pdTRUE if an item was successfully received from the queue,
* otherwise pdFALSE.
@@ -743,12 +843,12 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV
* @param xQueue The handle to the queue from which the item is to be
* received.
*
- * @param pvBuffer Pointer to the buffer into which the received item is
- * copied.
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time
- * of the call. xQueueReceive() returns immediately if xTicksToWait
+ * of the call. xQueueReceive() will return immediately if xTicksToWait
* is zero and the queue is empty. The time is defined in tick periods so the
* constant portTICK_PERIOD_MS should be used to convert to real time if this is
* required.
@@ -837,19 +937,19 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV
* @param xQueue The handle to the queue from which the item is to be
* received.
*
- * @param pvBuffer Pointer to the buffer into which the received item
- * is copied.
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
*
* @param xTicksToWait The maximum amount of time the task should block
* waiting for an item to receive should the queue be empty at the time
* of the call. The time is defined in tick periods so the constant
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
- * xQueueGenericReceive() returns immediately if the queue is empty and
+ * xQueueGenericReceive() will return immediately if the queue is empty and
* xTicksToWait is 0.
*
* @param xJustPeek When set to true, the item received from the queue is not
* actually removed from the queue - meaning a subsequent call to
- * xQueueReceive() returns the same item. When set to false, the item
+ * xQueueReceive() will return the same item. When set to false, the item
* being received from the queue is also removed from the queue.
*
* @return pdTRUE if an item was successfully received from the queue,
@@ -980,11 +1080,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
- * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() sets
+ * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then
@@ -1051,11 +1151,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
- * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() is set
+ * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then
@@ -1121,11 +1221,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
- * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() sets
+ * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then
@@ -1134,7 +1234,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* @return xQueueOverwriteFromISR() is a macro that calls
* xQueueGenericSendFromISR(), and therefore has the same return values as
* xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be
- * returned because xQueueOverwriteFromISR() writes to the queue even when
+ * returned because xQueueOverwriteFromISR() will write to the queue even when
* the queue is already full.
*
* Example usage:
@@ -1146,7 +1246,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
{
// Create a queue to hold one uint32_t value. It is strongly
// recommended *not* to use xQueueOverwriteFromISR() on queues that can
- // contain more than one value, and doing so triggers an assertion
+ // contain more than one value, and doing so will trigger an assertion
// if configASSERT() is defined.
xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
}
@@ -1161,13 +1261,13 @@ uint32_t ulVarToSend, ulValReceived;
ulVarToSend = 10;
xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
- // The queue is full, but calling xQueueOverwriteFromISR() again is still
- // passed because the value held in the queue is overwritten with the
+ // The queue is full, but calling xQueueOverwriteFromISR() again will still
+ // pass because the value held in the queue will be overwritten with the
// new value.
ulVarToSend = 100;
xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
- // Reading from the queue now returns 100.
+ // Reading from the queue will now return 100.
// ...
@@ -1211,11 +1311,11 @@ uint32_t ulVarToSend, ulValReceived;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
- * @param pxHigherPriorityTaskWoken xQueueSendFromISR() sets
+ * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xQueueSendFromISR() sets this value to pdTRUE then
@@ -1286,11 +1386,11 @@ uint32_t ulVarToSend, ulValReceived;
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
- * queue. The size of the items the queue holds was defined when the
- * queue was created, so this many bytes is copied from pvItemToQueue
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
- * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() sets
+ * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then
@@ -1356,13 +1456,13 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherP
* @param xQueue The handle to the queue from which the item is to be
* received.
*
- * @param pvBuffer Pointer to the buffer into which the received item
- * is copied.
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
*
* @param pxTaskWoken A task may be blocked waiting for space to become
* available on the queue. If xQueueReceiveFromISR causes such a task to
- * unblock *pxTaskWoken gets set to pdTRUE, otherwise *pxTaskWoken
- * remains unchanged.
+ * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
+ * remain unchanged.
*
* @return pdTRUE if an item was successfully received from the queue,
* otherwise pdFALSE.
@@ -1387,8 +1487,8 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherP
// ...
- // Post some characters that is used within an ISR. If the queue
- // is full then this task blocks for xTicksToWait ticks.
+ // Post some characters that will be used within an ISR. If the queue
+ // is full then this task will block for xTicksToWait ticks.
cValueToPost = 'a';
xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
cValueToPost = 'b';
@@ -1415,7 +1515,7 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherP
// If removing the character from the queue woke the task that was
// posting onto the queue cTaskWokenByReceive will have been set to
// pdTRUE. No matter how many times this loop iterates only one
- // task is woken up.
+ // task will be woken.
}
if( cTaskWokenByPost != ( char ) pdFALSE;
@@ -1437,28 +1537,6 @@ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FU
BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
-
-/*
- * xQueueAltGenericSend() is an alternative version of xQueueGenericSend().
- * Likewise xQueueAltGenericReceive() is an alternative version of
- * xQueueGenericReceive().
- *
- * The source code that implements the alternative (Alt) API is much
- * simpler because it executes everything from within a critical section.
- * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
- * preferred fully featured API too. The fully featured API has more
- * complex code that takes longer to execute, but makes much less use of
- * critical sections. Therefore the alternative API sacrifices interrupt
- * responsiveness to gain execution speed, whereas the fully featured API
- * sacrifices execution speed to ensure better interrupt responsiveness.
- */
-BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
-BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) PRIVILEGED_FUNCTION;
-#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
-#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
-#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE )
-#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE )
-
/*
* The functions defined above are for passing data to and from tasks. The
* functions below are the equivalents for passing data to and from
@@ -1479,7 +1557,9 @@ BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTi
* these functions directly.
*/
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
/*
@@ -1513,11 +1593,11 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
* handles can also be passed in here.
*
* @param pcName The name to be associated with the handle. This is the
- * name that the kernel aware debugger displays. The queue registry only
+ * name that the kernel aware debugger will display. The queue registry only
* stores a pointer to the string - so the string must be persistent (global or
* preferably in ROM/Flash), not on the stack.
*/
-#if configQUEUE_REGISTRY_SIZE > 0
+#if( configQUEUE_REGISTRY_SIZE > 0 )
void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#endif
@@ -1531,15 +1611,42 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
*
* @param xQueue The handle of the queue being removed from the registry.
*/
-#if configQUEUE_REGISTRY_SIZE > 0
+#if( configQUEUE_REGISTRY_SIZE > 0 )
void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#endif
/*
- * Generic version of the queue creation function, which is in turn called by
- * any queue, semaphore or mutex creation function or macro.
+ * The queue registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call pcQueueGetName() to look
+ * up and return the name of a queue in the queue registry from the queue's
+ * handle.
+ *
+ * @param xQueue The handle of the queue the name of which will be returned.
+ * @return If the queue is in the registry then a pointer to the name of the
+ * queue is returned. If the queue is not in the registry then NULL is
+ * returned.
+ */
+#if( configQUEUE_REGISTRY_SIZE > 0 )
+ const char *pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif
+
+/*
+ * Generic version of the function used to creaet a queue using dynamic memory
+ * allocation. This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
*/
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Generic version of the function used to creaet a queue using dynamic memory
+ * allocation. This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
/*
* Queue sets provide a mechanism to allow a task to block (pend) on a read
@@ -1559,7 +1666,7 @@ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseT
* for reasons why queue sets are very rarely needed in practice as there are
* simpler methods of blocking on multiple objects.
*
- * Note 2: Blocking on a queue set that contains a mutex does not cause the
+ * Note 2: Blocking on a queue set that contains a mutex will not cause the
* mutex holder to inherit the priority of the blocked task.
*
* Note 3: An additional 4 bytes of RAM is required for each space in a every
@@ -1648,21 +1755,21 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueS
* for reasons why queue sets are very rarely needed in practice as there are
* simpler methods of blocking on multiple objects.
*
- * Note 2: Blocking on a queue set that contains a mutex does not cause the
+ * Note 2: Blocking on a queue set that contains a mutex will not cause the
* mutex holder to inherit the priority of the blocked task.
*
* Note 3: A receive (in the case of a queue) or take (in the case of a
* semaphore) operation must not be performed on a member of a queue set unless
* a call to xQueueSelectFromSet() has first returned a handle to that set member.
*
- * @param xQueueSet The queue set on which the task (potentially) blocks.
+ * @param xQueueSet The queue set on which the task will (potentially) block.
*
- * @param xTicksToWait The maximum time, in ticks, that the calling task
- * remains in the Blocked state (with other tasks executing) to wait for a member
+ * @param xTicksToWait The maximum time, in ticks, that the calling task will
+ * remain in the Blocked state (with other tasks executing) to wait for a member
* of the queue set to be ready for a successful queue read or semaphore take
* operation.
*
- * @return xQueueSelectFromSet() returns the handle of a queue (cast to
+ * @return xQueueSelectFromSet() will return the handle of a queue (cast to
* a QueueSetMemberHandle_t type) contained in the queue set that contains data,
* or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained
* in the queue set that is available, or NULL if no such queue or semaphore
diff --git a/freertos/Source/include/semphr.h b/freertos/Source/include/semphr.h
index 9f76072..a674b02 100644
--- a/freertos/Source/include/semphr.h
+++ b/freertos/Source/include/semphr.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -87,6 +87,10 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semphr. h
* <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre>
*
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
* This old vSemaphoreCreateBinary() macro is now deprecated in favour of the
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
@@ -128,19 +132,37 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
-#define vSemaphoreCreateBinary( xSemaphore ) \
- { \
- ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
- if( ( xSemaphore ) != NULL ) \
- { \
- ( void ) xSemaphoreGive( ( xSemaphore ) ); \
- } \
- }
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define vSemaphoreCreateBinary( xSemaphore ) \
+ { \
+ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
+ if( ( xSemaphore ) != NULL ) \
+ { \
+ ( void ) xSemaphoreGive( ( xSemaphore ) ); \
+ } \
+ }
+#endif
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre>
*
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored. If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function. (see http://www.freertos.org/a00111.html). If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
* The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
@@ -148,11 +170,6 @@ typedef QueueHandle_t SemaphoreHandle_t;
* created using xSemaphoreCreateBinary() are created in a state such that the
* the semaphore must first be 'given' before it can be 'taken'.
*
- * Function that creates a semaphore by using the existing queue mechanism.
- * The queue length is 1 as this is a binary semaphore. The data size is 0
- * as nothing is actually stored - all that is important is whether the queue is
- * empty or full (the binary semaphore is available or not).
- *
* This type of semaphore can be used for pure synchronisation between tasks or
* between an interrupt and a task. The semaphore need not be given back once
* obtained, so one task/interrupt can continuously 'give' the semaphore while
@@ -160,7 +177,8 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semaphore does not use a priority inheritance mechanism. For an alternative
* that does use priority inheritance see xSemaphoreCreateMutex().
*
- * @return Handle to the created semaphore.
+ * @return Handle to the created semaphore, or NULL if the memory required to
+ * hold the semaphore's data structures could not be allocated.
*
* Example usage:
<pre>
@@ -168,7 +186,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
void vATask( void * pvParameters )
{
- // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+ // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
// This is a macro so pass the variable in directly.
xSemaphore = xSemaphoreCreateBinary();
@@ -179,10 +197,71 @@ typedef QueueHandle_t SemaphoreHandle_t;
}
}
</pre>
- * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )</pre>
+ *
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * NOTE: In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored. If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function. (see http://www.freertos.org/a00111.html). If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task. The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore. For this reason this type of
+ * semaphore does not use a priority inheritance mechanism. For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the semaphore is created then a handle to the created semaphore is
+ * returned. If pxSemaphoreBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore = NULL;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+ // The semaphore's data structures will be placed in the xSemaphoreBuffer
+ // variable, the address of which is passed into the function. The
+ // function's parameter is not NULL, so the function will not attempt any
+ // dynamic memory allocation, and therefore the function will not return
+ // return NULL.
+ xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
+
+ // Rest of task code goes here.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
* \ingroup Semaphores
*/
-#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
@@ -192,7 +271,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
* )</pre>
*
* <i>Macro</i> to obtain a semaphore. The semaphore must have previously been
- * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
* xSemaphoreCreateCounting().
*
* @param xSemaphore A handle to the semaphore being taken - obtained when
@@ -215,7 +294,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
void vATask( void * pvParameters )
{
// Create the semaphore to guard a shared resource.
- vSemaphoreCreateBinary( xSemaphore );
+ xSemaphore = xSemaphoreCreateBinary();
}
// A task that uses the semaphore.
@@ -270,8 +349,8 @@ typedef QueueHandle_t SemaphoreHandle_t;
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example,
- * if a task successfully 'takes' the same mutex 5 times then the mutex
- * is not available to any other task until it has also 'given' the mutex back
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
* exactly five times.
*
* @param xMutex A handle to the mutex being obtained. This is the
@@ -280,8 +359,8 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @param xBlockTime The time in ticks to wait for the semaphore to become
* available. The macro portTICK_PERIOD_MS can be used to convert this to a
* real time. A block time of zero can be used to poll the semaphore. If
- * the task already owns the semaphore then xSemaphoreTakeRecursive()
- * returns immediately no matter what the value of xBlockTime.
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will
+ * return immediately no matter what the value of xBlockTime.
*
* @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime
* expired without the semaphore becoming available.
@@ -320,7 +399,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
- // The mutex has now been 'taken' three times, so is not
+ // The mutex has now been 'taken' three times, so will not be
// available to another task until it has also been given back
// three times. Again it is unlikely that real code would have
// these calls sequentially, but instead buried in a more complex
@@ -342,29 +421,16 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive
* \ingroup Semaphores
*/
-#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
-
-
-/*
- * xSemaphoreAltTake() is an alternative version of xSemaphoreTake().
- *
- * The source code that implements the alternative (Alt) API is much
- * simpler because it executes everything from within a critical section.
- * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
- * preferred fully featured API too. The fully featured API has more
- * complex code that takes longer to execute, but makes much less use of
- * critical sections. Therefore the alternative API sacrifices interrupt
- * responsiveness to gain execution speed, whereas the fully featured API
- * sacrifices execution speed to ensure better interrupt responsiveness.
- */
-#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+#if( configUSE_RECURSIVE_MUTEXES == 1 )
+ #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
+#endif
/**
* semphr. h
* <pre>xSemaphoreGive( SemaphoreHandle_t xSemaphore )</pre>
*
* <i>Macro</i> to release a semaphore. The semaphore must have previously been
- * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
* xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().
*
* This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for
@@ -388,7 +454,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
void vATask( void * pvParameters )
{
// Create the semaphore to guard a shared resource.
- vSemaphoreCreateBinary( xSemaphore );
+ xSemaphore = vSemaphoreCreateBinary();
if( xSemaphore != NULL )
{
@@ -438,8 +504,8 @@ typedef QueueHandle_t SemaphoreHandle_t;
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example,
- * if a task successfully 'takes' the same mutex 5 times then the mutex is
- * not available to any other task until it has also 'given' the mutex back
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
* exactly five times.
*
* @param xMutex A handle to the mutex being released, or 'given'. This is the
@@ -481,7 +547,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
- // The mutex has now been 'taken' three times, so is not
+ // The mutex has now been 'taken' three times, so will not be
// available to another task until it has also been given back
// three times. Again it is unlikely that real code would have
// these calls sequentially, it would be more likely that the calls
@@ -504,21 +570,9 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive
* \ingroup Semaphores
*/
-#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
-
-/*
- * xSemaphoreAltGive() is an alternative version of xSemaphoreGive().
- *
- * The source code that implements the alternative (Alt) API is much
- * simpler because it executes everything from within a critical section.
- * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
- * preferred fully featured API too. The fully featured API has more
- * complex code that takes longer to execute, but makes much less use of
- * critical sections. Therefore the alternative API sacrifices interrupt
- * responsiveness to gain execution speed, whereas the fully featured API
- * sacrifices execution speed to ensure better interrupt responsiveness.
- */
-#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+#if( configUSE_RECURSIVE_MUTEXES == 1 )
+ #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
+#endif
/**
* semphr. h
@@ -529,7 +583,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
)</pre>
*
* <i>Macro</i> to release a semaphore. The semaphore must have previously been
- * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().
+ * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting().
*
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
* must not be used with this macro.
@@ -539,7 +593,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @param xSemaphore A handle to the semaphore being released. This is the
* handle returned when the semaphore was created.
*
- * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() sets
+ * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then
@@ -569,7 +623,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
// ...
// We have finished our task. Return to the top of the loop where
- // we block on the semaphore until it is time to execute
+ // we will block on the semaphore until it is time to execute
// again. Note when using the semaphore for synchronisation with an
// ISR in this manner there is no need to 'give' the semaphore back.
}
@@ -620,7 +674,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
)</pre>
*
* <i>Macro</i> to take a semaphore from an ISR. The semaphore must have
- * previously been created with a call to vSemaphoreCreateBinary() or
+ * previously been created with a call to xSemaphoreCreateBinary() or
* xSemaphoreCreateCounting().
*
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
@@ -634,7 +688,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
* @param xSemaphore A handle to the semaphore being taken. This is the
* handle returned when the semaphore was created.
*
- * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() set
+ * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task
* to unblock, and the unblocked task has a priority higher than the currently
* running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then
@@ -649,12 +703,21 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateMutex( void )</pre>
*
- * <i>Macro</i> that implements a mutex semaphore by using the existing queue
- * mechanism.
+ * Creates a new mutex type semaphore instance, and returns a handle by which
+ * the new mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored. If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
*
- * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
* and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
- * xSemaphoreGiveRecursive() macros should not be used.
+ * xSemaphoreGiveRecursive() macros must not be used.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
@@ -662,13 +725,14 @@ typedef QueueHandle_t SemaphoreHandle_t;
*
* Mutex type semaphores cannot be used from within interrupt service routines.
*
- * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
*
- * @return xSemaphore Handle to the created mutex semaphore. Should be of type
- * SemaphoreHandle_t.
+ * @return If the mutex was successfully created then a handle to the created
+ * semaphore is returned. If there was not enough heap to allocate the mutex
+ * data structures then NULL is returned.
*
* Example usage:
<pre>
@@ -687,28 +751,102 @@ typedef QueueHandle_t SemaphoreHandle_t;
}
}
</pre>
- * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre>
+ *
+ * Creates a new mutex type semaphore instance, and returns a handle by which
+ * the new mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored. If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros must not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will be used to hold the mutex's data structure, removing the need for
+ * the memory to be allocated dynamically.
+ *
+ * @return If the mutex was successfully created then a handle to the created
+ * mutex is returned. If pxMutexBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ // A mutex cannot be used before it has been created. xMutexBuffer is
+ // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
+ // attempted.
+ xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
+
+ // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+ // so there is no need to check it.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
* \ingroup Semaphores
*/
-#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre>
*
- * <i>Macro</i> that implements a recursive mutex by using the existing queue
- * mechanism.
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block
+ * of memory, in which the mutex structure is stored. If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
*
* Mutexes created using this macro can be accessed using the
* xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
- * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
*
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example,
- * if a task successfully 'takes' the same mutex 5 times then the mutex is
- * not available to any other task until it has also 'given' the mutex back
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
* exactly five times.
*
* This type of semaphore uses a priority inheritance mechanism so a task
@@ -717,13 +855,13 @@ typedef QueueHandle_t SemaphoreHandle_t;
*
* Mutex type semaphores cannot be used from within interrupt service routines.
*
- * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
*
* @return xSemaphore Handle to the created mutex semaphore. Should be of type
- * SemaphoreHandle_t.
+ * SemaphoreHandle_t.
*
* Example usage:
<pre>
@@ -742,25 +880,115 @@ typedef QueueHandle_t SemaphoreHandle_t;
}
}
</pre>
- * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex
* \ingroup Semaphores
*/
-#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre>
+ *
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block
+ * of memory, in which the mutex structure is stored. If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the recursive mutex's data structure,
+ * removing the need for the memory to be allocated dynamically.
+ *
+ * @return If the recursive mutex was successfully created then a handle to the
+ * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is
+ * returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ // A recursive semaphore cannot be used before it is created. Here a
+ // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
+ // The address of xMutexBuffer is passed into the function, and will hold
+ // the mutexes data structures - so no dynamic memory allocation will be
+ // attempted.
+ xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
+
+ // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+ // so there is no need to check it.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic
+ * \ingroup Semaphores
+ */
+#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre>
*
- * <i>Macro</i> that creates a counting semaphore by using the existing
- * queue mechanism.
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored. If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function. (see
+ * http://www.freertos.org/a00111.html). If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer can
+ * instead optionally provide the memory that will get used by the counting
+ * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting
+ * semaphore to be created without using any dynamic memory allocation.
*
* Counting semaphores are typically used for two things:
*
* 1) Counting events.
*
- * In this usage scenario an event handler 'gives' a semaphore each time
+ * In this usage scenario an event handler will 'give' a semaphore each time
* an event occurs (incrementing the semaphore count value), and a handler
- * task 'takes' a semaphore each time it processes an event
+ * task will 'take' a semaphore each time it processes an event
* (decrementing the semaphore count value). The count value is therefore
* the difference between the number of events that have occurred and the
* number that have been processed. In this case it is desirable for the
@@ -808,7 +1036,94 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
* \ingroup Semaphores
*/
-#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#endif
+
+/**
+ * semphr. h
+ * <pre>SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )</pre>
+ *
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored. If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function. (see
+ * http://www.freertos.org/a00111.html). If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer must
+ * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a
+ * counting semaphore to be created without using any dynamic memory allocation.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ * In this usage scenario an event handler will 'give' a semaphore each time
+ * an event occurs (incrementing the semaphore count value), and a handler
+ * task will 'take' a semaphore each time it processes an event
+ * (decrementing the semaphore count value). The count value is therefore
+ * the difference between the number of events that have occurred and the
+ * number that have been processed. In this case it is desirable for the
+ * initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ * In this usage scenario the count value indicates the number of resources
+ * available. To obtain control of a resource a task must first obtain a
+ * semaphore - decrementing the semaphore count value. When the count value
+ * reaches zero there are no free resources. When a task finishes with the
+ * resource it 'gives' the semaphore back - incrementing the semaphore count
+ * value. In this case it is desirable for the initial count value to be
+ * equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ * created.
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the counting semaphore was successfully created then a handle to
+ * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL
+ * then NULL is returned.
+ *
+ * Example usage:
+ <pre>
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Counting semaphore cannot be used before they have been created. Create
+ // a counting semaphore using xSemaphoreCreateCountingStatic(). The max
+ // value to which the semaphore can count is 10, and the initial value
+ // assigned to the count will be 0. The address of xSemaphoreBuffer is
+ // passed in and will be used to hold the semaphore structure, so no dynamic
+ // memory allocation will be used.
+ xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
+
+ // No memory allocation was attempted so xSemaphore cannot be NULL, so there
+ // is no need to check its value.
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
@@ -839,6 +1154,18 @@ typedef QueueHandle_t SemaphoreHandle_t;
*/
#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
+/**
+ * semphr.h
+ * <pre>UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );</pre>
+ *
+ * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns
+ * its current count value. If the semaphore is a binary semaphore then
+ * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the
+ * semaphore is not available.
+ *
+ */
+#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )
+
#endif /* SEMAPHORE_H */
diff --git a/freertos/Source/include/stdint.readme b/freertos/Source/include/stdint.readme
new file mode 100644
index 0000000..4414c29
--- /dev/null
+++ b/freertos/Source/include/stdint.readme
@@ -0,0 +1,27 @@
+
+#ifndef FREERTOS_STDINT
+#define FREERTOS_STDINT
+
+/*******************************************************************************
+ * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
+ * necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be
+ * built using compilers that do not provide their own stdint.h definition.
+ *
+ * To use this file:
+ *
+ * 1) Copy this file into the directory that contains your FreeRTOSConfig.h
+ * header file, as that directory will already be in the compilers include
+ * path.
+ *
+ * 2) Rename the copied file stdint.h.
+ *
+ */
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef long int32_t;
+typedef unsigned long uint32_t;
+
+#endif /* FREERTOS_STDINT */
diff --git a/freertos/Source/include/task.h b/freertos/Source/include/task.h
index 3e9402f..4c6913f 100644
--- a/freertos/Source/include/task.h
+++ b/freertos/Source/include/task.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -85,10 +85,10 @@ extern "C" {
* MACROS AND DEFINITIONS
*----------------------------------------------------------*/
-#define tskKERNEL_VERSION_NUMBER "V8.2.3"
-#define tskKERNEL_VERSION_MAJOR 8
-#define tskKERNEL_VERSION_MINOR 2
-#define tskKERNEL_VERSION_BUILD 3
+#define tskKERNEL_VERSION_NUMBER "V9.0.0"
+#define tskKERNEL_VERSION_MAJOR 9
+#define tskKERNEL_VERSION_MINOR 0
+#define tskKERNEL_VERSION_BUILD 0
/**
* task. h
@@ -115,7 +115,8 @@ typedef enum
eReady, /* The task being queried is in a read or pending ready list. */
eBlocked, /* The task being queried is in the Blocked state. */
eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */
- eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */
+ eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */
+ eInvalid /* Used as an 'invalid state' value. */
} eTaskState;
/* Actions that can be performed when vTaskNotify() is called. */
@@ -166,24 +167,24 @@ in the system. */
typedef struct xTASK_STATUS
{
TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
- const char *pcTaskName; /* A pointer to the task's name. This value is invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
UBaseType_t xTaskNumber; /* A number unique to the task. */
eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */
UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
- UBaseType_t uxBasePriority; /* The priority to which the task returns if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
+ UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
+ StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */
uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
} TaskStatus_t;
/* Possible return values for eTaskConfirmSleepModeStatus(). */
typedef enum
{
- eAbortSleep = 0, /* A task has been made ready or a context switch was pending since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */
- eStandardSleep, /* Enter a sleep mode that does not last any longer than the expected idle time. */
+ eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */
+ eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */
eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */
} eSleepModeStatus;
-
/**
* Defines the priority used by the idle task. This must not be modified.
*
@@ -276,6 +277,19 @@ is used in assert() statements. */
*
* Create a new task and add it to the list of tasks that are ready to run.
*
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory. xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * See xTaskCreateStatic() for a version that does not use any dynamic memory
+ * allocation.
+ *
* xTaskCreate() can only be used to create a task that has unrestricted
* access to the entire microcontroller memory map. Systems that include MPU
* support can alternatively create an MPU constrained task using
@@ -291,9 +305,9 @@ is used in assert() statements. */
* @param usStackDepth The size of the task stack specified as the number of
* variables the stack can hold - not the number of bytes. For example, if
* the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
- * are allocated for stack storage.
+ * will be allocated for stack storage.
*
- * @param pvParameters Pointer that is used as the parameter for the task
+ * @param pvParameters Pointer that will be used as the parameter for the task
* being created.
*
* @param uxPriority The priority at which the task should run. Systems that
@@ -342,7 +356,131 @@ is used in assert() statements. */
* \defgroup xTaskCreate xTaskCreate
* \ingroup Tasks
*/
-#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint16_t usStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif
+
+/**
+ * task. h
+ *<pre>
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
+ const char * const pcName,
+ uint32_t ulStackDepth,
+ void *pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t *pxStackBuffer,
+ StaticTask_t *pxTaskBuffer );</pre>
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory. xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * @param pvTaskCode Pointer to the task entry function. Tasks
+ * must be implemented to never return (i.e. continuous loop).
+ *
+ * @param pcName A descriptive name for the task. This is mainly used to
+ * facilitate debugging. The maximum length of the string is defined by
+ * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
+ *
+ * @param ulStackDepth The size of the task stack specified as the number of
+ * variables the stack can hold - not the number of bytes. For example, if
+ * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes
+ * will be allocated for stack storage.
+ *
+ * @param pvParameters Pointer that will be used as the parameter for the task
+ * being created.
+ *
+ * @param uxPriority The priority at which the task will run.
+ *
+ * @param pxStackBuffer Must point to a StackType_t array that has at least
+ * ulStackDepth indexes - the array will then be used as the task's stack,
+ * removing the need for the stack to be allocated dynamically.
+ *
+ * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
+ * then be used to hold the task's data structures, removing the need for the
+ * memory to be allocated dynamically.
+ *
+ * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
+ * be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer
+ * are NULL then the task will not be created and
+ * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
+ *
+ * Example usage:
+ <pre>
+
+ // Dimensions the buffer that the task being created will use as its stack.
+ // NOTE: This is the number of words the stack will hold, not the number of
+ // bytes. For example, if each stack item is 32-bits, and this is set to 100,
+ // then 400 bytes (100 * 32-bits) will be allocated.
+ #define STACK_SIZE 200
+
+ // Structure that will hold the TCB of the task being created.
+ StaticTask_t xTaskBuffer;
+
+ // Buffer that the task being created will use as its stack. Note this is
+ // an array of StackType_t variables. The size of StackType_t is dependent on
+ // the RTOS port.
+ StackType_t xStack[ STACK_SIZE ];
+
+ // Function that implements the task being created.
+ void vTaskCode( void * pvParameters )
+ {
+ // The parameter value is expected to be 1 as 1 is passed in the
+ // pvParameters value in the call to xTaskCreateStatic().
+ configASSERT( ( uint32_t ) pvParameters == 1UL );
+
+ for( ;; )
+ {
+ // Task code goes here.
+ }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ TaskHandle_t xHandle = NULL;
+
+ // Create the task without using any dynamic memory allocation.
+ xHandle = xTaskCreateStatic(
+ vTaskCode, // Function that implements the task.
+ "NAME", // Text name for the task.
+ STACK_SIZE, // Stack size in words, not bytes.
+ ( void * ) 1, // Parameter passed into the task.
+ tskIDLE_PRIORITY,// Priority at which the task is created.
+ xStack, // Array to use as the task's stack.
+ &xTaskBuffer ); // Variable to hold the task's data structure.
+
+ // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
+ // been created, and xHandle will be the task's handle. Use the handle
+ // to suspend the task.
+ vTaskSuspend( xHandle );
+ }
+ </pre>
+ * \defgroup xTaskCreateStatic xTaskCreateStatic
+ * \ingroup Tasks
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ 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 ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* task. h
@@ -411,7 +549,9 @@ TaskHandle_t xHandle;
* \defgroup xTaskCreateRestricted xTaskCreateRestricted
* \ingroup Tasks
*/
-#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) )
+#if( portUSING_MPU_WRAPPERS == 1 )
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
/**
* task. h
@@ -469,7 +609,7 @@ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const p
* See the configuration section for more information.
*
* Remove a task from the RTOS real time kernel's management. The task being
- * deleted is removed from all ready, blocked, suspended and event lists.
+ * deleted will be removed from all ready, blocked, suspended and event lists.
*
* NOTE: The idle task is responsible for freeing the kernel allocated
* memory from tasks that have been deleted. It is therefore important that
@@ -481,8 +621,8 @@ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const p
* See the demo application file death.c for sample code that utilises
* vTaskDelete ().
*
- * @param xTask The handle of the task to be deleted. Passing NULL
- * causes the calling task to be deleted.
+ * @param xTask The handle of the task to be deleted. Passing NULL will
+ * cause the calling task to be deleted.
*
* Example usage:
<pre>
@@ -521,10 +661,10 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
*
* vTaskDelay() specifies a time at which the task wishes to unblock relative to
* the time at which vTaskDelay() is called. For example, specifying a block
- * period of 100 ticks causes the task to unblock 100 ticks after
+ * period of 100 ticks will cause the task to unblock 100 ticks after
* vTaskDelay() is called. vTaskDelay() does not therefore provide a good method
* of controlling the frequency of a periodic task as the path taken through the
- * code, as well as other task and interrupt activity, effects the frequency
+ * code, as well as other task and interrupt activity, will effect the frequency
* at which vTaskDelay() gets called and therefore the time at which the task
* next executes. See vTaskDelayUntil() for an alternative API function designed
* to facilitate fixed frequency execution. It does this by specifying an
@@ -564,8 +704,8 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
* Delay a task until a specified time. This function can be used by periodic
* tasks to ensure a constant execution frequency.
*
- * This function differs from vTaskDelay () in one important aspect: vTaskDelay ()
- * causes a task to block for the specified number of ticks from the time vTaskDelay () is
+ * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will
+ * cause a task to block for the specified number of ticks from the time vTaskDelay () is
* called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed
* execution frequency as the time between a task starting to execute and that task
* calling vTaskDelay () may not be fixed [the task may take a different path though the
@@ -584,9 +724,9 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
* prior to its first use (see the example below). Following this the variable is
* automatically updated within vTaskDelayUntil ().
*
- * @param xTimeIncrement The cycle time period. The task is unblocked at
+ * @param xTimeIncrement The cycle time period. The task will be unblocked at
* time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the
- * same xTimeIncrement parameter value causes the task to execute with
+ * same xTimeIncrement parameter value will cause the task to execute with
* a fixed interface period.
*
* Example usage:
@@ -615,6 +755,31 @@ void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xT
/**
* task. h
+ * <pre>BaseType_t xTaskAbortDelay( TaskHandle_t xTask );</pre>
+ *
+ * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
+ * function to be available.
+ *
+ * A task will enter the Blocked state when it is waiting for an event. The
+ * event it is waiting for can be a temporal event (waiting for a time), such
+ * as when vTaskDelay() is called, or an event on an object, such as when
+ * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task
+ * that is in the Blocked state is used in a call to xTaskAbortDelay() then the
+ * task will leave the Blocked state, and return from whichever function call
+ * placed the task into the Blocked state.
+ *
+ * @param xTask The handle of the task to remove from the Blocked state.
+ *
+ * @return If the task referenced by xTask was not in the Blocked state then
+ * pdFAIL is returned. Otherwise pdPASS is returned.
+ *
+ * \defgroup xTaskAbortDelay xTaskAbortDelay
+ * \ingroup TaskCtrl
+ */
+BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
* <pre>UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );</pre>
*
* INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available.
@@ -688,6 +853,62 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/**
* task. h
+ * <pre>void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );</pre>
+ *
+ * configUSE_TRACE_FACILITY must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * Populates a TaskStatus_t structure with information about a task.
+ *
+ * @param xTask Handle of the task being queried. If xTask is NULL then
+ * information will be returned about the calling task.
+ *
+ * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be
+ * filled with information about the task referenced by the handle passed using
+ * the xTask parameter.
+ *
+ * @xGetFreeStackSpace The TaskStatus_t structure contains a member to report
+ * the stack high water mark of the task being queried. Calculating the stack
+ * high water mark takes a relatively long time, and can make the system
+ * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to
+ * allow the high water mark checking to be skipped. The high watermark value
+ * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is
+ * not set to pdFALSE;
+ *
+ * @param eState The TaskStatus_t structure contains a member to report the
+ * state of the task being queried. Obtaining the task state is not as fast as
+ * a simple assignment - so the eState parameter is provided to allow the state
+ * information to be omitted from the TaskStatus_t structure. To obtain state
+ * information then set eState to eInvalid - otherwise the value passed in
+ * eState will be reported as the task state in the TaskStatus_t structure.
+ *
+ * Example usage:
+ <pre>
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+ TaskStatus_t xTaskDetails;
+
+ // Obtain the handle of a task from its name.
+ xHandle = xTaskGetHandle( "Task_Name" );
+
+ // Check the handle is not NULL.
+ configASSERT( xHandle );
+
+ // Use the handle to obtain further information about the task.
+ vTaskGetInfo( xHandle,
+ &xTaskDetails,
+ pdTRUE, // Include the high water mark in xTaskDetails.
+ eInvalid ); // Include the task state in xTaskDetails.
+ }
+ </pre>
+ * \defgroup vTaskGetInfo vTaskGetInfo
+ * \ingroup TaskCtrl
+ */
+void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
* <pre>void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );</pre>
*
* INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available.
@@ -695,13 +916,13 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
*
* Set the priority of any task.
*
- * A context switch occurs before the function returns if the priority
+ * A context switch will occur before the function returns if the priority
* being set is higher than the currently executing task.
*
* @param xTask Handle to the task for which the priority is being set.
* Passing a NULL handle results in the priority of the calling task being set.
*
- * @param uxNewPriority The priority to which the task is set.
+ * @param uxNewPriority The priority to which the task will be set.
*
* Example usage:
<pre>
@@ -735,7 +956,7 @@ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGE
* INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
- * Suspend any task. When suspended a task never gets any microcontroller
+ * Suspend any task. When suspended a task will never get any microcontroller
* processing time, no matter what its priority.
*
* Calls to vTaskSuspend are not accumulative -
@@ -743,7 +964,7 @@ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGE
* call to vTaskResume () to ready the suspended task.
*
* @param xTaskToSuspend Handle to the task being suspended. Passing a NULL
- * handle causes the calling task to be suspended.
+ * handle will cause the calling task to be suspended.
*
* Example usage:
<pre>
@@ -761,7 +982,7 @@ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGE
// ...
- // The created task does not run during this period, unless
+ // The created task will not run during this period, unless
// another task calls vTaskResume( xHandle ).
//...
@@ -789,7 +1010,7 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
* Resumes a suspended task.
*
* A task that has been suspended by one or more calls to vTaskSuspend ()
- * is made available for running again by a single call to
+ * will be made available for running again by a single call to
* vTaskResume ().
*
* @param xTaskToResume Handle to the task being readied.
@@ -810,7 +1031,7 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
// ...
- // The created task does not run during this period, unless
+ // The created task will not run during this period, unless
// another task calls vTaskResume( xHandle ).
//...
@@ -819,7 +1040,7 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
// Resume the suspended task ourselves.
vTaskResume( xHandle );
- // The created task once again gets the microcontroller processing
+ // The created task will once again get microcontroller processing
// time in accordance with its priority within the system.
}
</pre>
@@ -838,7 +1059,7 @@ void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
* An implementation of vTaskResume() that can be called from within an ISR.
*
* A task that has been suspended by one or more calls to vTaskSuspend ()
- * is made available for running again by a single call to
+ * will be made available for running again by a single call to
* xTaskResumeFromISR ().
*
* xTaskResumeFromISR() should not be used to synchronise a task with an
@@ -897,9 +1118,9 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
* NOTE: At the time of writing only the x86 real mode port, which runs on a PC
* in place of DOS, implements this function.
*
- * Stops the real time kernel tick. All created tasks are automatically
- * deleted and multitasking (either preemptive or cooperative)
- * stops. Execution then resumes from the point where vTaskStartScheduler ()
+ * Stops the real time kernel tick. All created tasks will be automatically
+ * deleted and multitasking (either preemptive or cooperative) will
+ * stop. Execution then resumes from the point where vTaskStartScheduler ()
* was called, as if vTaskStartScheduler () had just returned.
*
* See the demo application file main. c in the demo/PC directory for an
@@ -909,8 +1130,8 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
* portable layer (see vPortEndScheduler () in port. c for the PC port). This
* performs hardware specific operations such as stopping the kernel tick.
*
- * vTaskEndScheduler () causes all of the resources allocated by the
- * kernel to be freed - but does not free resources allocated by application
+ * vTaskEndScheduler () will cause all of the resources allocated by the
+ * kernel to be freed - but will not free resources allocated by application
* tasks.
*
* Example usage:
@@ -950,7 +1171,7 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
* task. h
* <pre>void vTaskSuspendAll( void );</pre>
*
- * Suspends the scheduler without disabling interrupts. Context switches does
+ * Suspends the scheduler without disabling interrupts. Context switches will
* not occur while the scheduler is suspended.
*
* After calling vTaskSuspendAll () the calling task will continue to execute
@@ -958,7 +1179,7 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
* made.
*
* API functions that have the potential to cause a context switch (for example,
- * vTaskDelayUntil(), xQueueSend(), and so on.) must not be called while the scheduler
+ * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler
* is suspended.
*
* Example usage:
@@ -982,8 +1203,8 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
// Perform the operation here. There is no need to use critical
// sections as we have all the microcontroller processing time.
- // During this time interrupts still operate and the kernel
- // tick count is maintained.
+ // During this time interrupts will still operate and the kernel
+ // tick count will be maintained.
// ...
@@ -1031,8 +1252,8 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
// Perform the operation here. There is no need to use critical
// sections as we have all the microcontroller processing time.
- // During this time interrupts still operate and the real
- // time kernel tick count is maintained.
+ // During this time interrupts will still operate and the real
+ // time kernel tick count will be maintained.
// ...
@@ -1088,7 +1309,7 @@ TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
*
* @return The number of tasks that the real time kernel is currently managing.
* This includes all ready, blocked and suspended tasks. A task that
- * has been deleted but not yet freed by the idle task is also
+ * has been deleted but not yet freed by the idle task will also be
* included in the count.
*
* \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
@@ -1098,17 +1319,32 @@ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
/**
* task. h
- * <PRE>char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery );</PRE>
+ * <PRE>char *pcTaskGetName( TaskHandle_t xTaskToQuery );</PRE>
*
* @return The text (human readable) name of the task referenced by the handle
* xTaskToQuery. A task can query its own name by either passing in its own
- * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be
- * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available.
+ * handle, or by setting xTaskToQuery to NULL.
*
- * \defgroup pcTaskGetTaskName pcTaskGetTaskName
+ * \defgroup pcTaskGetName pcTaskGetName
* \ingroup TaskUtils
*/
-char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+char *pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * task. h
+ * <PRE>TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );</PRE>
+ *
+ * NOTE: This function takes a relatively long time to complete and should be
+ * used sparingly.
+ *
+ * @return The handle of the task that has the human readable name pcNameToQuery.
+ * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle
+ * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available.
+ *
+ * \defgroup pcTaskGetHandle pcTaskGetHandle
+ * \ingroup TaskUtils
+ */
+TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* task.h
@@ -1132,8 +1368,8 @@ char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/* When using trace macros it is sometimes necessary to include task.h before
-FreeRTOS.h. When this is done TaskHookFunction_t has not yet have been defined,
-so the following two prototypes cause a compilation error. This can be
+FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined,
+so the following two prototypes will cause a compilation error. This can be
fixed by simply guarding against the inclusion of these two prototypes unless
they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration
constant. */
@@ -1224,7 +1460,7 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
*
* @return The number of TaskStatus_t structures that were populated by
* uxTaskGetSystemState(). This should equal the number returned by the
- * uxTaskGetNumberOfTasks() API function, but is zero if the value passed
+ * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed
* in the uxArraySize parameter was too small.
*
* Example usage:
@@ -1265,7 +1501,7 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
for( x = 0; x < uxArraySize; x++ )
{
// What percentage of the total run time has the task used?
- // This is always rounded down to the nearest integer.
+ // This will always be rounded down to the nearest integer.
// ulTotalRunTimeDiv100 has already been divided by 100.
ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
@@ -1300,7 +1536,7 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const
* both be defined as 1 for this function to be available. See the
* configuration section of the FreeRTOS.org website for more information.
*
- * NOTE 1: This function disables interrupts for its duration. It is
+ * NOTE 1: This function will disable interrupts for its duration. It is
* not intended for normal application runtime use but as a debug aid.
*
* Lists all the current tasks, along with their current state and stack
@@ -1330,7 +1566,7 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const
* call to vTaskList().
*
* @param pcWriteBuffer A buffer into which the above mentioned details
- * are written, in ASCII form. This buffer is assumed to be large
+ * will be written, in ASCII form. This buffer is assumed to be large
* enough to contain the generated report. Approximately 40 bytes per
* task should be sufficient.
*
@@ -1351,10 +1587,10 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unquali
* value respectively. The counter should be at least 10 times the frequency of
* the tick count.
*
- * NOTE 1: This function disables interrupts for its duration. It is
+ * NOTE 1: This function will disable interrupts for its duration. It is
* not intended for normal application runtime use but as a debug aid.
*
- * Setting configGENERATE_RUN_TIME_STATS to 1 results in a total
+ * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total
* accumulated execution time being stored for each task. The resolution
* of the accumulated time value depends on the frequency of the timer
* configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro.
@@ -1383,7 +1619,7 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unquali
* to get access to raw stats data, rather than indirectly through a call to
* vTaskGetRunTimeStats().
*
- * @param pcWriteBuffer A buffer into which the execution times are
+ * @param pcWriteBuffer A buffer into which the execution times will be
* written, in ASCII form. This buffer is assumed to be large enough to
* contain the generated report. Approximately 40 bytes per task should
* be sufficient.
@@ -1413,10 +1649,10 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
- * A notification sent to a task remains pending until it is cleared by the
+ * A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was
* already in the Blocked state to wait for a notification when the notification
- * arrives then the task is automatically removed from the Blocked state
+ * arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
@@ -1453,8 +1689,8 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
*
* eSetValueWithoutOverwrite -
* If the task being notified did not already have a notification pending then
- * the task's notification value is set to ulValue and xTaskNotify()
- * returns pdPASS. If the task being notified already had a notification
+ * the task's notification value is set to ulValue and xTaskNotify() will
+ * return pdPASS. If the task being notified already had a notification
* pending then no action is performed and pdFAIL is returned.
*
* eNoAction -
@@ -1499,10 +1735,10 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
- * A notification sent to a task remains pending until it is cleared by the
+ * A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was
* already in the Blocked state to wait for a notification when the notification
- * arrives then the task is automatically removed from the Blocked state
+ * arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
@@ -1539,8 +1775,8 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
*
* eSetValueWithoutOverwrite -
* If the task being notified did not already have a notification pending then
- * the task's notification value is set to ulValue and xTaskNotify()
- * returns pdPASS. If the task being notified already had a notification
+ * the task's notification value is set to ulValue and xTaskNotify() will
+ * return pdPASS. If the task being notified already had a notification
* pending then no action is performed and pdFAIL is returned.
*
* eNoAction -
@@ -1548,7 +1784,7 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
* updated. ulValue is not used and xTaskNotify() always returns pdPASS in
* this case.
*
- * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() sets
+ * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
* task to which the notification was sent to leave the Blocked state, and the
* unblocked task has a priority higher than the currently running task. If
@@ -1587,10 +1823,10 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
- * A notification sent to a task remains pending until it is cleared by the
+ * A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was
* already in the Blocked state to wait for a notification when the notification
- * arrives then the task is automatically removed from the Blocked state
+ * arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
@@ -1601,34 +1837,34 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details.
*
* @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value
- * is cleared in the calling task's notification value before the task
+ * will be cleared in the calling task's notification value before the task
* checks to see if any notifications are pending, and optionally blocks if no
* notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if
- * limits.h is included) or 0xffffffffUL (if limits.h is not included) has
+ * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have
* the effect of resetting the task's notification value to 0. Setting
- * ulBitsToClearOnEntry to 0 leaves the task's notification value unchanged.
+ * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged.
*
* @param ulBitsToClearOnExit If a notification is pending or received before
* the calling task exits the xTaskNotifyWait() function then the task's
* notification value (see the xTaskNotify() API function) is passed out using
* the pulNotificationValue parameter. Then any bits that are set in
- * ulBitsToClearOnExit are cleared in the task's notification value (note
+ * ulBitsToClearOnExit will be cleared in the task's notification value (note
* *pulNotificationValue is set before any bits are cleared). Setting
* ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL
- * (if limits.h is not included) has the effect of resetting the task's
+ * (if limits.h is not included) will have the effect of resetting the task's
* notification value to 0 before the function exits. Setting
- * ulBitsToClearOnExit to 0 leaves the task's notification value unchanged
+ * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged
* when the function exits (in which case the value passed out in
- * pulNotificationValue matches the task's notification value).
+ * pulNotificationValue will match the task's notification value).
*
* @param pulNotificationValue Used to pass the task's notification value out
- * of the function. Note the value passed out is not effected by the
+ * of the function. Note the value passed out will not be effected by the
* clearing of any bits caused by ulBitsToClearOnExit being non-zero.
*
* @param xTicksToWait The maximum amount of time that the task should wait in
* the Blocked state for a notification to be received, should a notification
* not already be pending when xTaskNotifyWait() was called. The task
- * does not consume any processing time while it is in the Blocked state. This
+ * will not consume any processing time while it is in the Blocked state. This
* is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be
* used to convert a time specified in milliseconds to a time specified in
* ticks.
@@ -1729,7 +1965,7 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea
* task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle().
*
- * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() sets
+ * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
* task to which the notification was sent to leave the Blocked state, and the
* unblocked task has a priority higher than the currently running task. If
@@ -1783,8 +2019,8 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri
* the task's notification value to be non-zero. The task does not consume any
* CPU time while it is in the Blocked state.
*
- * Where as xTaskNotifyWait() returns when a notification is pending,
- * ulTaskNotifyTake() returns when the task's notification value is
+ * Where as xTaskNotifyWait() will return when a notification is pending,
+ * ulTaskNotifyTake() will return when the task's notification value is
* not zero.
*
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details.
@@ -1799,7 +2035,7 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri
* @param xTicksToWait The maximum amount of time that the task should wait in
* the Blocked state for the task's notification value to be greater than zero,
* should the count not already be greater than zero when
- * ulTaskNotifyTake() was called. The task does not consume any processing
+ * ulTaskNotifyTake() was called. The task will not consume any processing
* time while it is in the Blocked state. This is specified in kernel ticks,
* the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time
* specified in milliseconds to a time specified in ticks.
@@ -1857,7 +2093,7 @@ BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
*
* Removes the calling task from the ready list and places it both
* on the list of tasks waiting for a particular event, and the
- * list of delayed tasks. The task is removed from both lists
+ * list of delayed tasks. The task will be removed from both lists
* and replaced on the ready list should either the event occur (and
* there be no higher priority tasks waiting on the same event) or
* the delay period expires.
@@ -1894,7 +2130,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte
* indefinitely, whereas vTaskPlaceOnEventList() does.
*
*/
-void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
+void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
/*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
@@ -1905,13 +2141,13 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType
* Removes a task from both the specified event list and the list of blocked
* tasks, and places it on a ready queue.
*
- * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() is called
+ * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called
* if either an event occurs to unblock a task, or the block timeout period
* expires.
*
* xTaskRemoveFromEventList() is used when the event list is in task priority
- * order. It removes the list item from the head of the event list as that
- * has the highest priority owning task of all the tasks on the event list.
+ * order. It removes the list item from the head of the event list as that will
+ * have the highest priority owning task of all the tasks on the event list.
* xTaskRemoveFromUnorderedEventList() is used when the event list is not
* ordered and the event list items hold something other than the owning tasks
* priority. In this case the event list item value is updated to the value
@@ -1931,7 +2167,11 @@ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, cons
* Sets the pointer to the current TCB to the TCB of the highest priority task
* that is ready to run.
*/
+#if defined(__GNUC__)
+void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION __attribute__((used));
+#else
void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION;
+#endif
/*
* THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY
@@ -1980,12 +2220,6 @@ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTIO
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
/*
- * Generic version of the task creation function which is in turn called by the
- * xTaskCreate() and xTaskCreateRestricted() macros.
- */
-BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-
-/*
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
*/
UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
@@ -1999,7 +2233,7 @@ void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVIL
/*
* Only available when configUSE_TICKLESS_IDLE is set to 1.
* If tickless mode is being used, or a low power mode is implemented, then
- * the tick interrupt does not execute during idle periods. When this is the
+ * the tick interrupt will not execute during idle periods. When this is the
* case, the tick count value maintained by the scheduler needs to be kept up
* to date with the actual execution time by being skipped forward by a time
* equal to the idle period.
diff --git a/freertos/Source/include/timers.h b/freertos/Source/include/timers.h
index 423b204..798c955 100644
--- a/freertos/Source/include/timers.h
+++ b/freertos/Source/include/timers.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -135,9 +135,17 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* void * pvTimerID,
* TimerCallbackFunction_t pxCallbackFunction );
*
- * Creates a new software timer instance. This allocates the storage required
- * by the new timer, initialises the new timers internal state, and returns a
- * handle by which the new timer can be referenced.
+ * Creates a new software timer instance, and returns a handle by which the
+ * created software timer can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, software timers use a block
+ * of memory, in which the timer data structure is stored. If a software timer
+ * is created using xTimerCreate() then the required memory is automatically
+ * dynamically allocated inside the xTimerCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a software timer is created using
+ * xTimerCreateStatic() then the application writer must provide the memory that
+ * will get used by the software timer. xTimerCreateStatic() therefore allows a
+ * software timer to be created without using any dynamic memory allocation.
*
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
* xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
@@ -156,9 +164,9 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or
* equal to 1000.
*
- * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer
- * expires repeatedly with a frequency set by the xTimerPeriodInTicks parameter.
- * If uxAutoReload is set to pdFALSE then the timer is a one-shot timer and
+ * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will
+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter.
+ * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and
* enter the dormant state after it expires.
*
* @param pvTimerID An identifier that is assigned to the timer being created.
@@ -185,7 +193,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* // An array to hold a count of the number of times each timer expires.
* int32_t lExpireCounters[ NUM_TIMERS ] = { 0 };
*
- * // Define a callback function that is used by multiple timer instances.
+ * // Define a callback function that will be used by multiple timer instances.
* // The callback function does nothing but count the number of times the
* // associated timer expires, and stop the timer once the timer has expired
* // 10 times.
@@ -217,13 +225,13 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* int32_t x;
*
* // Create then start some timers. Starting the timers before the scheduler
- * // has been started means the timers start running immediately that
+ * // has been started means the timers will start running immediately that
* // the scheduler starts.
* for( x = 0; x < NUM_TIMERS; x++ )
* {
* xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel.
* ( 100 * x ), // The timer period in ticks.
- * pdTRUE, // The timers auto-reload themselves when they expire.
+ * pdTRUE, // The timers will auto-reload themselves when they expire.
* ( void * ) x, // Assign each timer a unique id equal to its array index.
* vTimerCallback // Each timer calls the same callback when it expires.
* );
@@ -248,16 +256,153 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
* // Create tasks here.
* // ...
*
- * // Starting the scheduler starts the timers running as they have already
+ * // Starting the scheduler will start the timers running as they have already
* // been set into the active state.
- * xTaskStartScheduler();
+ * vTaskStartScheduler();
*
* // Should not reach here.
* for( ;; );
* }
* @endverbatim
*/
-TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ TimerHandle_t xTimerCreate( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif
+
+/**
+ * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
+ * TickType_t xTimerPeriodInTicks,
+ * UBaseType_t uxAutoReload,
+ * void * pvTimerID,
+ * TimerCallbackFunction_t pxCallbackFunction,
+ * StaticTimer_t *pxTimerBuffer );
+ *
+ * Creates a new software timer instance, and returns a handle by which the
+ * created software timer can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, software timers use a block
+ * of memory, in which the timer data structure is stored. If a software timer
+ * is created using xTimerCreate() then the required memory is automatically
+ * dynamically allocated inside the xTimerCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a software timer is created using
+ * xTimerCreateStatic() then the application writer must provide the memory that
+ * will get used by the software timer. xTimerCreateStatic() therefore allows a
+ * software timer to be created without using any dynamic memory allocation.
+ *
+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
+ * xTimerChangePeriodFromISR() API functions can all be used to transition a
+ * timer into the active state.
+ *
+ * @param pcTimerName A text name that is assigned to the timer. This is done
+ * purely to assist debugging. The kernel itself only ever references a timer
+ * by its handle, and never by its name.
+ *
+ * @param xTimerPeriodInTicks The timer period. The time is defined in tick
+ * periods so the constant portTICK_PERIOD_MS can be used to convert a time that
+ * has been specified in milliseconds. For example, if the timer must expire
+ * after 100 ticks, then xTimerPeriodInTicks should be set to 100.
+ * Alternatively, if the timer must expire after 500ms, then xPeriod can be set
+ * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or
+ * equal to 1000.
+ *
+ * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will
+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter.
+ * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and
+ * enter the dormant state after it expires.
+ *
+ * @param pvTimerID An identifier that is assigned to the timer being created.
+ * Typically this would be used in the timer callback function to identify which
+ * timer expired when the same callback function is assigned to more than one
+ * timer.
+ *
+ * @param pxCallbackFunction The function to call when the timer expires.
+ * Callback functions must have the prototype defined by TimerCallbackFunction_t,
+ * which is "void vCallbackFunction( TimerHandle_t xTimer );".
+ *
+ * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which
+ * will be then be used to hold the software timer's data structures, removing
+ * the need for the memory to be allocated dynamically.
+ *
+ * @return If the timer is created then a handle to the created timer is
+ * returned. If pxTimerBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ * @verbatim
+ *
+ * // The buffer used to hold the software timer's data structure.
+ * static StaticTimer_t xTimerBuffer;
+ *
+ * // A variable that will be incremented by the software timer's callback
+ * // function.
+ * UBaseType_t uxVariableToIncrement = 0;
+ *
+ * // A software timer callback function that increments a variable passed to
+ * // it when the software timer was created. After the 5th increment the
+ * // callback function stops the software timer.
+ * static void prvTimerCallback( TimerHandle_t xExpiredTimer )
+ * {
+ * UBaseType_t *puxVariableToIncrement;
+ * BaseType_t xReturned;
+ *
+ * // Obtain the address of the variable to increment from the timer ID.
+ * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );
+ *
+ * // Increment the variable to show the timer callback has executed.
+ * ( *puxVariableToIncrement )++;
+ *
+ * // If this callback has executed the required number of times, stop the
+ * // timer.
+ * if( *puxVariableToIncrement == 5 )
+ * {
+ * // This is called from a timer callback so must not block.
+ * xTimerStop( xExpiredTimer, staticDONT_BLOCK );
+ * }
+ * }
+ *
+ *
+ * void main( void )
+ * {
+ * // Create the software time. xTimerCreateStatic() has an extra parameter
+ * // than the normal xTimerCreate() API function. The parameter is a pointer
+ * // to the StaticTimer_t structure that will hold the software timer
+ * // structure. If the parameter is passed as NULL then the structure will be
+ * // allocated dynamically, just as if xTimerCreate() had been called.
+ * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS.
+ * xTimerPeriod, // The period of the timer in ticks.
+ * pdTRUE, // This is an auto-reload timer.
+ * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function
+ * prvTimerCallback, // The function to execute when the timer expires.
+ * &xTimerBuffer ); // The buffer that will hold the software timer structure.
+ *
+ * // The scheduler has not started yet so a block time is not used.
+ * xReturned = xTimerStart( xTimer, 0 );
+ *
+ * // ...
+ * // Create tasks here.
+ * // ...
+ *
+ * // Starting the scheduler will start the timers running as they have already
+ * // been set into the active state.
+ * vTaskStartScheduler();
+ *
+ * // Should not reach here.
+ * for( ;; );
+ * }
+ * @endverbatim
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* void *pvTimerGetTimerID( TimerHandle_t xTimer );
@@ -307,7 +452,7 @@ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION
*
* Queries a timer to see if it is active or dormant.
*
- * A timer is dormant if:
+ * A timer will be dormant if:
* 1) It has been created but not started, or
* 2) It is an expired one-shot timer that has not been restarted.
*
@@ -318,8 +463,8 @@ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION
*
* @param xTimer The timer being queried.
*
- * @return pdFALSE is returned if the timer is dormant. A value other than
- * pdFALSE is returned if the timer is active.
+ * @return pdFALSE will be returned if the timer is dormant. A value other than
+ * pdFALSE will be returned if the timer is active.
*
* Example usage:
* @verbatim
@@ -342,9 +487,6 @@ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/**
* TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
*
- * xTimerGetTimerDaemonTaskHandle() is only available if
- * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h.
- *
* Simply returns the handle of the timer service/daemon task. It it not valid
* to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started.
*/
@@ -367,12 +509,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
*
* Starting a timer ensures the timer is in the active state. If the timer
* is not stopped, deleted, or reset in the mean time, the callback function
- * associated with the timer is called 'n' ticks after xTimerStart() was
+ * associated with the timer will get called 'n' ticks after xTimerStart() was
* called, where 'n' is the timers defined period.
*
* It is valid to call xTimerStart() before the scheduler has been started, but
- * when this is done the timer does not actually start until the scheduler is
- * started, and the timers expiration time is relative to when the scheduler is
+ * when this is done the timer will not actually start until the scheduler is
+ * started, and the timers expiry time will be relative to when the scheduler is
* started, not relative to when xTimerStart() was called.
*
* The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart()
@@ -386,10 +528,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called
* before the scheduler is started.
*
- * @return pdFAIL is returned if the start command could not be sent to
- * the timer command queue even after xTicksToWait ticks had passed. pdPASS
- * is returned if the command was successfully sent to the timer command queue.
- * When the command is actually processed depends on the priority of the
+ * @return pdFAIL will be returned if the start command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system, although the
* timers expiry time is relative to when xTimerStart() is actually called. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
@@ -429,10 +571,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called
* before the scheduler is started.
*
- * @return pdFAIL is returned if the stop command could not be sent to
- * the timer command queue even after xTicksToWait ticks had passed. pdPASS is
- * returned if the command was successfully sent to the timer command queue.
- * When the command is actually processed depends on the priority of the
+ * @return pdFAIL will be returned if the stop command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system. The timer
* service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
@@ -481,10 +623,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* full when xTimerChangePeriod() was called. xTicksToWait is ignored if
* xTimerChangePeriod() is called before the scheduler is started.
*
- * @return pdFAIL is returned if the change period command could not be
+ * @return pdFAIL will be returned if the change period command could not be
* sent to the timer command queue even after xTicksToWait ticks had passed.
- * pdPASS is returned if the command was successfully sent to the timer
- * command queue. When the command is actually processed depends on the
+ * pdPASS will be returned if the command was successfully sent to the timer
+ * command queue. When the command is actually processed will depend on the
* priority of the timer service/daemon task relative to other tasks in the
* system. The timer service/daemon task priority is set by the
* configTIMER_TASK_PRIORITY configuration constant.
@@ -505,8 +647,8 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* }
* else
* {
- * // xTimer is not active, change its period to 500ms. This also
- * // causes the timer to start. Block for a maximum of 100 ticks if the
+ * // xTimer is not active, change its period to 500ms. This will also
+ * // cause the timer to start. Block for a maximum of 100 ticks if the
* // change period command cannot immediately be sent to the timer
* // command queue.
* if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS )
@@ -548,10 +690,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete()
* is called before the scheduler is started.
*
- * @return pdFAIL is returned if the delete command could not be sent to
- * the timer command queue even after xTicksToWait ticks had passed. pdPASS
- * is returned if the command was successfully sent to the timer command queue.
- * When the command is actually processed depends on the priority of the
+ * @return pdFAIL will be returned if the delete command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system. The timer
* service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
@@ -574,19 +716,19 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
*
* xTimerReset() re-starts a timer that was previously created using the
* xTimerCreate() API function. If the timer had already been started and was
- * already in the active state, then xTimerReset() causes the timer to
+ * already in the active state, then xTimerReset() will cause the timer to
* re-evaluate its expiry time so that it is relative to when xTimerReset() was
* called. If the timer was in the dormant state then xTimerReset() has
* equivalent functionality to the xTimerStart() API function.
*
* Resetting a timer ensures the timer is in the active state. If the timer
* is not stopped, deleted, or reset in the mean time, the callback function
- * associated with the timer is called 'n' ticks after xTimerReset() was
+ * associated with the timer will get called 'n' ticks after xTimerReset() was
* called, where 'n' is the timers defined period.
*
* It is valid to call xTimerReset() before the scheduler has been started, but
- * when this is done the timer does not actually start until the scheduler is
- * started, and the timers expiration time is relative to when the scheduler is
+ * when this is done the timer will not actually start until the scheduler is
+ * started, and the timers expiry time will be relative to when the scheduler is
* started, not relative to when xTimerReset() was called.
*
* The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset()
@@ -600,10 +742,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called
* before the scheduler is started.
*
- * @return pdFAIL is returned if the reset command could not be sent to
- * the timer command queue even after xTicksToWait ticks had passed. pdPASS
- * is returned if the command was successfully sent to the timer command queue.
- * When the command is actually processed depends on the priority of the
+ * @return pdFAIL will be returned if the reset command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
* timer service/daemon task relative to other tasks in the system, although the
* timers expiry time is relative to when xTimerStart() is actually called. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
@@ -675,9 +817,9 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* // Create tasks here.
* // ...
*
- * // Starting the scheduler starts the timer running as it has already
+ * // Starting the scheduler will start the timer running as it has already
* // been set into the active state.
- * xTaskStartScheduler();
+ * vTaskStartScheduler();
*
* // Should not reach here.
* for( ;; );
@@ -702,15 +844,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* task out of the Blocked state. If calling xTimerStartFromISR() causes the
* timer service/daemon task to leave the Blocked state, and the timer service/
* daemon task has a priority equal to or greater than the currently executing
- * task (the task that was interrupted), then *pxHigherPriorityTaskWoken
- * gets set to pdTRUE internally within the xTimerStartFromISR() function. If
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerStartFromISR() function. If
* xTimerStartFromISR() sets this value to pdTRUE then a context switch should
* be performed before the interrupt exits.
*
- * @return pdFAIL is returned if the start command could not be sent to
- * the timer command queue. pdPASS is returned if the command was
+ * @return pdFAIL will be returned if the start command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
* successfully sent to the timer command queue. When the command is actually
- * processed depends on the priority of the timer service/daemon task
+ * processed will depend on the priority of the timer service/daemon task
* relative to other tasks in the system, although the timers expiry time is
* relative to when xTimerStartFromISR() is actually called. The timer
* service/daemon task priority is set by the configTIMER_TASK_PRIORITY
@@ -788,15 +930,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* task out of the Blocked state. If calling xTimerStopFromISR() causes the
* timer service/daemon task to leave the Blocked state, and the timer service/
* daemon task has a priority equal to or greater than the currently executing
- * task (the task that was interrupted), then *pxHigherPriorityTaskWoken
- * is set to pdTRUE internally within the xTimerStopFromISR() function. If
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerStopFromISR() function. If
* xTimerStopFromISR() sets this value to pdTRUE then a context switch should
* be performed before the interrupt exits.
*
- * @return pdFAIL is returned if the stop command could not be sent to
- * the timer command queue. pdPASS is returned if the command was
+ * @return pdFAIL will be returned if the stop command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
* successfully sent to the timer command queue. When the command is actually
- * processed depends on the priority of the timer service/daemon task
+ * processed will depend on the priority of the timer service/daemon task
* relative to other tasks in the system. The timer service/daemon task
* priority is set by the configTIMER_TASK_PRIORITY configuration constant.
*
@@ -861,15 +1003,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* causes the timer service/daemon task to leave the Blocked state, and the
* timer service/daemon task has a priority equal to or greater than the
* currently executing task (the task that was interrupted), then
- * *pxHigherPriorityTaskWoken is set to pdTRUE internally within the
+ * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the
* xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets
* this value to pdTRUE then a context switch should be performed before the
* interrupt exits.
*
- * @return pdFAIL is returned if the command to change the timers period
- * could not be sent to the timer command queue. pdPASS is returned if the
+ * @return pdFAIL will be returned if the command to change the timers period
+ * could not be sent to the timer command queue. pdPASS will be returned if the
* command was successfully sent to the timer command queue. When the command
- * is actually processed depends on the priority of the timer service/daemon
+ * is actually processed will depend on the priority of the timer service/daemon
* task relative to other tasks in the system. The timer service/daemon task
* priority is set by the configTIMER_TASK_PRIORITY configuration constant.
*
@@ -925,15 +1067,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* task out of the Blocked state. If calling xTimerResetFromISR() causes the
* timer service/daemon task to leave the Blocked state, and the timer service/
* daemon task has a priority equal to or greater than the currently executing
- * task (the task that was interrupted), then *pxHigherPriorityTaskWoken
- * is set to pdTRUE internally within the xTimerResetFromISR() function. If
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerResetFromISR() function. If
* xTimerResetFromISR() sets this value to pdTRUE then a context switch should
* be performed before the interrupt exits.
*
- * @return pdFAIL is returned if the reset command could not be sent to
- * the timer command queue. pdPASS is returned if the command was
+ * @return pdFAIL will be returned if the reset command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
* successfully sent to the timer command queue. When the command is actually
- * processed depends on the priority of the timer service/daemon task
+ * processed will depend on the priority of the timer service/daemon task
* relative to other tasks in the system, although the timers expiry time is
* relative to when xTimerResetFromISR() is actually called. The timer service/daemon
* task priority is set by the configTIMER_TASK_PRIORITY configuration constant.
@@ -1013,7 +1155,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* to the RTOS daemon task.
*
* A mechanism is provided that allows the interrupt to return directly to the
- * task that is subsequently execute the pending callback function. This
+ * task that will subsequently execute the pended callback function. This
* allows the callback function to execute contiguously in time with the
* interrupt - just as if the callback had executed in the interrupt itself.
*
@@ -1029,11 +1171,11 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* @param ulParameter2 The value of the callback function's second parameter.
*
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
- * results in a message being sent to the timer daemon task. If the
+ * will result in a message being sent to the timer daemon task. If the
* priority of the timer daemon task (which is set using
* configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of
* the currently running task (the task the interrupt interrupted) then
- * *pxHigherPriorityTaskWoken is set to pdTRUE within
+ * *pxHigherPriorityTaskWoken will be set to pdTRUE within
* xTimerPendFunctionCallFromISR(), indicating that a context switch should be
* requested before the interrupt exits. For that reason
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
@@ -1045,7 +1187,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* Example usage:
* @verbatim
*
- * // The callback function that executes in the context of the daemon task.
+ * // The callback function that will execute in the context of the daemon task.
* // Note callback functions must all use this same prototype.
* void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 )
* {
@@ -1075,8 +1217,8 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken );
*
* // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
- * // switch should be requested. The macro used is port specific and
- * // is either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - See
+ * // switch should be requested. The macro used is port specific and will
+ * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
* // the documentation page for the port being used.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
*
@@ -1107,7 +1249,7 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void
*
* @param ulParameter2 The value of the callback function's second parameter.
*
- * @param xTicksToWait Calling this function results in a message being
+ * @param xTicksToWait Calling this function will result in a message being
* sent to the timer daemon task on a queue. xTicksToWait is the amount of
* time the calling task should remain in the Blocked state (so not using any
* processing time) for space to become available on the timer queue if the
@@ -1120,7 +1262,7 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
- * const char * const pcTimerGetTimerName( TimerHandle_t xTimer );
+ * const char * const pcTimerGetName( TimerHandle_t xTimer );
*
* Returns the name that was assigned to a timer when the timer was created.
*
@@ -1128,7 +1270,33 @@ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvPar
*
* @return The name assigned to the timer specified by the xTimer parameter.
*/
-const char * pcTimerGetTimerName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
+ *
+ * Returns the period of a timer.
+ *
+ * @param xTimer The handle of the timer being queried.
+ *
+ * @return The period of the timer in ticks.
+ */
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
+*
+* Returns the time in ticks at which the timer will expire. If this is less
+* than the current tick count then the expiry time has overflowed from the
+* current time.
+*
+* @param xTimer The handle of the timer being queried.
+*
+* @return If the timer is running then the time in ticks at which the timer
+* will next expire is returned. If the timer is not running then the return
+* value is undefined.
+*/
+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/*
* Functions beyond this part are not part of the public API and are intended
diff --git a/freertos/Source/list.c b/freertos/Source/list.c
index ce20cd8..5e207c1 100644
--- a/freertos/Source/list.c
+++ b/freertos/Source/list.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
diff --git a/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_generic.h b/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_generic.h
new file mode 100644
index 0000000..6579370
--- /dev/null
+++ b/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_generic.h
@@ -0,0 +1,122 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/* This file was separated prom original port.c by SDK team to enable efective tickless idle mode implementation. */
+
+#ifndef FSL_TICKLESS_GENERIC_H
+#define FSL_TICKLESS_GENERIC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef configSYSTICK_CLOCK_HZ
+ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
+ /* Ensure the SysTick is clocked at the same frequency as the core. */
+ #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
+#else
+ /* The way the SysTick is clocked is not modified in case it is not the same
+ as the core. */
+ #define portNVIC_SYSTICK_CLK_BIT ( 0 )
+#endif
+
+/* Constants required to manipulate the core. Registers first... */
+#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
+
+/* ...then bits in the registers. */
+#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
+#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
+
+/* The LPTMR is a 16-bit counter. */
+#define portMAX_16_BIT_NUMBER ( 0xffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+occurred while the SysTick counter is stopped during tickless idle
+calculations. */
+#define portMISSED_COUNTS_FACTOR ( 45UL )
+
+/*
+ * Setup the timer to generate the tick interrupts.
+ */
+void vPortSetupTimerInterrupt( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FSL_TICKLESS_GENERIC_H */
diff --git a/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_lptmr.c b/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_lptmr.c
new file mode 100644
index 0000000..c23eaaa
--- /dev/null
+++ b/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_lptmr.c
@@ -0,0 +1,260 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+#include "FreeRTOS.h"
+#include "task.h"
+#include "fsl_tickless_generic.h"
+
+#if configUSE_TICKLESS_IDLE == 1
+#include "fsl_lptmr.h"
+#endif
+
+extern uint32_t SystemCoreClock; /* in Kinetis SDK, this contains the system core clock speed */
+
+/*
+ * LPT timer base address and interrupt number
+ */
+
+#if configUSE_TICKLESS_IDLE == 1
+ extern LPTMR_Type *vPortGetLptrmBase(void);
+ extern IRQn_Type vPortGetLptmrIrqn(void);
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The number of LPTIMER increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static uint32_t ulLPTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The flag of LPTIMER is occurs or not.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static volatile bool ulLPTimerInterruptFired = false;
+#endif /* configUSE_TICKLESS_IDLE */
+
+#if configUSE_TICKLESS_IDLE == 1
+void vPortLptmrIsr(void)
+{
+ ulLPTimerInterruptFired = true;
+ LPTMR_ClearStatusFlags(vPortGetLptrmBase(), kLPTMR_TimerCompareFlag);
+}
+
+void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+{
+ uint32_t ulReloadValue, ulCompleteTickPeriods;
+ TickType_t xModifiableIdleTime;
+ LPTMR_Type *pxLptmrBase;
+
+ pxLptmrBase = vPortGetLptrmBase();
+ if (pxLptmrBase == 0) return;
+ /* Make sure the SysTick reload value does not overflow the counter. */
+ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+ {
+ xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+ }
+ if (xExpectedIdleTime == 0) return;
+ /* Calculate the reload value required to wait xExpectedIdleTime
+ tick periods. -1 is used because this code will execute part way
+ through one of the tick periods. */
+ ulReloadValue = LPTMR_GetCurrentTimerCount(pxLptmrBase) + ( ulLPTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+
+ /* Stop the LPTMR and systick momentarily. The time the LPTMR and systick is stopped for
+ is accounted for as best it can be, but using the tickless mode will
+ inevitably result in some tiny drift of the time maintained by the
+ kernel with respect to calendar time. */
+ LPTMR_StopTimer(pxLptmrBase);
+ portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+ /* Enter a critical section but don't use the taskENTER_CRITICAL()
+ method as that will mask interrupts that should exit sleep mode. */
+ __asm volatile( "cpsid i" );
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* If a context switch is pending or a task is waiting for the scheduler
+ to be unsuspended then abandon the low power entry. */
+ if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+ {
+ /* Restart from whatever is left in the count register to complete
+ this tick period. */
+ portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+ /* Restart SysTick. */
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+ /* Reset the reload register to the value required for normal tick
+ periods. */
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Re-enable interrupts - see comments above the cpsid instruction()
+ above. */
+ __asm volatile( "cpsie i" );
+ }
+ else
+ {
+ /* Set the new reload value. */
+ LPTMR_SetTimerPeriod(pxLptmrBase, ulReloadValue);
+
+ /* Enable LPTMR. */
+ LPTMR_StartTimer(pxLptmrBase);
+
+
+ /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
+ set its parameter to 0 to indicate that its implementation contains
+ its own wait for interrupt or wait for event instruction, and so wfi
+ should not be executed again. However, the original expected idle
+ time variable must remain unmodified, so a copy is taken. */
+ xModifiableIdleTime = xExpectedIdleTime;
+ configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+ if( xModifiableIdleTime > 0 )
+ {
+ __asm volatile( "dsb" );
+ __asm volatile( "wfi" );
+ __asm volatile( "isb" );
+ }
+ configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+ ulLPTimerInterruptFired = false;
+
+ /* Re-enable interrupts - see comments above the cpsid instruction()
+ above. */
+ __asm volatile( "cpsie i" );
+ __NOP();
+ if( ulLPTimerInterruptFired )
+ {
+ /* The tick interrupt handler will already have pended the tick
+ processing in the kernel. As the pending tick will be
+ processed as soon as this function exits, the tick value
+ maintained by the tick is stepped forward by one less than the
+ time spent waiting. */
+ ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+ ulLPTimerInterruptFired = false;
+ }
+ else
+ {
+ /* Something other than the tick interrupt ended the sleep.
+ Work out how long the sleep lasted rounded to complete tick
+ periods (not the ulReload value which accounted for part
+ ticks). */
+ ulCompleteTickPeriods = LPTMR_GetCurrentTimerCount(pxLptmrBase)/ulLPTimerCountsForOneTick;
+ }
+
+ /* Stop LPTMR when CPU waked up then set portNVIC_SYSTICK_LOAD_REG back to its standard
+ value. The critical section is used to ensure the tick interrupt
+ can only execute once in the case that the reload register is near
+ zero. */
+ LPTMR_StopTimer(pxLptmrBase);
+ portENTER_CRITICAL();
+ {
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+ }
+ portEXIT_CRITICAL();
+ }
+}
+#endif /* #if configUSE_TICKLESS_IDLE */
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+void vPortSetupTimerInterrupt( void )
+{
+ /* Calculate the constants required to configure the tick interrupt. */
+ #if( configUSE_TICKLESS_IDLE == 1 )
+ {
+ ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+ ulLPTimerCountsForOneTick = ( configLPTMR_CLOCK_HZ / configTICK_RATE_HZ );
+ xMaximumPossibleSuppressedTicks = portMAX_16_BIT_NUMBER / ulLPTimerCountsForOneTick;
+ NVIC_EnableIRQ(vPortGetLptmrIrqn());
+ }
+ #endif /* configUSE_TICKLESS_IDLE */
+
+ /* Configure SysTick to interrupt at the requested rate. */
+ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+}
diff --git a/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_systick.c b/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_systick.c
new file mode 100644
index 0000000..c75613d
--- /dev/null
+++ b/freertos/Source/portable/GCC/ARM_CM3/fsl_tickless_systick.c
@@ -0,0 +1,273 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+#include "FreeRTOS.h"
+#include "task.h"
+#include "fsl_tickless_generic.h"
+
+extern uint32_t SystemCoreClock; /* in Kinetis SDK, this contains the system core clock speed */
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if configUSE_TICKLESS_IDLE == 1
+ static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+
+/*-----------------------------------------------------------*/
+#if configUSE_TICKLESS_IDLE == 1
+
+ __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+ {
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ TickType_t xModifiableIdleTime;
+
+ /* Make sure the SysTick reload value does not overflow the counter. */
+ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+ {
+ xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+ }
+ if (xExpectedIdleTime == 0) return;
+ /* Stop the SysTick momentarily. The time the SysTick is stopped for
+ is accounted for as best it can be, but using the tickless mode will
+ inevitably result in some tiny drift of the time maintained by the
+ kernel with respect to calendar time. */
+ portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+ /* Calculate the reload value required to wait xExpectedIdleTime
+ tick periods. -1 is used because this code will execute part way
+ through one of the tick periods. */
+ ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+ if( ulReloadValue > ulStoppedTimerCompensation )
+ {
+ ulReloadValue -= ulStoppedTimerCompensation;
+ }
+
+ /* Enter a critical section but don't use the taskENTER_CRITICAL()
+ method as that will mask interrupts that should exit sleep mode. */
+ __asm volatile( "cpsid i" );
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* If a context switch is pending or a task is waiting for the scheduler
+ to be unsuspended then abandon the low power entry. */
+ if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+ {
+ /* Restart from whatever is left in the count register to complete
+ this tick period. */
+ portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+ /* Restart SysTick. */
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+ /* Reset the reload register to the value required for normal tick
+ periods. */
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Re-enable interrupts - see comments above the cpsid instruction()
+ above. */
+ __asm volatile( "cpsie i" );
+ }
+ else
+ {
+ /* Set the new reload value. */
+ portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+ /* Clear the SysTick count flag and set the count value back to
+ zero. */
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+ /* Restart SysTick. */
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+ /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
+ set its parameter to 0 to indicate that its implementation contains
+ its own wait for interrupt or wait for event instruction, and so wfi
+ should not be executed again. However, the original expected idle
+ time variable must remain unmodified, so a copy is taken. */
+ xModifiableIdleTime = xExpectedIdleTime;
+ configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+ if( xModifiableIdleTime > 0 )
+ {
+ __asm volatile( "dsb" );
+ __asm volatile( "wfi" );
+ __asm volatile( "isb" );
+ }
+ configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+ /* Stop SysTick. Again, the time the SysTick is stopped for is
+ accounted for as best it can be, but using the tickless mode will
+ inevitably result in some tiny drift of the time maintained by the
+ kernel with respect to calendar time. */
+ ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
+ portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
+
+ /* Re-enable interrupts - see comments above the cpsid instruction()
+ above. */
+ __asm volatile( "cpsie i" );
+
+ if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ {
+ uint32_t ulCalculatedLoadValue;
+
+ /* The tick interrupt has already executed, and the SysTick
+ count reloaded with ulReloadValue. Reset the
+ portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
+ period. */
+ ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+ /* Don't allow a tiny value, or values that have somehow
+ underflowed because the post sleep hook did something
+ that took too long. */
+ if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+ {
+ ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+ }
+
+ portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+ /* The tick interrupt handler will already have pended the tick
+ processing in the kernel. As the pending tick will be
+ processed as soon as this function exits, the tick value
+ maintained by the tick is stepped forward by one less than the
+ time spent waiting. */
+ ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+ }
+ else
+ {
+ /* Something other than the tick interrupt ended the sleep.
+ Work out how long the sleep lasted rounded to complete tick
+ periods (not the ulReload value which accounted for part
+ ticks). */
+ ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+ /* How many complete tick periods passed while the processor
+ was waiting? */
+ ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+ /* The reload value is set to whatever fraction of a single tick
+ period remains. */
+ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+ }
+
+ /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
+ again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
+ value. The critical section is used to ensure the tick interrupt
+ can only execute once in the case that the reload register is near
+ zero. */
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+ portENTER_CRITICAL();
+ {
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+ }
+ portEXIT_CRITICAL();
+ }
+ }
+
+#endif /* #if configUSE_TICKLESS_IDLE */
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
+{
+ /* Calculate the constants required to configure the tick interrupt. */
+ #if configUSE_TICKLESS_IDLE == 1
+ {
+ ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+ xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+ ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
+ }
+ #endif /* configUSE_TICKLESS_IDLE */
+
+ /* Configure SysTick to interrupt at the requested rate. */
+ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+}
diff --git a/freertos/Source/portable/GCC/ARM_CM3/port.c b/freertos/Source/portable/GCC/ARM_CM3/port.c
index 1d5ed30..34d33d3 100644
--- a/freertos/Source/portable/GCC/ARM_CM3/port.c
+++ b/freertos/Source/portable/GCC/ARM_CM3/port.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -74,10 +74,7 @@
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
-
-#if configSYSTICK_USE_LOW_POWER_TIMER
-#include "fsl_lptmr.h"
-#endif
+#include "fsl_tickless_generic.h"
extern uint32_t SystemCoreClock; /* in Kinetis SDK, this contains the system core clock speed */
@@ -88,27 +85,7 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#define configKERNEL_INTERRUPT_PRIORITY 255
#endif
-#ifndef configSYSTICK_CLOCK_HZ
- #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
- /* Ensure the SysTick is clocked at the same frequency as the core. */
- #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
-#else
- /* The way the SysTick is clocked is not modified in case it is not the same
- as the core. */
- #define portNVIC_SYSTICK_CLK_BIT ( 0 )
-#endif
-/* Constants required to manipulate the core. Registers first... */
-#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
-#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
-#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
-#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
-/* ...then bits in the registers. */
-#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
-#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
-#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
-#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
-#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
@@ -129,17 +106,11 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000UL )
-/* The systick is a 24-bit counter. */
-#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
-
-/* The LPTMR is a 16-bit counter. */
-#define portMAX_16_BIT_NUMBER ( 0xffffUL )
-/* A fiddle factor to estimate the number of SysTick counts that would have
-occurred while the SysTick counter is stopped during tickless idle
-calculations. */
-#define portMISSED_COUNTS_FACTOR ( 45UL )
+/* For strict compliance with the Cortex-M spec the task start address should
+have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
+#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the
@@ -155,13 +126,6 @@ variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
- * Setup the timer to generate the tick interrupts. The implementation in this
- * file is weak to allow application writers to change the timer used to
- * generate the tick interrupt.
- */
-void vPortSetupTimerInterrupt( void );
-
-/*
* Exception handlers.
*/
void xPortPendSVHandler( void ) __attribute__ (( naked ));
@@ -178,56 +142,9 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
*/
static void prvTaskExitError( void );
-/*
- * LPT timer base address and interrupt number
- */
-
-#if configSYSTICK_USE_LOW_POWER_TIMER == 1
- extern LPTMR_Type *vPortGetLptrmBase(void);
- extern IRQn_Type vPortGetLptmrIrqn(void);
-#endif /* configSYSTICK_USE_LOW_POWER_TIMER */
-
/*-----------------------------------------------------------*/
/*
- * The number of SysTick increments that make up one tick period.
- */
-#if configUSE_TICKLESS_IDLE == 1
- static uint32_t ulTimerCountsForOneTick = 0;
-#endif /* configUSE_TICKLESS_IDLE */
-
-/*
- * The number of SysTick increments that make up one tick period.
- */
-#if configSYSTICK_USE_LOW_POWER_TIMER == 1
- static uint32_t ulLPTimerCountsForOneTick = 0;
-#endif /* configSYSTICK_USE_LOW_POWER_TIMER */
-
-/*
- * The flag of LPTIEMR is occurs or not.
- */
-#if configSYSTICK_USE_LOW_POWER_TIMER == 1
- static volatile bool ulLPTimerInterruptFired = false;
-#endif /* configSYSTICK_USE_LOW_POWER_TIMER */
-
-
-/*
- * The maximum number of tick periods that can be suppressed is limited by the
- * 24 bit resolution of the SysTick timer.
- */
-#if configUSE_TICKLESS_IDLE == 1
- static uint32_t xMaximumPossibleSuppressedTicks = 0;
-#endif /* configUSE_TICKLESS_IDLE */
-
-/*
- * Compensate for the CPU cycles that pass while the SysTick is stopped (low
- * power functionality only.
- */
-#if configUSE_TICKLESS_IDLE == 1
- static uint32_t ulStoppedTimerCompensation = 0;
-#endif /* configUSE_TICKLESS_IDLE */
-
-/*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
@@ -250,7 +167,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
+ *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
@@ -289,7 +206,7 @@ void vPortSVCHandler( void )
" orr r14, #0xd \n"
" bx r14 \n"
" \n"
- " .align 2 \n"
+ " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
);
}
@@ -398,27 +315,13 @@ void vPortEndScheduler( void )
}
/*-----------------------------------------------------------*/
-void vPortYield( void )
-{
- /* Set a PendSV to request a context switch. */
- portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
-
- /* Barriers are normally not required but do ensure the code is completely
- within the specified behaviour for the architecture. */
- __asm volatile( "dsb" );
- __asm volatile( "isb" );
-}
-/*-----------------------------------------------------------*/
-
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
- __asm volatile( "dsb" );
- __asm volatile( "isb" );
-
+
/* This is not the interrupt safe version of the enter critical function so
- assert() if it is being called from an interrupt context. Only API
+ assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
@@ -440,37 +343,6 @@ void vPortExitCritical( void )
}
/*-----------------------------------------------------------*/
-__attribute__(( naked )) uint32_t ulPortSetInterruptMask( void )
-{
- __asm volatile \
- ( \
- " mrs r0, basepri \n" \
- " mov r1, %0 \n" \
- " msr basepri, r1 \n" \
- " bx lr \n" \
- :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \
- );
-
- /* This return will not be reached but is necessary to prevent compiler
- warnings. */
- return 0;
-}
-/*-----------------------------------------------------------*/
-
-__attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
-{
- __asm volatile \
- ( \
- " msr basepri, r0 \n" \
- " bx lr \n" \
- :::"r0" \
- );
-
- /* Just to avoid compiler warnings. */
- ( void ) ulNewMaskValue;
-}
-/*-----------------------------------------------------------*/
-
void xPortPendSVHandler( void )
{
/* This is a naked function. */
@@ -501,7 +373,7 @@ void xPortPendSVHandler( void )
" isb \n"
" bx r14 \n"
" \n"
- " .align 2 \n"
+ " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
@@ -514,7 +386,7 @@ void xPortSysTickHandler( void )
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known. */
- ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+ portDISABLE_INTERRUPTS();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
@@ -524,316 +396,8 @@ void xPortSysTickHandler( void )
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+ portENABLE_INTERRUPTS();
}
-/*-----------------------------------------------------------*/
-
-#if configUSE_TICKLESS_IDLE == 1
-#if configSYSTICK_USE_LOW_POWER_TIMER == 1
-
- void vPortLptmrIsr(void)
- {
- ulLPTimerInterruptFired = true;
- LPTMR_ClearStatusFlags(vPortGetLptrmBase(), kLPTMR_TimerCompareFlag);
-
- }
-
- __attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
- {
- uint32_t ulReloadValue, ulCompleteTickPeriods;
- TickType_t xModifiableIdleTime;
- LPTMR_Type *pxLptmrBase;
-
- pxLptmrBase = vPortGetLptrmBase();
- if (pxLptmrBase == 0) return;
- /* Make sure the SysTick reload value does not overflow the counter. */
- if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
- {
- xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
- }
- if (xExpectedIdleTime == 0) return;
- /* Calculate the reload value required to wait xExpectedIdleTime
- tick periods. -1 is used because this code will execute part way
- through one of the tick periods. */
- ulReloadValue = LPTMR_GetCurrentTimerCount(pxLptmrBase) + ( ulLPTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
- if( ulReloadValue > ulStoppedTimerCompensation )
- {
- ulReloadValue -= ulStoppedTimerCompensation;
- }
-
- /* Stop the LPTMR and systick momentarily. The time the LPTMR and systick is stopped for
- is accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- LPTMR_StopTimer(pxLptmrBase);
- portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
-
- /* Enter a critical section but don't use the taskENTER_CRITICAL()
- method as that will mask interrupts that should exit sleep mode. */
- __asm volatile( "cpsid i" );
-
- /* If a context switch is pending or a task is waiting for the scheduler
- to be unsuspended then abandon the low power entry. */
- if( eTaskConfirmSleepModeStatus() == eAbortSleep )
- {
- /* Restart from whatever is left in the count register to complete
- this tick period. */
- portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
-
- /* Restart SysTick. */
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
-
- /* Reset the reload register to the value required for normal tick
- periods. */
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
-
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
- __asm volatile( "cpsie i" );
- }
- else
- {
- /* Set the new reload value. */
- LPTMR_SetTimerPeriod(pxLptmrBase, ulReloadValue);
-
- /* Enable LPTMR. */
- LPTMR_StartTimer(pxLptmrBase);
-
- /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
- set its parameter to 0 to indicate that its implementation contains
- its own wait for interrupt or wait for event instruction, and so wfi
- should not be executed again. However, the original expected idle
- time variable must remain unmodified, so a copy is taken. */
- xModifiableIdleTime = xExpectedIdleTime;
- configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
- if( xModifiableIdleTime > 0 )
- {
- __asm volatile( "dsb" );
- __asm volatile( "wfi" );
- __asm volatile( "isb" );
- }
- configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
-
- ulLPTimerInterruptFired = false;
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
- __asm volatile( "cpsie i" );
- __NOP();
- if( ulLPTimerInterruptFired )
- {
-
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
- ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
- ulLPTimerInterruptFired = false;
- }
- else
- {
- /* Something other than the tick interrupt ended the sleep.
- Work out how long the sleep lasted rounded to complete tick
- periods (not the ulReload value which accounted for part
- ticks). */
- ulCompleteTickPeriods = LPTMR_GetCurrentTimerCount(pxLptmrBase);
-
- }
-
- /* Stop LPTMR when CPU waked up then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
- LPTMR_StopTimer(pxLptmrBase);
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
- }
- }
-#else /* configSYSTICK_USE_LOW_POWER_TIMER == 1 */
- __attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
- {
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
- TickType_t xModifiableIdleTime;
-
- /* Make sure the SysTick reload value does not overflow the counter. */
- if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
- {
- xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
- }
- if (xExpectedIdleTime == 0) return;
- /* Stop the SysTick momentarily. The time the SysTick is stopped for
- is accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
-
- /* Calculate the reload value required to wait xExpectedIdleTime
- tick periods. -1 is used because this code will execute part way
- through one of the tick periods. */
- ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
- if( ulReloadValue > ulStoppedTimerCompensation )
- {
- ulReloadValue -= ulStoppedTimerCompensation;
- }
-
- /* Enter a critical section but don't use the taskENTER_CRITICAL()
- method as that will mask interrupts that should exit sleep mode. */
- __asm volatile( "cpsid i" );
-
- /* If a context switch is pending or a task is waiting for the scheduler
- to be unsuspended then abandon the low power entry. */
- if( eTaskConfirmSleepModeStatus() == eAbortSleep )
- {
- /* Restart from whatever is left in the count register to complete
- this tick period. */
- portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
-
- /* Restart SysTick. */
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
-
- /* Reset the reload register to the value required for normal tick
- periods. */
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
-
- /* Re-enable interrupts - see comments above the cpsid instruction()
- above. */
- __asm volatile( "cpsie i" );
- }
- else
- {
- /* Set the new reload value. */
- portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
-
- /* Clear the SysTick count flag and set the count value back to
- zero. */
- portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
-
- /* Restart SysTick. */
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
-
- /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
- set its parameter to 0 to indicate that its implementation contains
- its own wait for interrupt or wait for event instruction, and so wfi
- should not be executed again. However, the original expected idle
- time variable must remain unmodified, so a copy is taken. */
- xModifiableIdleTime = xExpectedIdleTime;
- configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
- if( xModifiableIdleTime > 0 )
- {
- __asm volatile( "dsb" );
- __asm volatile( "wfi" );
- __asm volatile( "isb" );
- }
- configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
-
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above the cpsid instruction()
- above. */
- __asm volatile( "cpsie i" );
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
- {
- uint32_t ulCalculatedLoadValue;
-
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
- portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
- period. */
- ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
-
- /* Don't allow a tiny value, or values that have somehow
- underflowed because the post sleep hook did something
- that took too long. */
- if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
- {
- ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
- }
-
- portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
-
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
- ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
- }
- else
- {
- /* Something other than the tick interrupt ended the sleep.
- Work out how long the sleep lasted rounded to complete tick
- periods (not the ulReload value which accounted for part
- ticks). */
- ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
-
- /* How many complete tick periods passed while the processor
- was waiting? */
- ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
-
- /* The reload value is set to whatever fraction of a single tick
- period remains. */
- portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
- }
-
- /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
- again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
- portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
- }
- }
-#endif/* #if configSYSTICK_USE_LOW_POWER_TIMER */
-#endif /* #if configUSE_TICKLESS_IDLE */
-/*-----------------------------------------------------------*/
-
-/*
- * Setup the systick timer to generate the tick interrupts at the required
- * frequency.
- */
-__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
-{
- /* Calculate the constants required to configure the tick interrupt. */
- #if( configUSE_TICKLESS_IDLE == 1 )
- {
- #if( configSYSTICK_USE_LOW_POWER_TIMER == 1 )
- ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
- ulStoppedTimerCompensation = 0;
- ulLPTimerCountsForOneTick = configSYSTICK_CLOCK_HZ / configLPTMR_RATE_HZ;
- xMaximumPossibleSuppressedTicks = portMAX_16_BIT_NUMBER / ulLPTimerCountsForOneTick;
- NVIC_EnableIRQ(vPortGetLptmrIrqn());
- #else
- ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
- xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
- ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
- #endif
- }
- #endif /* configUSE_TICKLESS_IDLE */
-
- /* Configure SysTick to interrupt at the requested rate. */
- portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
- portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
-}
-/*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 )
@@ -894,3 +458,24 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
}
#endif /* configASSERT_DEFINED */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/freertos/Source/portable/GCC/ARM_CM3/portmacro.h b/freertos/Source/portable/GCC/ARM_CM3/portmacro.h
index 2aa8472..d44fc92 100644
--- a/freertos/Source/portable/GCC/ARM_CM3/portmacro.h
+++ b/freertos/Source/portable/GCC/ARM_CM3/portmacro.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -117,27 +117,34 @@ typedef unsigned long UBaseType_t;
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
-
/* Scheduler utilities. */
-extern void vPortYield( void );
+#define portYIELD() \
+{ \
+ /* Set a PendSV to request a context switch. */ \
+ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
+ \
+ /* Barriers are normally not required but do ensure the code is completely \
+ within the specified behaviour for the architecture. */ \
+ __asm volatile( "dsb" ); \
+ __asm volatile( "isb" ); \
+}
+
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
-#define portYIELD() vPortYield()
-#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
-extern uint32_t ulPortSetInterruptMask( void );
-extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
-#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
-#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
-#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
+#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
+#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
+#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
+
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
@@ -181,7 +188,7 @@ not necessary for to use this port. They are defined so the common demo files
/*-----------------------------------------------------------*/
- #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
+ #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
@@ -195,6 +202,80 @@ not necessary for to use this port. They are defined so the common demo files
/* portNOP() is not required by this port. */
#define portNOP()
+#define portINLINE __inline
+
+#ifndef portFORCE_INLINE
+ #define portFORCE_INLINE inline __attribute__(( always_inline))
+#endif
+
+portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
+{
+uint32_t ulCurrentInterrupt;
+BaseType_t xReturn;
+
+ /* Obtain the number of the currently executing interrupt. */
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+ if( ulCurrentInterrupt == 0 )
+ {
+ xReturn = pdFALSE;
+ }
+ else
+ {
+ xReturn = pdTRUE;
+ }
+
+ return xReturn;
+}
+
+/*-----------------------------------------------------------*/
+
+portFORCE_INLINE static void vPortRaiseBASEPRI( void )
+{
+uint32_t ulNewBASEPRI;
+
+ __asm volatile
+ (
+ " mov %0, %1 \n" \
+ " msr basepri, %0 \n" \
+ " isb \n" \
+ " dsb \n" \
+ :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+ );
+}
+
+/*-----------------------------------------------------------*/
+
+portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
+{
+uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
+
+ __asm volatile
+ (
+ " mrs %0, basepri \n" \
+ " mov %1, %2 \n" \
+ " msr basepri, %1 \n" \
+ " isb \n" \
+ " dsb \n" \
+ :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+ );
+
+ /* This return will not be reached but is necessary to prevent compiler
+ warnings. */
+ return ulOriginalBASEPRI;
+}
+/*-----------------------------------------------------------*/
+
+portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
+{
+ __asm volatile
+ (
+ " msr basepri, %0 " :: "r" ( ulNewMaskValue )
+ );
+}
+/*-----------------------------------------------------------*/
+
+
#ifdef __cplusplus
}
#endif
diff --git a/freertos/Source/portable/MemMang/heap_1.c b/freertos/Source/portable/MemMang/heap_1.c
index 06958d3..6dfb3cb 100644
--- a/freertos/Source/portable/MemMang/heap_1.c
+++ b/freertos/Source/portable/MemMang/heap_1.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -87,11 +87,23 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
/* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
/* Allocate the memory for the heap. */
-static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+/* Allocate the memory for the heap. */
+#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
+ /* The application writer has already defined the array used for the RTOS
+ heap - probably so it can be placed in a special segment or address. */
+ extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#else
+ static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#endif /* configAPPLICATION_ALLOCATED_HEAP */
+
static size_t xNextFreeByte = ( size_t ) 0;
/*-----------------------------------------------------------*/
@@ -102,12 +114,14 @@ void *pvReturn = NULL;
static uint8_t *pucAlignedHeap = NULL;
/* Ensure that blocks are always aligned to the required number of bytes. */
- #if portBYTE_ALIGNMENT != 1
+ #if( portBYTE_ALIGNMENT != 1 )
+ {
if( xWantedSize & portBYTE_ALIGNMENT_MASK )
{
/* Byte alignment required. */
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
}
+ }
#endif
vTaskSuspendAll();
diff --git a/freertos/Source/portable/MemMang/heap_2.c b/freertos/Source/portable/MemMang/heap_2.c
index 96220e9..bba8554 100644
--- a/freertos/Source/portable/MemMang/heap_2.c
+++ b/freertos/Source/portable/MemMang/heap_2.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -88,6 +88,10 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
/* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
@@ -97,7 +101,14 @@ task.h is included from an application file. */
static void prvHeapInit( void );
/* Allocate the memory for the heap. */
-static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
+ /* The application writer has already defined the array used for the RTOS
+ heap - probably so it can be placed in a special segment or address. */
+ extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#else
+ static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
+#endif /* configAPPLICATION_ALLOCATED_HEAP */
+
/* Define the linked list structure. This is used to link free blocks in order
of their size. */
@@ -127,7 +138,7 @@ static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE;
*/
#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \
{ \
-BlockLink_t *pxIterator; \
+BlockLink_t *pxIterator; \
size_t xBlockSize; \
\
xBlockSize = pxBlockToInsert->xBlockSize; \
diff --git a/freertos/Source/portable/MemMang/heap_3.c b/freertos/Source/portable/MemMang/heap_3.c
index da85a58..f922001 100644
--- a/freertos/Source/portable/MemMang/heap_3.c
+++ b/freertos/Source/portable/MemMang/heap_3.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -91,6 +91,10 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
/*-----------------------------------------------------------*/
void *pvPortMalloc( size_t xWantedSize )
diff --git a/freertos/Source/portable/MemMang/heap_4.c b/freertos/Source/portable/MemMang/heap_4.c
index 97855c4..e7c7ade 100644
--- a/freertos/Source/portable/MemMang/heap_4.c
+++ b/freertos/Source/portable/MemMang/heap_4.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -87,6 +87,10 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
/* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
@@ -293,7 +297,7 @@ void *pvReturn = NULL;
}
#endif
- configASSERT( ( ( ( uint32_t ) pvReturn ) & portBYTE_ALIGNMENT_MASK ) == 0 );
+ configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn;
}
/*-----------------------------------------------------------*/
diff --git a/freertos/Source/portable/MemMang/heap_5.c b/freertos/Source/portable/MemMang/heap_5.c
index 9d92021..d53e41e 100644
--- a/freertos/Source/portable/MemMang/heap_5.c
+++ b/freertos/Source/portable/MemMang/heap_5.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -121,6 +121,10 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
/* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
diff --git a/freertos/Source/portable/readme.txt b/freertos/Source/portable/readme.txt
new file mode 100644
index 0000000..43e7c1d
--- /dev/null
+++ b/freertos/Source/portable/readme.txt
@@ -0,0 +1,19 @@
+Each real time kernel port consists of three files that contain the core kernel
+components and are common to every port, and one or more files that are
+specific to a particular microcontroller and/or compiler.
+
+
++ The FreeRTOS/Source/Portable/MemMang directory contains the three sample
+memory allocators as described on the http://www.FreeRTOS.org WEB site.
+
++ The other directories each contain files specific to a particular
+microcontroller or compiler.
+
+
+
+For example, if you are interested in the GCC port for the ATMega323
+microcontroller then the port specific files are contained in
+FreeRTOS/Source/Portable/GCC/ATMega323 directory. If this is the only
+port you are interested in then all the other directories can be
+ignored.
+
diff --git a/freertos/Source/queue.c b/freertos/Source/queue.c
index 25fcc26..ce623be 100644
--- a/freertos/Source/queue.c
+++ b/freertos/Source/queue.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -90,9 +90,9 @@ privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
-/* Constants used with the xRxLock and xTxLock structure members. */
-#define queueUNLOCKED ( ( BaseType_t ) -1 )
-#define queueLOCKED_UNMODIFIED ( ( BaseType_t ) 0 )
+/* Constants used with the cRxLock and cTxLock structure members. */
+#define queueUNLOCKED ( ( int8_t ) -1 )
+#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 )
/* When the Queue_t structure is used to represent a base queue its pcHead and
pcTail members are used as pointers into the queue storage area. When the
@@ -146,18 +146,22 @@ typedef struct QueueDefinition
UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */
- volatile BaseType_t xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
- volatile BaseType_t xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
+ volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
+ volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
- #if ( configUSE_TRACE_FACILITY == 1 )
- UBaseType_t uxQueueNumber;
- uint8_t ucQueueType;
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
#endif
#if ( configUSE_QUEUE_SETS == 1 )
struct QueueDefinition *pxQueueSetContainer;
#endif
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxQueueNumber;
+ uint8_t ucQueueType;
+ #endif
+
} xQUEUE;
/* The old xQUEUE name is maintained above then typedefed to the new Queue_t
@@ -236,6 +240,21 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
#endif
+/*
+ * Called after a Queue_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Mutexes are a special type of queue. When a mutex is created, first the
+ * queue is created, then prvInitialiseMutex() is called to configure the queue
+ * as a mutex.
+ */
+#if( configUSE_MUTEXES == 1 )
+ static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
+#endif
+
/*-----------------------------------------------------------*/
/*
@@ -245,13 +264,13 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
#define prvLockQueue( pxQueue ) \
taskENTER_CRITICAL(); \
{ \
- if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
+ if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
{ \
- ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
+ ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \
} \
- if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
+ if( ( pxQueue )->cTxLock == queueUNLOCKED ) \
{ \
- ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
+ ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \
} \
} \
taskEXIT_CRITICAL()
@@ -269,8 +288,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
pxQueue->pcWriteTo = pxQueue->pcHead;
pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize );
- pxQueue->xRxLock = queueUNLOCKED;
- pxQueue->xTxLock = queueUNLOCKED;
+ pxQueue->cRxLock = queueUNLOCKED;
+ pxQueue->cTxLock = queueUNLOCKED;
if( xNewQueue == pdFALSE )
{
@@ -281,7 +300,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
it will be possible to write to it. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
@@ -310,129 +329,163 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
}
/*-----------------------------------------------------------*/
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
-{
-Queue_t *pxNewQueue;
-size_t xQueueSizeInBytes;
-QueueHandle_t xReturn = NULL;
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
- /* Remove compiler warnings about unused parameters should
- configUSE_TRACE_FACILITY not be set to 1. */
- ( void ) ucQueueType;
+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType )
+ {
+ Queue_t *pxNewQueue;
- configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
+ configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
- if( uxItemSize == ( UBaseType_t ) 0 )
- {
- /* There is not going to be a queue storage area. */
- xQueueSizeInBytes = ( size_t ) 0;
- }
- else
- {
- /* The queue is one byte longer than asked for to make wrap checking
- easier/faster. */
- xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ /* The StaticQueue_t structure and the queue storage area must be
+ supplied. */
+ configASSERT( pxStaticQueue != NULL );
+
+ /* A queue storage area should be provided if the item size is not 0, and
+ should not be provided if the item size is 0. */
+ configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );
+ configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );
+
+ #if( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ variable of type StaticQueue_t or StaticSemaphore_t equals the size of
+ the real queue and semaphore structures. */
+ volatile size_t xSize = sizeof( StaticQueue_t );
+ configASSERT( xSize == sizeof( Queue_t ) );
+ }
+ #endif /* configASSERT_DEFINED */
+
+ /* The address of a statically allocated queue was passed in, use it.
+ The address of a statically allocated storage area was also passed in
+ but is already set. */
+ pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+
+ if( pxNewQueue != NULL )
+ {
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Queues can be allocated wither statically or dynamically, so
+ note this queue was allocated statically in case the queue is
+ later deleted. */
+ pxNewQueue->ucStaticallyAllocated = pdTRUE;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
+ }
+
+ return pxNewQueue;
}
- /* Allocate the new queue structure and storage area. */
- pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
- if( pxNewQueue != NULL )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
{
+ Queue_t *pxNewQueue;
+ size_t xQueueSizeInBytes;
+ uint8_t *pucQueueStorage;
+
+ configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
+
if( uxItemSize == ( UBaseType_t ) 0 )
{
- /* No RAM was allocated for the queue storage area, but PC head
- cannot be set to NULL because NULL is used as a key to say the queue
- is used as a mutex. Therefore just set pcHead to point to the queue
- as a benign value that is known to be within the memory map. */
- pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
+ /* There is not going to be a queue storage area. */
+ xQueueSizeInBytes = ( size_t ) 0;
}
else
{
- /* Jump past the queue structure to find the location of the queue
- storage area. */
- pxNewQueue->pcHead = ( ( int8_t * ) pxNewQueue ) + sizeof( Queue_t );
+ /* Allocate enough space to hold the maximum number of items that
+ can be in the queue at any time. */
+ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
- /* Initialise the queue members as described above where the queue type
- is defined. */
- pxNewQueue->uxLength = uxQueueLength;
- pxNewQueue->uxItemSize = uxItemSize;
- ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
+ pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
- #if ( configUSE_TRACE_FACILITY == 1 )
+ if( pxNewQueue != NULL )
{
- pxNewQueue->ucQueueType = ucQueueType;
- }
- #endif /* configUSE_TRACE_FACILITY */
+ /* Jump past the queue structure to find the location of the queue
+ storage area. */
+ pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );
- #if( configUSE_QUEUE_SETS == 1 )
- {
- pxNewQueue->pxQueueSetContainer = NULL;
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* Queues can be created either statically or dynamically, so
+ note this task was created dynamically in case it is later
+ deleted. */
+ pxNewQueue->ucStaticallyAllocated = pdFALSE;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
}
- #endif /* configUSE_QUEUE_SETS */
- traceQUEUE_CREATE( pxNewQueue );
- xReturn = pxNewQueue;
+ return pxNewQueue;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )
+{
+ /* Remove compiler warnings about unused parameters should
+ configUSE_TRACE_FACILITY not be set to 1. */
+ ( void ) ucQueueType;
+
+ if( uxItemSize == ( UBaseType_t ) 0 )
+ {
+ /* No RAM was allocated for the queue storage area, but PC head cannot
+ be set to NULL because NULL is used as a key to say the queue is used as
+ a mutex. Therefore just set pcHead to point to the queue as a benign
+ value that is known to be within the memory map. */
+ pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
}
else
{
- mtCOVERAGE_TEST_MARKER();
+ /* Set the head to the start of the queue storage area. */
+ pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
}
- configASSERT( xReturn );
+ /* Initialise the queue members as described where the queue type is
+ defined. */
+ pxNewQueue->uxLength = uxQueueLength;
+ pxNewQueue->uxItemSize = uxItemSize;
+ ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
- return xReturn;
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ pxNewQueue->ucQueueType = ucQueueType;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+
+ #if( configUSE_QUEUE_SETS == 1 )
+ {
+ pxNewQueue->pxQueueSetContainer = NULL;
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ traceQUEUE_CREATE( pxNewQueue );
}
/*-----------------------------------------------------------*/
-#if ( configUSE_MUTEXES == 1 )
+#if( configUSE_MUTEXES == 1 )
- QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+ static void prvInitialiseMutex( Queue_t *pxNewQueue )
{
- Queue_t *pxNewQueue;
-
- /* Prevent compiler warnings about unused parameters if
- configUSE_TRACE_FACILITY does not equal 1. */
- ( void ) ucQueueType;
-
- /* Allocate the new queue structure. */
- pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
if( pxNewQueue != NULL )
{
- /* Information required for priority inheritance. */
+ /* The queue create function will set all the queue structure members
+ correctly for a generic queue, but this function is creating a
+ mutex. Overwrite those members that need to be set differently -
+ in particular the information required for priority inheritance. */
pxNewQueue->pxMutexHolder = NULL;
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
- /* Queues used as a mutex no data is actually copied into or out
- of the queue. */
- pxNewQueue->pcWriteTo = NULL;
- pxNewQueue->u.pcReadFrom = NULL;
-
- /* Each mutex has a length of 1 (like a binary semaphore) and
- an item size of 0 as nothing is actually copied into or out
- of the mutex. */
- pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
- pxNewQueue->uxLength = ( UBaseType_t ) 1U;
- pxNewQueue->uxItemSize = ( UBaseType_t ) 0U;
- pxNewQueue->xRxLock = queueUNLOCKED;
- pxNewQueue->xTxLock = queueUNLOCKED;
-
- #if ( configUSE_TRACE_FACILITY == 1 )
- {
- pxNewQueue->ucQueueType = ucQueueType;
- }
- #endif
-
- #if ( configUSE_QUEUE_SETS == 1 )
- {
- pxNewQueue->pxQueueSetContainer = NULL;
- }
- #endif
-
- /* Ensure the event queues start with the correct state. */
- vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
- vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
+ /* In case this is a recursive mutex. */
+ pxNewQueue->u.uxRecursiveCallCount = 0;
traceCREATE_MUTEX( pxNewQueue );
@@ -443,6 +496,40 @@ QueueHandle_t xReturn = NULL;
{
traceCREATE_MUTEX_FAILED();
}
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+ {
+ Queue_t *pxNewQueue;
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+ pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
+ prvInitialiseMutex( pxNewQueue );
+
+ return pxNewQueue;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue )
+ {
+ Queue_t *pxNewQueue;
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+ /* Prevent compiler warnings about unused parameters if
+ configUSE_TRACE_FACILITY does not equal 1. */
+ ( void ) ucQueueType;
+
+ pxNewQueue = ( Queue_t * ) xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );
+ prvInitialiseMutex( pxNewQueue );
return pxNewQueue;
}
@@ -506,7 +593,7 @@ QueueHandle_t xReturn = NULL;
uxRecursiveCallCount member. */
( pxMutex->u.uxRecursiveCallCount )--;
- /* Have we unwound the call count? */
+ /* Has the recursive call count unwound to 0? */
if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 )
{
/* Return the mutex. This will automatically unblock any other
@@ -561,7 +648,7 @@ QueueHandle_t xReturn = NULL;
/* pdPASS will only be returned if the mutex was successfully
obtained. The calling task may have entered the Blocked state
before reaching here. */
- if( xReturn == pdPASS )
+ if( xReturn != pdFAIL )
{
( pxMutex->u.uxRecursiveCallCount )++;
}
@@ -577,7 +664,35 @@ QueueHandle_t xReturn = NULL;
#endif /* configUSE_RECURSIVE_MUTEXES */
/*-----------------------------------------------------------*/
-#if ( configUSE_COUNTING_SEMAPHORES == 1 )
+#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue )
+ {
+ QueueHandle_t xHandle;
+
+ configASSERT( uxMaxCount != 0 );
+ configASSERT( uxInitialCount <= uxMaxCount );
+
+ xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
+
+ if( xHandle != NULL )
+ {
+ ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
+
+ traceCREATE_COUNTING_SEMAPHORE();
+ }
+ else
+ {
+ traceCREATE_COUNTING_SEMAPHORE_FAILED();
+ }
+
+ return xHandle;
+ }
+
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
{
@@ -599,11 +714,10 @@ QueueHandle_t xReturn = NULL;
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
- configASSERT( xHandle );
return xHandle;
}
-#endif /* configUSE_COUNTING_SEMAPHORES */
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
/*-----------------------------------------------------------*/
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
@@ -642,7 +756,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
if( pxQueue->pxQueueSetContainer != NULL )
{
- if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
+ if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
{
/* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to
@@ -660,7 +774,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The unblocked task has a priority higher than
our own so yield immediately. Yes it is ok to
@@ -693,7 +807,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The unblocked task has a priority higher than
our own so yield immediately. Yes it is ok to do
@@ -797,8 +911,6 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
- /* Return to the original privilege level before exiting the
- function. */
traceQUEUE_SEND_FAILED( pxQueue );
return errQUEUE_FULL;
}
@@ -806,251 +918,6 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
}
/*-----------------------------------------------------------*/
-#if ( configUSE_ALTERNATIVE_API == 1 )
-
- BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition )
- {
- BaseType_t xEntryTimeSet = pdFALSE;
- TimeOut_t xTimeOut;
- Queue_t * const pxQueue = ( Queue_t * ) xQueue;
-
- configASSERT( pxQueue );
- configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
-
- for( ;; )
- {
- taskENTER_CRITICAL();
- {
- /* Is there room on the queue now? To be running we must be
- the highest priority task wanting to access the queue. */
- if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
- {
- traceQUEUE_SEND( pxQueue );
- prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
-
- /* If there was a task waiting for data to arrive on the
- queue then unblock it now. */
- if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
- {
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
- {
- /* The unblocked task has a priority higher than
- our own so yield immediately. */
- portYIELD_WITHIN_API();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- taskEXIT_CRITICAL();
- return pdPASS;
- }
- else
- {
- if( xTicksToWait == ( TickType_t ) 0 )
- {
- taskEXIT_CRITICAL();
- return errQUEUE_FULL;
- }
- else if( xEntryTimeSet == pdFALSE )
- {
- vTaskSetTimeOutState( &xTimeOut );
- xEntryTimeSet = pdTRUE;
- }
- }
- }
- taskEXIT_CRITICAL();
-
- taskENTER_CRITICAL();
- {
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- if( prvIsQueueFull( pxQueue ) != pdFALSE )
- {
- traceBLOCKING_ON_QUEUE_SEND( pxQueue );
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
- portYIELD_WITHIN_API();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- else
- {
- taskEXIT_CRITICAL();
- traceQUEUE_SEND_FAILED( pxQueue );
- return errQUEUE_FULL;
- }
- }
- taskEXIT_CRITICAL();
- }
- }
-
-#endif /* configUSE_ALTERNATIVE_API */
-/*-----------------------------------------------------------*/
-
-#if ( configUSE_ALTERNATIVE_API == 1 )
-
- BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking )
- {
- BaseType_t xEntryTimeSet = pdFALSE;
- TimeOut_t xTimeOut;
- int8_t *pcOriginalReadPosition;
- Queue_t * const pxQueue = ( Queue_t * ) xQueue;
-
- configASSERT( pxQueue );
- configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
-
- for( ;; )
- {
- taskENTER_CRITICAL();
- {
- if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
- {
- /* Remember our read position in case we are just peeking. */
- pcOriginalReadPosition = pxQueue->u.pcReadFrom;
-
- prvCopyDataFromQueue( pxQueue, pvBuffer );
-
- if( xJustPeeking == pdFALSE )
- {
- traceQUEUE_RECEIVE( pxQueue );
-
- /* Data is actually being removed (not just peeked). */
- --( pxQueue->uxMessagesWaiting );
-
- #if ( configUSE_MUTEXES == 1 )
- {
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
- {
- /* Record the information required to implement
- priority inheritance should it become necessary. */
- pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- #endif
-
- if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
- {
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
- {
- portYIELD_WITHIN_API();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- }
- else
- {
- traceQUEUE_PEEK( pxQueue );
-
- /* The data is not being removed, so reset our read
- pointer. */
- pxQueue->u.pcReadFrom = pcOriginalReadPosition;
-
- /* The data is being left in the queue, so see if there are
- any other tasks waiting for the data. */
- if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
- {
- /* Tasks that are removed from the event list will get added to
- the pending ready list as the scheduler is still suspended. */
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
- {
- /* The task waiting has a higher priority than this task. */
- portYIELD_WITHIN_API();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
-
- taskEXIT_CRITICAL();
- return pdPASS;
- }
- else
- {
- if( xTicksToWait == ( TickType_t ) 0 )
- {
- taskEXIT_CRITICAL();
- traceQUEUE_RECEIVE_FAILED( pxQueue );
- return errQUEUE_EMPTY;
- }
- else if( xEntryTimeSet == pdFALSE )
- {
- vTaskSetTimeOutState( &xTimeOut );
- xEntryTimeSet = pdTRUE;
- }
- }
- }
- taskEXIT_CRITICAL();
-
- taskENTER_CRITICAL();
- {
- if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
- {
- if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
- {
- traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
-
- #if ( configUSE_MUTEXES == 1 )
- {
- if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
- {
- taskENTER_CRITICAL();
- {
- vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
- }
- taskEXIT_CRITICAL();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- #endif
-
- vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
- portYIELD_WITHIN_API();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- else
- {
- taskEXIT_CRITICAL();
- traceQUEUE_RECEIVE_FAILED( pxQueue );
- return errQUEUE_EMPTY;
- }
- }
- taskEXIT_CRITICAL();
- }
- }
-
-
-#endif /* configUSE_ALTERNATIVE_API */
-/*-----------------------------------------------------------*/
-
BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition )
{
BaseType_t xReturn;
@@ -1086,6 +953,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
{
+ const int8_t cTxLock = pxQueue->cTxLock;
+
traceQUEUE_SEND_FROM_ISR( pxQueue );
/* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
@@ -1097,13 +966,13 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* The event list is not altered if the queue is locked. This will
be done when the queue is unlocked later. */
- if( pxQueue->xTxLock == queueUNLOCKED )
+ if( cTxLock == queueUNLOCKED )
{
#if ( configUSE_QUEUE_SETS == 1 )
{
if( pxQueue->pxQueueSetContainer != NULL )
{
- if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
+ if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
{
/* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to
@@ -1183,7 +1052,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
/* Increment the lock count so the task that unlocks the queue
knows that data was posted while it was locked. */
- ++( pxQueue->xTxLock );
+ pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );
}
xReturn = pdPASS;
@@ -1241,11 +1110,15 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
/* When the queue is used to implement a semaphore no data is ever
moved through the queue but it is still valid to see if the queue 'has
space'. */
- if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+ if( uxMessagesWaiting < pxQueue->uxLength )
{
+ const int8_t cTxLock = pxQueue->cTxLock;
+
traceQUEUE_SEND_FROM_ISR( pxQueue );
/* A task can only have an inherited priority if it is a mutex
@@ -1254,17 +1127,17 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
can be assumed there is no mutex holder and no need to determine if
priority disinheritance is needed. Simply increase the count of
messages (semaphores) available. */
- ++( pxQueue->uxMessagesWaiting );
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1;
/* The event list is not altered if the queue is locked. This will
be done when the queue is unlocked later. */
- if( pxQueue->xTxLock == queueUNLOCKED )
+ if( cTxLock == queueUNLOCKED )
{
#if ( configUSE_QUEUE_SETS == 1 )
{
if( pxQueue->pxQueueSetContainer != NULL )
{
- if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
+ if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE )
{
/* The semaphore is a member of a queue set, and
posting to the queue set caused a higher priority
@@ -1344,7 +1217,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
/* Increment the lock count so the task that unlocks the queue
knows that data was posted while it was locked. */
- ++( pxQueue->xTxLock );
+ pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );
}
xReturn = pdPASS;
@@ -1384,9 +1257,11 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
taskENTER_CRITICAL();
{
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
/* Is there data in the queue now? To be running the calling task
- must be the highest priority task wanting to access the queue. */
- if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+ must be the highest priority task wanting to access the queue. */
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
{
/* Remember the read position in case the queue is only being
peeked. */
@@ -1399,7 +1274,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
traceQUEUE_RECEIVE( pxQueue );
/* Actually removing data, not just peeking. */
- --( pxQueue->uxMessagesWaiting );
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;
#if ( configUSE_MUTEXES == 1 )
{
@@ -1418,7 +1293,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
- if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
@@ -1541,8 +1416,16 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
- traceQUEUE_RECEIVE_FAILED( pxQueue );
- return errQUEUE_EMPTY;
+
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
}
}
}
@@ -1575,19 +1458,23 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
/* Cannot block in an ISR, so check there is data available. */
- if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
{
+ const int8_t cRxLock = pxQueue->cRxLock;
+
traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
prvCopyDataFromQueue( pxQueue, pvBuffer );
- --( pxQueue->uxMessagesWaiting );
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;
/* If the queue is locked the event list will not be modified.
Instead update the lock count so the task that unlocks the queue
will know that an ISR has removed data while the queue was
locked. */
- if( pxQueue->xRxLock == queueUNLOCKED )
+ if( cRxLock == queueUNLOCKED )
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
@@ -1618,7 +1505,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
/* Increment the lock count so the task that unlocks the queue
knows that data was removed while it was locked. */
- ++( pxQueue->xRxLock );
+ pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 );
}
xReturn = pdPASS;
@@ -1740,14 +1627,40 @@ void vQueueDelete( QueueHandle_t xQueue )
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue );
-
traceQUEUE_DELETE( pxQueue );
+
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{
vQueueUnregisterQueue( pxQueue );
}
#endif
- vPortFree( pxQueue );
+
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+ {
+ /* The queue can only have been allocated dynamically - free it
+ again. */
+ vPortFree( pxQueue );
+ }
+ #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ {
+ /* The queue could have been allocated statically or dynamically, so
+ check before attempting to free the memory. */
+ if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+ {
+ vPortFree( pxQueue );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #else
+ {
+ /* The queue must have been statically allocated, so is not going to be
+ deleted. Avoid compiler warnings about the unused parameter. */
+ ( void ) pxQueue;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
/*-----------------------------------------------------------*/
@@ -1784,6 +1697,11 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
{
BaseType_t xReturn = pdFALSE;
+UBaseType_t uxMessagesWaiting;
+
+ /* This function is called from a critical section. */
+
+ uxMessagesWaiting = pxQueue->uxMessagesWaiting;
if( pxQueue->uxItemSize == ( UBaseType_t ) 0 )
{
@@ -1830,13 +1748,13 @@ BaseType_t xReturn = pdFALSE;
if( xPosition == queueOVERWRITE )
{
- if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
{
/* An item is not being added but overwritten, so subtract
one from the recorded number of items in the queue so when
one is added again below the number of recorded items remains
correct. */
- --( pxQueue->uxMessagesWaiting );
+ --uxMessagesWaiting;
}
else
{
@@ -1849,7 +1767,7 @@ BaseType_t xReturn = pdFALSE;
}
}
- ++( pxQueue->uxMessagesWaiting );
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1;
return xReturn;
}
@@ -1883,8 +1801,10 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
updated. */
taskENTER_CRITICAL();
{
+ int8_t cTxLock = pxQueue->cTxLock;
+
/* See if data was added to the queue while it was locked. */
- while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
+ while( cTxLock > queueLOCKED_UNMODIFIED )
{
/* Data was posted while the queue was locked. Are any tasks
blocked waiting for data to become available? */
@@ -1892,7 +1812,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
{
if( pxQueue->pxQueueSetContainer != NULL )
{
- if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
+ if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE )
{
/* The queue is a member of a queue set, and posting to
the queue set caused a higher priority task to unblock.
@@ -1906,8 +1826,9 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
}
else
{
- /* Tasks that are removed from the event list will get added to
- the pending ready list as the scheduler is still suspended. */
+ /* Tasks that are removed from the event list will get
+ added to the pending ready list as the scheduler is still
+ suspended. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
@@ -1935,8 +1856,8 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
- /* The task waiting has a higher priority so record that a
- context switch is required. */
+ /* The task waiting has a higher priority so record that
+ a context switch is required. */
vTaskMissedYield();
}
else
@@ -1951,17 +1872,19 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
}
#endif /* configUSE_QUEUE_SETS */
- --( pxQueue->xTxLock );
+ --cTxLock;
}
- pxQueue->xTxLock = queueUNLOCKED;
+ pxQueue->cTxLock = queueUNLOCKED;
}
taskEXIT_CRITICAL();
/* Do the same for the Rx lock. */
taskENTER_CRITICAL();
{
- while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
+ int8_t cRxLock = pxQueue->cRxLock;
+
+ while( cRxLock > queueLOCKED_UNMODIFIED )
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
@@ -1974,7 +1897,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
mtCOVERAGE_TEST_MARKER();
}
- --( pxQueue->xRxLock );
+ --cRxLock;
}
else
{
@@ -1982,7 +1905,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
}
}
- pxQueue->xRxLock = queueUNLOCKED;
+ pxQueue->cRxLock = queueUNLOCKED;
}
taskEXIT_CRITICAL();
}
@@ -2372,6 +2295,34 @@ BaseType_t xReturn;
#if ( configQUEUE_REGISTRY_SIZE > 0 )
+ const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ UBaseType_t ux;
+ const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+ /* Note there is nothing here to protect against another task adding or
+ removing entries from the registry while it is being searched. */
+ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
+ {
+ if( xQueueRegistry[ ux ].xHandle == xQueue )
+ {
+ pcReturn = xQueueRegistry[ ux ].pcQueueName;
+ break;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ return pcReturn;
+ }
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+/*-----------------------------------------------------------*/
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
void vQueueUnregisterQueue( QueueHandle_t xQueue )
{
UBaseType_t ux;
@@ -2384,6 +2335,11 @@ BaseType_t xReturn;
{
/* Set the name to NULL to show that this slot if free again. */
xQueueRegistry[ ux ].pcQueueName = NULL;
+
+ /* Set the handle to NULL to ensure the same queue handle cannot
+ appear in the registry twice if it is added, removed, then
+ added again. */
+ xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0;
break;
}
else
@@ -2433,7 +2389,7 @@ BaseType_t xReturn;
#endif /* configUSE_TIMERS */
/*-----------------------------------------------------------*/
-#if ( configUSE_QUEUE_SETS == 1 )
+#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
{
@@ -2556,12 +2512,14 @@ BaseType_t xReturn;
if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
{
+ const int8_t cTxLock = pxQueueSetContainer->cTxLock;
+
traceQUEUE_SEND( pxQueueSetContainer );
/* The data copied is the handle of the queue that contains data. */
xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
- if( pxQueueSetContainer->xTxLock == queueUNLOCKED )
+ if( cTxLock == queueUNLOCKED )
{
if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
{
@@ -2582,7 +2540,7 @@ BaseType_t xReturn;
}
else
{
- ( pxQueueSetContainer->xTxLock )++;
+ pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 );
}
}
else
diff --git a/freertos/Source/readme.txt b/freertos/Source/readme.txt
new file mode 100644
index 0000000..58480c5
--- /dev/null
+++ b/freertos/Source/readme.txt
@@ -0,0 +1,17 @@
+Each real time kernel port consists of three files that contain the core kernel
+components and are common to every port, and one or more files that are
+specific to a particular microcontroller and or compiler.
+
++ The FreeRTOS/Source directory contains the three files that are common to
+every port - list.c, queue.c and tasks.c. The kernel is contained within these
+three files. croutine.c implements the optional co-routine functionality - which
+is normally only used on very memory limited systems.
+
++ The FreeRTOS/Source/Portable directory contains the files that are specific to
+a particular microcontroller and or compiler.
+
++ The FreeRTOS/Source/include directory contains the real time kernel header
+files.
+
+See the readme file in the FreeRTOS/Source/Portable directory for more
+information. \ No newline at end of file
diff --git a/freertos/Source/tasks.c b/freertos/Source/tasks.c
index b363bde..df0f346 100644
--- a/freertos/Source/tasks.c
+++ b/freertos/Source/tasks.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -98,18 +98,6 @@ functions but without including stdio.h here. */
#include <stdio.h>
#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
-/* Sanity check the configuration. */
-#if( configUSE_TICKLESS_IDLE != 0 )
- #if( INCLUDE_vTaskSuspend != 1 )
- #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
- #endif /* INCLUDE_vTaskSuspend */
-#endif /* configUSE_TICKLESS_IDLE */
-
-/*
- * Defines the size, in words, of the stack allocated to the idle task.
- */
-#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
-
#if( configUSE_PREEMPTION == 0 )
/* If the cooperative scheduler is being used then a yield should not be
performed just because a higher priority task has been woken. */
@@ -118,157 +106,10 @@ functions but without including stdio.h here. */
#define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
#endif
-/* Value that can be assigned to the eNotifyState member of the TCB. */
-typedef enum
-{
- eNotWaitingNotification = 0,
- eWaitingNotification,
- eNotified
-} eNotifyValue;
-
-/*
- * Task control block. A task control block (TCB) is allocated for each task,
- * and stores task state information, including a pointer to the task's context
- * (the task's run time environment, including register values)
- */
-typedef struct tskTaskControlBlock
-{
- volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
-
- #if ( portUSING_MPU_WRAPPERS == 1 )
- xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
- BaseType_t xUsingStaticallyAllocatedStack; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */
- #endif
-
- ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
- ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
- UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
- StackType_t *pxStack; /*< Points to the start of the stack. */
- char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-
- #if ( portSTACK_GROWTH > 0 )
- StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
- #endif
-
- #if ( portCRITICAL_NESTING_IN_TCB == 1 )
- UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
- #endif
-
- #if ( configUSE_TRACE_FACILITY == 1 )
- UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
- UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
- #endif
-
- #if ( configUSE_MUTEXES == 1 )
- UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
- UBaseType_t uxMutexesHeld;
- #endif
-
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- TaskHookFunction_t pxTaskTag;
- #endif
-
- #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
- void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
- #endif
-
- #if ( configGENERATE_RUN_TIME_STATS == 1 )
- uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
- #endif
-
- #if ( configUSE_NEWLIB_REENTRANT == 1 )
- /* Allocate a Newlib reent structure that is specific to this task.
- Note Newlib support has been included by popular demand, but is not
- used by the FreeRTOS maintainers themselves. FreeRTOS is not
- responsible for resulting newlib operation. User must be familiar with
- newlib and must provide system-wide implementations of the necessary
- stubs. Be warned that (at the time of writing) the current newlib design
- implements a system-wide malloc() that must be provided with locks. */
- struct _reent xNewLib_reent;
- #endif
-
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- volatile uint32_t ulNotifiedValue;
- volatile eNotifyValue eNotifyState;
- #endif
-
-} tskTCB;
-
-/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
-below to enable the use of older kernel aware debuggers. */
-typedef tskTCB TCB_t;
-
-/*
- * Some kernel aware debuggers require the data the debugger needs access to to
- * be global, rather than file scope.
- */
-#ifdef portREMOVE_STATIC_QUALIFIER
- #define static
-#endif
-
-/*lint -e956 A manual analysis and inspection has been used to determine which
-static variables must be declared volatile. */
-
-PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
-
-/* Lists for ready and blocked tasks. --------------------*/
-PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
-PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
-PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
-PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
-PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
-PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
-
-#if ( INCLUDE_vTaskDelete == 1 )
-
- PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
- PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;
-
-#endif
-
-#if ( INCLUDE_vTaskSuspend == 1 )
-
- PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
-
-#endif
-
-#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
-
- PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
-
-#endif
-
-/* Other file private variables. --------------------------------*/
-PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
-PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
-PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
-PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
-PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
-PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
-
-/* Context switches are held pending while the scheduler is suspended. Also,
-interrupts must not manipulate the xGenericListItem of a TCB, or any of the
-lists the xGenericListItem can be referenced from, if the scheduler is suspended.
-If an interrupt needs to unblock a task while the scheduler is suspended then it
-moves the task's event list item into the xPendingReadyList, ready for the
-kernel to move the task from the pending ready list into the real ready list
-when the scheduler is unsuspended. The pending ready list itself can only be
-accessed from a critical section. */
-PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
-
-#if ( configGENERATE_RUN_TIME_STATS == 1 )
-
- PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
- PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
-
-#endif
-
-/*lint +e956 */
-
-/* Debugging and trace facilities private variables and macros. ------------*/
+/* Values that can be assigned to the ucNotifyState member of the TCB. */
+#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 )
+#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
+#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
/*
* The value used to fill the stack of a task when the task is created. This
@@ -276,6 +117,26 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
*/
#define tskSTACK_FILL_BYTE ( 0xa5U )
+/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
+dynamically allocated RAM, in which case when any task is deleted it is known
+that both the task's stack and TCB need to be freed. Sometimes the
+FreeRTOSConfig.h settings only allow a task to be created using statically
+allocated RAM, in which case when any task is deleted it is known that neither
+the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
+settings allow a task to be created using either statically or dynamically
+allocated RAM, in which case a member of the TCB is used to record whether the
+stack and/or TCB were allocated statically or dynamically, so when a task is
+deleted the RAM that was allocated dynamically is freed again and no attempt is
+made to free the RAM that was allocated statically.
+tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
+task to be created using either statically or dynamically allocated RAM. Note
+that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
+a statically allocated stack and a dynamically allocated TCB. */
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
+#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
+#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
+#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
+
/*
* Macros used by vListTask to indicate which state a task is in.
*/
@@ -284,7 +145,13 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
#define tskDELETED_CHAR ( 'D' )
#define tskSUSPENDED_CHAR ( 'S' )
-/*-----------------------------------------------------------*/
+/*
+ * Some kernel aware debuggers require the data the debugger needs access to be
+ * global, rather than file scope.
+ */
+#ifdef portREMOVE_STATIC_QUALIFIER
+ #define static
+#endif
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
@@ -306,16 +173,19 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
+ UBaseType_t uxTopPriority = uxTopReadyPriority; \
+ \
/* Find the highest priority queue that contains ready tasks. */ \
- while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
+ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
{ \
- configASSERT( uxTopReadyPriority ); \
- --uxTopReadyPriority; \
+ configASSERT( uxTopPriority ); \
+ --uxTopPriority; \
} \
\
/* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
the same priority get an equal share of the processor time. */ \
- listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
+ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
+ uxTopReadyPriority = uxTopPriority; \
} /* taskSELECT_HIGHEST_PRIORITY_TASK */
/*-----------------------------------------------------------*/
@@ -341,7 +211,7 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
{ \
UBaseType_t uxTopPriority; \
\
- /* Find the highest priority queue that contains ready tasks. */ \
+ /* Find the highest priority list that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
@@ -389,7 +259,8 @@ count overflows. */
#define prvAddTaskToReadyList( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
- vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
+ vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
+ tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
/*-----------------------------------------------------------*/
/*
@@ -408,28 +279,166 @@ being used for another purpose. The following bit definition is used to inform
the scheduler that the value should not be changed - in which case it is the
responsibility of whichever module is using the value to ensure it gets set back
to its original value when it is released. */
-#if configUSE_16_BIT_TICKS == 1
+#if( configUSE_16_BIT_TICKS == 1 )
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
#else
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
#endif
+/*
+ * Task control block. A task control block (TCB) is allocated for each task,
+ * and stores task state information, including a pointer to the task's context
+ * (the task's run time environment, including register values)
+ */
+typedef struct tskTaskControlBlock
+{
+ volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
+ #endif
+
+ ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
+ ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
+ UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
+ StackType_t *pxStack; /*< Points to the start of the stack. */
+ char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+ #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+ StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
+ #endif
+
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
+ UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
+ #endif
+
+ #if ( configUSE_MUTEXES == 1 )
+ UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
+ UBaseType_t uxMutexesHeld;
+ #endif
+
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ TaskHookFunction_t pxTaskTag;
+ #endif
+
+ #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+ void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+ #endif
+
+ #if( configGENERATE_RUN_TIME_STATS == 1 )
+ uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
+ #endif
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ /* Allocate a Newlib reent structure that is specific to this task.
+ Note Newlib support has been included by popular demand, but is not
+ used by the FreeRTOS maintainers themselves. FreeRTOS is not
+ responsible for resulting newlib operation. User must be familiar with
+ newlib and must provide system-wide implementations of the necessary
+ stubs. Be warned that (at the time of writing) the current newlib design
+ implements a system-wide malloc() that must be provided with locks. */
+ struct _reent xNewLib_reent;
+ #endif
+
+ #if( configUSE_TASK_NOTIFICATIONS == 1 )
+ volatile uint32_t ulNotifiedValue;
+ volatile uint8_t ucNotifyState;
+ #endif
+
+ /* See the comments above the definition of
+ tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
+ #endif
+
+ #if( INCLUDE_xTaskAbortDelay == 1 )
+ uint8_t ucDelayAborted;
+ #endif
+
+} tskTCB;
+
+/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
+below to enable the use of older kernel aware debuggers. */
+typedef tskTCB TCB_t;
+
+/*lint -e956 A manual analysis and inspection has been used to determine which
+static variables must be declared volatile. */
+
+PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
+
+/* Lists for ready and blocked tasks. --------------------*/
+PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
+PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
+PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
+PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
+PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
+PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
+
+#if( INCLUDE_vTaskDelete == 1 )
+
+ PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
+ PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
+
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
+
+#endif
+
+/* Other file private variables. --------------------------------*/
+PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
+PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
+PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
+PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
+PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
+PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
+
+/* Context switches are held pending while the scheduler is suspended. Also,
+interrupts must not manipulate the xStateListItem of a TCB, or any of the
+lists the xStateListItem can be referenced from, if the scheduler is suspended.
+If an interrupt needs to unblock a task while the scheduler is suspended then it
+moves the task's event list item into the xPendingReadyList, ready for the
+kernel to move the task from the pending ready list into the real ready list
+when the scheduler is unsuspended. The pending ready list itself can only be
+accessed from a critical section. */
+PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+ PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
+ PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
+
+#endif
+
+/*lint +e956 */
+
+/*-----------------------------------------------------------*/
+
/* Callback function prototypes. --------------------------*/
-#if configCHECK_FOR_STACK_OVERFLOW > 0
+#if( configCHECK_FOR_STACK_OVERFLOW > 0 )
extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
#endif
-#if configUSE_TICK_HOOK > 0
+#if( configUSE_TICK_HOOK > 0 )
extern void vApplicationTickHook( void );
#endif
-/* File private functions. --------------------------------*/
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
+#endif
-/*
- * Utility to ready a TCB for a given task. Mainly just copies the parameters
- * into the TCB structure.
- */
-static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+/* File private functions. --------------------------------*/
/**
* Utility task that simply returns pdTRUE if the task referenced by xTask is
@@ -483,13 +492,7 @@ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
* The currently executing task is entering the Blocked state. Add the task to
* either the current or the overflow delayed task list.
*/
-static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
-
-/*
- * Allocates memory from the heap for a TCB and associated stack. Checks the
- * allocation was successful.
- */
-static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
+static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
/*
* Fills an TaskStatus_t structure with information on each task that is
@@ -501,7 +504,17 @@ static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t *
*/
#if ( configUSE_TRACE_FACILITY == 1 )
- static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
+ static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Searches pxList for a task with name pcNameToQuery - returning a handle to
+ * the task if it is found, or NULL if the task is not found.
+ */
+#if ( INCLUDE_xTaskGetHandle == 1 )
+
+ static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
#endif
@@ -543,199 +556,497 @@ static void prvResetNextTaskUnblockTime( void );
* Helper function used to pad task names with spaces when printing out
* human readable tables of task information.
*/
- static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName );
+ static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;
#endif
+
+/*
+ * Called after a Task_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+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,
+ const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/*
+ * Called after a new task has been created and initialised to place the task
+ * under the control of the scheduler.
+ */
+static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
+
/*-----------------------------------------------------------*/
-BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-{
-BaseType_t xReturn;
-TCB_t * pxNewTCB;
-StackType_t *pxTopOfStack;
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ 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. */
+ {
+ TCB_t *pxNewTCB;
+ TaskHandle_t xReturn;
- configASSERT( pxTaskCode );
- configASSERT( ( ( uxPriority & ( UBaseType_t ) ( ~portPRIVILEGE_BIT ) ) < ( UBaseType_t ) configMAX_PRIORITIES ) );
+ configASSERT( puxStackBuffer != NULL );
+ configASSERT( pxTaskBuffer != NULL );
- /* Allocate the memory required by the TCB and stack for the new task,
- checking that the allocation was successful. */
- pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
+ 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. */
+ pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
+
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ task was created statically in case the task is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
+ prvAddNewTaskToReadyList( pxNewTCB );
+ }
+ else
+ {
+ xReturn = NULL;
+ }
- if( pxNewTCB != NULL )
+ return xReturn;
+ }
+
+#endif /* SUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( portUSING_MPU_WRAPPERS == 1 )
+
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
- #if( portUSING_MPU_WRAPPERS == 1 )
- /* Should the task be created in privileged mode? */
- BaseType_t xRunPrivileged;
- if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
+ TCB_t *pxNewTCB;
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+ configASSERT( pxTaskDefinition->puxStackBuffer );
+
+ if( pxTaskDefinition->puxStackBuffer != NULL )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends
+ on the implementation of the port malloc function and whether or
+ not static allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+ if( pxNewTCB != NULL )
{
- xRunPrivileged = pdTRUE;
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+ /* Tasks can be created statically or dynamically, so note
+ this task had a statically allocated stack in case it is
+ later deleted. The TCB was allocated dynamically. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
+
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
+ pxTaskDefinition->pcName,
+ ( uint32_t ) pxTaskDefinition->usStackDepth,
+ pxTaskDefinition->pvParameters,
+ pxTaskDefinition->uxPriority,
+ pxCreatedTask, pxNewTCB,
+ pxTaskDefinition->xRegions );
+
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
}
- else
+ }
+
+ return xReturn;
+ }
+
+#endif /* portUSING_MPU_WRAPPERS */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ 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. */
+ {
+ TCB_t *pxNewTCB;
+ BaseType_t xReturn;
+
+ /* If the stack grows down then allocate the stack then the TCB so the stack
+ does not grow into the TCB. Likewise if the stack grows up then allocate
+ the TCB then the stack. */
+ #if( portSTACK_GROWTH > 0 )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends on
+ the implementation of the port malloc function and whether or not static
+ allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+ if( pxNewTCB != NULL )
{
- xRunPrivileged = pdFALSE;
+ /* Allocate space for the stack used by the task being created.
+ The base of the stack memory stored in the TCB so the task can
+ be deleted later if required. */
+ pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ if( pxNewTCB->pxStack == NULL )
+ {
+ /* Could not allocate the stack. Delete the allocated TCB. */
+ vPortFree( pxNewTCB );
+ pxNewTCB = NULL;
+ }
}
- uxPriority &= ~portPRIVILEGE_BIT;
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ StackType_t *pxStack;
- if( puxStackBuffer != NULL )
+ /* Allocate space for the stack used by the task being created. */
+ pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ if( pxStack != NULL )
{
- /* The application provided its own stack. Note this so no
- attempt is made to delete the stack should that task be
- deleted. */
- pxNewTCB->xUsingStaticallyAllocatedStack = pdTRUE;
+ /* Allocate space for the TCB. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
+
+ if( pxNewTCB != NULL )
+ {
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxStack;
+ }
+ else
+ {
+ /* The stack cannot be used as the TCB was not created. Free
+ it again. */
+ vPortFree( pxStack );
+ }
}
else
{
- /* The stack was allocated dynamically. Note this so it can be
- deleted again if the task is deleted. */
- pxNewTCB->xUsingStaticallyAllocatedStack = pdFALSE;
+ pxNewTCB = NULL;
}
- #endif /* portUSING_MPU_WRAPPERS == 1 */
+ }
+ #endif /* portSTACK_GROWTH */
- /* Calculate the top of stack address. This depends on whether the
- stack grows from high memory to low (as per the 80x86) or vice versa.
- portSTACK_GROWTH is used to make the result positive or negative as
- required by the port. */
- #if( portSTACK_GROWTH < 0 )
+ if( pxNewTCB != NULL )
{
- pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
- pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ task was created dynamically in case it is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
- /* Check the alignment of the calculated top of stack is correct. */
- configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
}
- #else /* portSTACK_GROWTH */
+ else
{
- pxTopOfStack = pxNewTCB->pxStack;
+ xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+ }
- /* Check the alignment of the stack buffer is correct. */
- configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ return xReturn;
+ }
- /* If we want to use stack checking on architectures that use
- a positive stack growth direction then we also need to store the
- other extreme of the stack space. */
- pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
- }
- #endif /* portSTACK_GROWTH */
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
- /* Setup the newly allocated TCB with the initial state of the task. */
- prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
+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,
+ const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+{
+StackType_t *pxTopOfStack;
+UBaseType_t x;
- /* Initialize the TCB stack to look as if the task was already running,
- but had been interrupted by the scheduler. The return address is set
- to the start of the task function. Once the stack has been initialised
- the top of stack variable is updated. */
- #if( portUSING_MPU_WRAPPERS == 1 )
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ /* Should the task be created in privileged mode? */
+ BaseType_t xRunPrivileged;
+ if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
{
- pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ xRunPrivileged = pdTRUE;
}
- #else /* portUSING_MPU_WRAPPERS */
+ else
+ {
+ xRunPrivileged = pdFALSE;
+ }
+ uxPriority &= ~portPRIVILEGE_BIT;
+ #endif /* portUSING_MPU_WRAPPERS == 1 */
+
+ /* Avoid dependency on memset() if it is not required. */
+ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 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 /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
+
+ /* Calculate the top of stack address. This depends on whether the stack
+ grows from high memory to low (as per the 80x86) or vice versa.
+ portSTACK_GROWTH is used to make the result positive or negative as required
+ by the port. */
+ #if( portSTACK_GROWTH < 0 )
+ {
+ pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
+ pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
+
+ /* Check the alignment of the calculated top of stack is correct. */
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ #if( configRECORD_STACK_HIGH_ADDRESS == 1 )
{
- pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ /* Also record the stack's high address, which may assist
+ debugging. */
+ pxNewTCB->pxEndOfStack = pxTopOfStack;
}
- #endif /* portUSING_MPU_WRAPPERS */
+ #endif /* configRECORD_STACK_HIGH_ADDRESS */
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ pxTopOfStack = pxNewTCB->pxStack;
+
+ /* Check the alignment of the stack buffer is correct. */
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
- if( ( void * ) pxCreatedTask != NULL )
+ /* The other extreme of the stack space is required if stack checking is
+ performed. */
+ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
+ }
+ #endif /* portSTACK_GROWTH */
+
+ /* Store the task name in the TCB. */
+ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
+ {
+ pxNewTCB->pcTaskName[ x ] = pcName[ x ];
+
+ /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
+ configMAX_TASK_NAME_LEN characters just in case the memory after the
+ string is not accessible (extremely unlikely). */
+ if( pcName[ x ] == 0x00 )
{
- /* Pass the TCB out - in an anonymous way. The calling function/
- task can use this as a handle to delete the task later if
- required.*/
- *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
+ break;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
+ }
- /* Ensure interrupts don't access the task lists while they are being
- updated. */
- taskENTER_CRITICAL();
+ /* Ensure the name string is terminated in the case that the string length
+ was greater or equal to configMAX_TASK_NAME_LEN. */
+ pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
+
+ /* This is used as an array index so must ensure it's not too large. First
+ remove the privilege bit if one is present. */
+ if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
+ {
+ uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ pxNewTCB->uxPriority = uxPriority;
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxNewTCB->uxBasePriority = uxPriority;
+ pxNewTCB->uxMutexesHeld = 0;
+ }
+ #endif /* configUSE_MUTEXES */
+
+ vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
+ vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
+
+ /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
+ back to the containing TCB from a generic item in a list. */
+ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
+
+ /* Event lists are always in priority order. */
+ listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
+
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ {
+ pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
+ }
+ #endif /* portCRITICAL_NESTING_IN_TCB */
+
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ {
+ pxNewTCB->pxTaskTag = NULL;
+ }
+ #endif /* configUSE_APPLICATION_TASK_TAG */
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ pxNewTCB->ulRunTimeCounter = 0UL;
+ }
+ #endif /* configGENERATE_RUN_TIME_STATS */
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ {
+ vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
+ }
+ #else
+ {
+ /* Avoid compiler warning about unreferenced parameter. */
+ ( void ) xRegions;
+ }
+ #endif
+
+ #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
+ {
+ for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
{
- uxCurrentNumberOfTasks++;
- if( pxCurrentTCB == NULL )
- {
- /* There are no other tasks, or all the other tasks are in
- the suspended state - make this the current task. */
- pxCurrentTCB = pxNewTCB;
+ pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
+ }
+ }
+ #endif
- if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
- {
- /* This is the first task to be created so do the preliminary
- initialisation required. We will not recover if this call
- fails, but we will report the failure. */
- prvInitialiseTaskLists();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ {
+ pxNewTCB->ulNotifiedValue = 0;
+ pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
+ }
+ #endif
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ {
+ /* Initialise this task's Newlib reent structure. */
+ _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
+ }
+ #endif
+
+ #if( INCLUDE_xTaskAbortDelay == 1 )
+ {
+ pxNewTCB->ucDelayAborted = pdFALSE;
+ }
+ #endif
+
+ /* Initialize the TCB stack to look as if the task was already running,
+ but had been interrupted by the scheduler. The return address is set
+ to the start of the task function. Once the stack has been initialised
+ the top of stack variable is updated. */
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ }
+ #else /* portUSING_MPU_WRAPPERS */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ }
+ #endif /* portUSING_MPU_WRAPPERS */
+
+ if( ( void * ) pxCreatedTask != NULL )
+ {
+ /* Pass the handle out in an anonymous way. The handle can be used to
+ change the created task's priority, delete the created task, etc.*/
+ *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
+{
+ /* Ensure interrupts don't access the task lists while the lists are being
+ updated. */
+ taskENTER_CRITICAL();
+ {
+ uxCurrentNumberOfTasks++;
+ if( pxCurrentTCB == NULL )
+ {
+ /* There are no other tasks, or all the other tasks are in
+ the suspended state - make this the current task. */
+ pxCurrentTCB = pxNewTCB;
+
+ if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
+ {
+ /* This is the first task to be created so do the preliminary
+ initialisation required. We will not recover if this call
+ fails, but we will report the failure. */
+ prvInitialiseTaskLists();
}
else
{
- /* If the scheduler is not already running, make this task the
- current task if it is the highest priority task to be created
- so far. */
- if( xSchedulerRunning == pdFALSE )
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* If the scheduler is not already running, make this task the
+ current task if it is the highest priority task to be created
+ so far. */
+ if( xSchedulerRunning == pdFALSE )
+ {
+ if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
{
- if( pxCurrentTCB->uxPriority <= uxPriority )
- {
- pxCurrentTCB = pxNewTCB;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ pxCurrentTCB = pxNewTCB;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
-
- uxTaskNumber++;
-
- #if ( configUSE_TRACE_FACILITY == 1 )
+ else
{
- /* Add a counter into the TCB for tracing only. */
- pxNewTCB->uxTCBNumber = uxTaskNumber;
+ mtCOVERAGE_TEST_MARKER();
}
- #endif /* configUSE_TRACE_FACILITY */
- traceTASK_CREATE( pxNewTCB );
+ }
- prvAddTaskToReadyList( pxNewTCB );
+ uxTaskNumber++;
- xReturn = pdPASS;
- portSETUP_TCB( pxNewTCB );
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ /* Add a counter into the TCB for tracing only. */
+ pxNewTCB->uxTCBNumber = uxTaskNumber;
}
- taskEXIT_CRITICAL();
- }
- else
- {
- xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
- traceTASK_CREATE_FAILED();
+ #endif /* configUSE_TRACE_FACILITY */
+ traceTASK_CREATE( pxNewTCB );
+
+ prvAddTaskToReadyList( pxNewTCB );
+
+ portSETUP_TCB( pxNewTCB );
}
+ taskEXIT_CRITICAL();
- if( xReturn == pdPASS )
+ if( xSchedulerRunning != pdFALSE )
{
- if( xSchedulerRunning != pdFALSE )
+ /* If the created task is of a higher priority than the current task
+ then it should run now. */
+ if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
{
- /* If the created task is of a higher priority than the current task
- then it should run now. */
- if( pxCurrentTCB->uxPriority < uxPriority )
- {
- taskYIELD_IF_USING_PREEMPTION();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
-
- return xReturn;
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
}
/*-----------------------------------------------------------*/
@@ -751,11 +1062,8 @@ StackType_t *pxTopOfStack;
being deleted. */
pxTCB = prvGetTCBFromHandle( xTaskToDelete );
- /* Remove task from the ready list and place in the termination list.
- This will stop the task from be scheduled. The idle task will check
- the termination list and free up any memory allocated by the
- scheduler for the TCB and stack. */
- if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
+ /* Remove task from the ready list. */
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
@@ -774,16 +1082,42 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
+ /* Increment the uxTaskNumber also so kernel aware debuggers can
+ detect that the task lists need re-generating. This is done before
+ portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
+ not return. */
+ uxTaskNumber++;
- /* Increment the ucTasksDeleted variable so the idle task knows
- there is a task that has been deleted and that it should therefore
- check the xTasksWaitingTermination list. */
- ++uxTasksDeleted;
+ if( pxTCB == pxCurrentTCB )
+ {
+ /* A task is deleting itself. This cannot complete within the
+ task itself, as a context switch to another task is required.
+ Place the task in the termination list. The idle task will
+ check the termination list and free up any memory allocated by
+ the scheduler for the TCB and stack of the deleted task. */
+ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
+
+ /* Increment the ucTasksDeleted variable so the idle task knows
+ there is a task that has been deleted and that it should therefore
+ check the xTasksWaitingTermination list. */
+ ++uxDeletedTasksWaitingCleanUp;
- /* Increment the uxTaskNumberVariable also so kernel aware debuggers
- can detect that the task lists need re-generating. */
- uxTaskNumber++;
+ /* The pre-delete hook is primarily for the Windows simulator,
+ in which Windows specific clean up operations are performed,
+ after which it is not possible to yield away from this task -
+ hence xYieldPending is used to latch that a context switch is
+ required. */
+ portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
+ }
+ else
+ {
+ --uxCurrentNumberOfTasks;
+ prvDeleteTCB( pxTCB );
+
+ /* Reset the next expected unblock time in case it referred to
+ the task that has just been deleted. */
+ prvResetNextTaskUnblockTime();
+ }
traceTASK_DELETE( pxTCB );
}
@@ -796,24 +1130,11 @@ StackType_t *pxTopOfStack;
if( pxTCB == pxCurrentTCB )
{
configASSERT( uxSchedulerSuspended == 0 );
-
- /* The pre-delete hook is primarily for the Windows simulator,
- in which Windows specific clean up operations are performed,
- after which it is not possible to yield away from this task -
- hence xYieldPending is used to latch that a context switch is
- required. */
- portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
portYIELD_WITHIN_API();
}
else
{
- /* Reset the next expected unblock time in case it referred to
- the task that has just been deleted. */
- taskENTER_CRITICAL();
- {
- prvResetNextTaskUnblockTime();
- }
- taskEXIT_CRITICAL();
+ mtCOVERAGE_TEST_MARKER();
}
}
}
@@ -877,23 +1198,11 @@ StackType_t *pxTopOfStack;
if( xShouldDelay != pdFALSE )
{
- traceTASK_DELAY_UNTIL();
-
- /* Remove the task from the ready list before adding it to the
- blocked list as the same list item is used for both lists. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is
- no need to check, and the port reset macro can be called
- directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ traceTASK_DELAY_UNTIL( xTimeToWake );
- prvAddCurrentTaskToDelayedList( xTimeToWake );
+ /* prvAddCurrentTaskToDelayedList() needs the block time, not
+ the time to wake, so subtract the current tick count. */
+ prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
}
else
{
@@ -921,10 +1230,8 @@ StackType_t *pxTopOfStack;
void vTaskDelay( const TickType_t xTicksToDelay )
{
- TickType_t xTimeToWake;
BaseType_t xAlreadyYielded = pdFALSE;
-
/* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( TickType_t ) 0U )
{
@@ -940,26 +1247,7 @@ StackType_t *pxTopOfStack;
This task cannot be in an event list as it is the currently
executing task. */
-
- /* Calculate the time to wake - this may overflow but this is
- not a problem. */
- xTimeToWake = xTickCount + xTicksToDelay;
-
- /* We must remove ourselves from the ready list before adding
- ourselves to the blocked list as the same list item is used for
- both lists. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is
- no need to check, and the port reset macro can be called
- directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- prvAddCurrentTaskToDelayedList( xTimeToWake );
+ prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
}
xAlreadyYielded = xTaskResumeAll();
}
@@ -983,7 +1271,7 @@ StackType_t *pxTopOfStack;
#endif /* INCLUDE_vTaskDelay */
/*-----------------------------------------------------------*/
-#if ( INCLUDE_eTaskGetState == 1 )
+#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )
eTaskState eTaskGetState( TaskHandle_t xTask )
{
@@ -1002,7 +1290,7 @@ StackType_t *pxTopOfStack;
{
taskENTER_CRITICAL();
{
- pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
+ pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
}
taskEXIT_CRITICAL();
@@ -1031,10 +1319,11 @@ StackType_t *pxTopOfStack;
#endif
#if ( INCLUDE_vTaskDelete == 1 )
- else if( pxStateList == &xTasksWaitingTermination )
+ else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
{
/* The task being queried is referenced from the deleted
- tasks list. */
+ tasks list, or it is not referenced from any lists at
+ all. */
eReturn = eDeleted;
}
#endif
@@ -1236,12 +1525,12 @@ StackType_t *pxTopOfStack;
nothing more than change it's priority variable. However, if
the task is in a ready list it needs to be removed and placed
in the list appropriate to its new priority. */
- if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
{
/* The task is currently in its ready list - remove before adding
it to it's new ready list. As we are in a critical section we
can do this even if the scheduler is suspended. */
- if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
/* It is known that the task is in its ready list so
there is no need to check again and the port level
@@ -1259,7 +1548,7 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- if( xYieldRequired == pdTRUE )
+ if( xYieldRequired != pdFALSE )
{
taskYIELD_IF_USING_PREEMPTION();
}
@@ -1295,7 +1584,7 @@ StackType_t *pxTopOfStack;
/* Remove task from the ready/delayed list and place in the
suspended list. */
- if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
@@ -1314,10 +1603,25 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
+ vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
}
taskEXIT_CRITICAL();
+ if( xSchedulerRunning != pdFALSE )
+ {
+ /* Reset the next expected unblock time in case it referred to the
+ task that is now in the Suspended state. */
+ taskENTER_CRITICAL();
+ {
+ prvResetNextTaskUnblockTime();
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
if( pxTCB == pxCurrentTCB )
{
if( xSchedulerRunning != pdFALSE )
@@ -1347,21 +1651,7 @@ StackType_t *pxTopOfStack;
}
else
{
- if( xSchedulerRunning != pdFALSE )
- {
- /* A task other than the currently running task was suspended,
- reset the next expected unblock time in case it referred to the
- task that is now in the Suspended state. */
- taskENTER_CRITICAL();
- {
- prvResetNextTaskUnblockTime();
- }
- taskEXIT_CRITICAL();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ mtCOVERAGE_TEST_MARKER();
}
}
@@ -1382,7 +1672,7 @@ StackType_t *pxTopOfStack;
configASSERT( xTask );
/* Is the task being resumed actually in the suspended list? */
- if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
@@ -1429,13 +1719,13 @@ StackType_t *pxTopOfStack;
{
taskENTER_CRITICAL();
{
- if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
+ if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
{
traceTASK_RESUME( pxTCB );
/* As we are in a critical section we can access the ready
lists even if the scheduler is suspended. */
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
/* We may have just resumed a higher priority task. */
@@ -1498,7 +1788,7 @@ StackType_t *pxTopOfStack;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
- if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
+ if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
{
traceTASK_RESUME_FROM_ISR( pxTCB );
@@ -1516,7 +1806,7 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
@@ -1545,18 +1835,42 @@ void vTaskStartScheduler( void )
BaseType_t xReturn;
/* Add the idle task at the lowest priority. */
- #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
- /* Create the idle task, storing its handle in xIdleTaskHandle so it can
- be returned by the xTaskGetIdleTaskHandle() function. */
- xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_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. */
+ StaticTask_t *pxIdleTaskTCBBuffer = NULL;
+ StackType_t *pxIdleTaskStackBuffer = NULL;
+ uint32_t ulIdleTaskStackSize;
+
+ /* The Idle task is created using user provided RAM - obtain the
+ address of the RAM then create the idle task. */
+ vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
+ 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. */
+
+ if( xIdleTaskHandle != NULL )
+ {
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
}
#else
{
- /* Create the idle task without storing its handle. */
- xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
+ /* The Idle task is being created using dynamically allocated RAM. */
+ 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. */
}
- #endif /* INCLUDE_xTaskGetIdleTaskHandle */
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
#if ( configUSE_TIMERS == 1 )
{
@@ -1614,8 +1928,12 @@ BaseType_t xReturn;
/* This line will only be reached if the kernel could not be started,
because there was not enough FreeRTOS heap to create the idle task
or the timer task. */
- configASSERT( xReturn );
+ configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
}
+
+ /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
+ meaning xIdleTaskHandle is not used anywhere else. */
+ ( void ) xIdleTaskHandle;
}
/*-----------------------------------------------------------*/
@@ -1645,6 +1963,34 @@ void vTaskSuspendAll( void )
static TickType_t prvGetExpectedIdleTime( void )
{
TickType_t xReturn;
+ UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
+
+ /* uxHigherPriorityReadyTasks takes care of the case where
+ configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
+ task that are in the Ready state, even though the idle task is
+ running. */
+ #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
+ {
+ if( uxTopReadyPriority > tskIDLE_PRIORITY )
+ {
+ uxHigherPriorityReadyTasks = pdTRUE;
+ }
+ }
+ #else
+ {
+ const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
+
+ /* When port optimised task selection is used the uxTopReadyPriority
+ variable is used as a bit map. If bits other than the least
+ significant bit are set then there are tasks that have a priority
+ above the idle priority that are in the Ready state. This takes
+ care of the case where the co-operative scheduler is in use. */
+ if( uxTopReadyPriority > uxLeastSignificantBit )
+ {
+ uxHigherPriorityReadyTasks = pdTRUE;
+ }
+ }
+ #endif
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
{
@@ -1657,6 +2003,13 @@ void vTaskSuspendAll( void )
processed. */
xReturn = 0;
}
+ else if( uxHigherPriorityReadyTasks != pdFALSE )
+ {
+ /* There are tasks in the Ready state that have a priority above the
+ idle priority. This path can only be reached if
+ configUSE_PREEMPTION is 0. */
+ xReturn = 0;
+ }
else
{
xReturn = xNextTaskUnblockTime - xTickCount;
@@ -1670,7 +2023,7 @@ void vTaskSuspendAll( void )
BaseType_t xTaskResumeAll( void )
{
-TCB_t *pxTCB;
+TCB_t *pxTCB = NULL;
BaseType_t xAlreadyYielded = pdFALSE;
/* If uxSchedulerSuspended is zero then this function does not match a
@@ -1696,7 +2049,7 @@ BaseType_t xAlreadyYielded = pdFALSE;
{
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
/* If the moved task has a priority higher than the current
@@ -1711,31 +2064,48 @@ BaseType_t xAlreadyYielded = pdFALSE;
}
}
+ if( pxTCB != NULL )
+ {
+ /* A task was unblocked while the scheduler was suspended,
+ which may have prevented the next unblock time from being
+ re-calculated, in which case re-calculate it now. Mainly
+ important for low power tickless implementations, where
+ this can prevent an unnecessary exit from low power
+ state. */
+ prvResetNextTaskUnblockTime();
+ }
+
/* If any ticks occurred while the scheduler was suspended then
they should be processed now. This ensures the tick count does
not slip, and that any delayed tasks are resumed at the correct
time. */
- if( uxPendedTicks > ( UBaseType_t ) 0U )
{
- while( uxPendedTicks > ( UBaseType_t ) 0U )
+ UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
+
+ if( uxPendedCounts > ( UBaseType_t ) 0U )
{
- if( xTaskIncrementTick() != pdFALSE )
+ do
{
- xYieldPending = pdTRUE;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- --uxPendedTicks;
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ --uxPendedCounts;
+ } while( uxPendedCounts > ( UBaseType_t ) 0U );
+
+ uxPendedTicks = 0;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
}
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
}
- if( xYieldPending == pdTRUE )
+ if( xYieldPending != pdFALSE )
{
#if( configUSE_PREEMPTION != 0 )
{
@@ -1815,19 +2185,142 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
}
/*-----------------------------------------------------------*/
-#if ( INCLUDE_pcTaskGetTaskName == 1 )
+char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+{
+TCB_t *pxTCB;
- char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ /* If null is passed in here then the name of the calling task is being
+ queried. */
+ pxTCB = prvGetTCBFromHandle( xTaskToQuery );
+ configASSERT( pxTCB );
+ return &( pxTCB->pcTaskName[ 0 ] );
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetHandle == 1 )
+
+ static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )
{
- TCB_t *pxTCB;
+ TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;
+ UBaseType_t x;
+ char cNextChar;
- /* If null is passed in here then the name of the calling task is being queried. */
- pxTCB = prvGetTCBFromHandle( xTaskToQuery );
- configASSERT( pxTCB );
- return &( pxTCB->pcTaskName[ 0 ] );
+ /* This function is called with the scheduler suspended. */
+
+ if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
+
+ do
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
+
+ /* Check each character in the name looking for a match or
+ mismatch. */
+ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
+ {
+ cNextChar = pxNextTCB->pcTaskName[ x ];
+
+ if( cNextChar != pcNameToQuery[ x ] )
+ {
+ /* Characters didn't match. */
+ break;
+ }
+ else if( cNextChar == 0x00 )
+ {
+ /* Both strings terminated, a match must have been
+ found. */
+ pxReturn = pxNextTCB;
+ break;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ if( pxReturn != NULL )
+ {
+ /* The handle has been found. */
+ break;
+ }
+
+ } while( pxNextTCB != pxFirstTCB );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return pxReturn;
}
-#endif /* INCLUDE_pcTaskGetTaskName */
+#endif /* INCLUDE_xTaskGetHandle */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetHandle == 1 )
+
+ TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ UBaseType_t uxQueue = configMAX_PRIORITIES;
+ TCB_t* pxTCB;
+
+ /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
+ configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
+
+ vTaskSuspendAll();
+ {
+ /* Search the ready lists. */
+ do
+ {
+ uxQueue--;
+ pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
+
+ if( pxTCB != NULL )
+ {
+ /* Found the handle. */
+ break;
+ }
+
+ } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* Search the delayed lists. */
+ if( pxTCB == NULL )
+ {
+ pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
+ }
+
+ if( pxTCB == NULL )
+ {
+ pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ if( pxTCB == NULL )
+ {
+ /* Search the suspended list. */
+ pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
+ }
+ }
+ #endif
+
+ #if( INCLUDE_vTaskDelete == 1 )
+ {
+ if( pxTCB == NULL )
+ {
+ /* Search the deleted list. */
+ pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
+ }
+ }
+ #endif
+ }
+ ( void ) xTaskResumeAll();
+
+ return ( TaskHandle_t ) pxTCB;
+ }
+
+#endif /* INCLUDE_xTaskGetHandle */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
@@ -1846,20 +2339,20 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
do
{
uxQueue--;
- uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Fill in an TaskStatus_t structure with information on each
task in the Blocked state. */
- uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
- uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
#if( INCLUDE_vTaskDelete == 1 )
{
/* Fill in an TaskStatus_t structure with information on
each task that has been deleted but not yet cleaned up. */
- uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
}
#endif
@@ -1867,7 +2360,7 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
{
/* Fill in an TaskStatus_t structure with information on
each task in the Suspended state. */
- uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
}
#endif
@@ -1936,6 +2429,80 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
#endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/
+#if ( INCLUDE_xTaskAbortDelay == 1 )
+
+ BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
+ {
+ TCB_t *pxTCB = ( TCB_t * ) xTask;
+ BaseType_t xReturn = pdFALSE;
+
+ configASSERT( pxTCB );
+
+ vTaskSuspendAll();
+ {
+ /* A task can only be prematurely removed from the Blocked state if
+ it is actually in the Blocked state. */
+ if( eTaskGetState( xTask ) == eBlocked )
+ {
+ /* Remove the reference to the task from the blocked list. An
+ interrupt won't touch the xStateListItem because the
+ scheduler is suspended. */
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
+
+ /* Is the task waiting on an event also? If so remove it from
+ the event list too. Interrupts can touch the event list item,
+ even though the scheduler is suspended, so a critical section
+ is used. */
+ taskENTER_CRITICAL();
+ {
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ pxTCB->ucDelayAborted = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Place the unblocked task into the appropriate ready list. */
+ prvAddTaskToReadyList( pxTCB );
+
+ /* A task being unblocked cannot cause an immediate context
+ switch if preemption is turned off. */
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ /* Preemption is on, but a context switch should only be
+ performed if the unblocked task has a priority that is
+ equal to or higher than the currently executing task. */
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* Pend the yield to be performed when the scheduler
+ is unsuspended. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ xTaskResumeAll();
+
+ return xReturn;
+ }
+
+#endif /* INCLUDE_xTaskAbortDelay */
+/*----------------------------------------------------------*/
+
BaseType_t xTaskIncrementTick( void )
{
TCB_t * pxTCB;
@@ -1948,103 +2515,101 @@ BaseType_t xSwitchRequired = pdFALSE;
traceTASK_INCREMENT_TICK( xTickCount );
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
+ /* Minor optimisation. The tick count cannot change in this
+ block. */
+ const TickType_t xConstTickCount = xTickCount + 1;
+
/* Increment the RTOS tick, switching the delayed and overflowed
delayed lists if it wraps to 0. */
- ++xTickCount;
+ xTickCount = xConstTickCount;
+ if( xConstTickCount == ( TickType_t ) 0U )
{
- /* Minor optimisation. The tick count cannot change in this
- block. */
- const TickType_t xConstTickCount = xTickCount;
-
- if( xConstTickCount == ( TickType_t ) 0U )
- {
- taskSWITCH_DELAYED_LISTS();
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ taskSWITCH_DELAYED_LISTS();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
- /* See if this tick has made a timeout expire. Tasks are stored in
- the queue in the order of their wake time - meaning once one task
- has been found whose block time has not expired there is no need to
- look any further down the list. */
- if( xConstTickCount >= xNextTaskUnblockTime )
+ /* See if this tick has made a timeout expire. Tasks are stored in
+ the queue in the order of their wake time - meaning once one task
+ has been found whose block time has not expired there is no need to
+ look any further down the list. */
+ if( xConstTickCount >= xNextTaskUnblockTime )
+ {
+ for( ;; )
{
- for( ;; )
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
+ {
+ /* The delayed list is empty. Set xNextTaskUnblockTime
+ to the maximum possible value so it is extremely
+ unlikely that the
+ if( xTickCount >= xNextTaskUnblockTime ) test will pass
+ next time through. */
+ xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ break;
+ }
+ else
{
- if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
+ /* The delayed list is not empty, get the value of the
+ item at the head of the delayed list. This is the time
+ at which the task at the head of the delayed list must
+ be removed from the Blocked state. */
+ pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
+ xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
+
+ if( xConstTickCount < xItemValue )
{
- /* The delayed list is empty. Set xNextTaskUnblockTime
- to the maximum possible value so it is extremely
- unlikely that the
- if( xTickCount >= xNextTaskUnblockTime ) test will pass
- next time through. */
- xNextTaskUnblockTime = portMAX_DELAY;
+ /* It is not time to unblock this item yet, but the
+ item value is the time at which the task at the head
+ of the blocked list must be removed from the Blocked
+ state - so record the item value in
+ xNextTaskUnblockTime. */
+ xNextTaskUnblockTime = xItemValue;
break;
}
else
{
- /* The delayed list is not empty, get the value of the
- item at the head of the delayed list. This is the time
- at which the task at the head of the delayed list must
- be removed from the Blocked state. */
- pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
- xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
-
- if( xConstTickCount < xItemValue )
- {
- /* It is not time to unblock this item yet, but the
- item value is the time at which the task at the head
- of the blocked list must be removed from the Blocked
- state - so record the item value in
- xNextTaskUnblockTime. */
- xNextTaskUnblockTime = xItemValue;
- break;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ mtCOVERAGE_TEST_MARKER();
+ }
- /* It is time to remove the item from the Blocked state. */
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ /* It is time to remove the item from the Blocked state. */
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
- /* Is the task waiting on an event also? If so remove
- it from the event list. */
- if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ /* Is the task waiting on an event also? If so remove
+ it from the event list. */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Place the unblocked task into the appropriate ready
+ list. */
+ prvAddTaskToReadyList( pxTCB );
+
+ /* A task being unblocked cannot cause an immediate
+ context switch if preemption is turned off. */
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ /* Preemption is on, but a context switch should
+ only be performed if the unblocked task has a
+ priority that is equal to or higher than the
+ currently executing task. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
- ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ xSwitchRequired = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
-
- /* Place the unblocked task into the appropriate ready
- list. */
- prvAddTaskToReadyList( pxTCB );
-
- /* A task being unblocked cannot cause an immediate
- context switch if preemption is turned off. */
- #if ( configUSE_PREEMPTION == 1 )
- {
- /* Preemption is on, but a context switch should
- only be performed if the unblocked task has a
- priority that is equal to or higher than the
- currently executing task. */
- if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
- {
- xSwitchRequired = pdTRUE;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- #endif /* configUSE_PREEMPTION */
}
+ #endif /* configUSE_PREEMPTION */
}
}
}
@@ -2222,9 +2787,9 @@ void vTaskSwitchContext( void )
#endif
/* Add the amount of time the task has been running to the
- accumulated time so far. The time the task started running was
+ accumulated time so far. The time the task started running was
stored in ulTaskSwitchedInTime. Note that there is no overflow
- protection here so count values are only valid until the timer
+ protection here so count values are only valid until the timer
overflows. The guard against negative values is to protect
against suspect run time stat counter implementations - which
are provided by the application, not the kernel. */
@@ -2261,8 +2826,6 @@ void vTaskSwitchContext( void )
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
{
-TickType_t xTimeToWake;
-
configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
@@ -2274,54 +2837,12 @@ TickType_t xTimeToWake;
list is locked, preventing simultaneous access from interrupts. */
vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
- /* The task must be removed from from the ready list before it is added to
- the blocked list as the same list item is used for both lists. Exclusive
- access to the ready lists guaranteed because the scheduler is locked. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is no need to
- check, and the port reset macro can be called directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- #if ( INCLUDE_vTaskSuspend == 1 )
- {
- if( xTicksToWait == portMAX_DELAY )
- {
- /* Add the task to the suspended task list instead of a delayed task
- list to ensure the task is not woken by a timing event. It will
- block indefinitely. */
- vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* Calculate the time at which the task should be woken if the event
- does not occur. This may overflow but this doesn't matter, the
- scheduler will handle it. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- }
- #else /* INCLUDE_vTaskSuspend */
- {
- /* Calculate the time at which the task should be woken if the event does
- not occur. This may overflow but this doesn't matter, the scheduler
- will handle it. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- #endif /* INCLUDE_vTaskSuspend */
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
}
/*-----------------------------------------------------------*/
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
{
-TickType_t xTimeToWake;
-
configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
@@ -2340,56 +2861,14 @@ TickType_t xTimeToWake;
the task level). */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
- /* The task must be removed from the ready list before it is added to the
- blocked list. Exclusive access can be assured to the ready list as the
- scheduler is locked. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is no need to
- check, and the port reset macro can be called directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- #if ( INCLUDE_vTaskSuspend == 1 )
- {
- if( xTicksToWait == portMAX_DELAY )
- {
- /* Add the task to the suspended task list instead of a delayed task
- list to ensure it is not woken by a timing event. It will block
- indefinitely. */
- vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* Calculate the time at which the task should be woken if the event
- does not occur. This may overflow but this doesn't matter, the
- kernel will manage it correctly. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- }
- #else /* INCLUDE_vTaskSuspend */
- {
- /* Calculate the time at which the task should be woken if the event does
- not occur. This may overflow but this doesn't matter, the kernel
- will manage it correctly. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- #endif /* INCLUDE_vTaskSuspend */
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
}
/*-----------------------------------------------------------*/
-#if configUSE_TIMERS == 1
+#if( configUSE_TIMERS == 1 )
- void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
+ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
{
- TickType_t xTimeToWake;
-
configASSERT( pxEventList );
/* This function should not be called by application code hence the
@@ -2404,59 +2883,16 @@ TickType_t xTimeToWake;
can be used in place of vListInsert. */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
- /* We must remove this task from the ready list before adding it to the
- blocked list as the same list item is used for both lists. This
- function is called with the scheduler locked so interrupts will not
- access the lists at the same time. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is no need to
- check, and the port reset macro can be called directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- /* If vTaskSuspend() is available then the suspended task list is also
- available and a task that is blocking indefinitely can enter the
- suspended state (it is not really suspended as it will re-enter the
- Ready state when the event it is waiting indefinitely for occurs).
- Blocking indefinitely is useful when using tickless idle mode as when
- all tasks are blocked indefinitely all timers can be turned off. */
- #if( INCLUDE_vTaskSuspend == 1 )
+ /* If the task should block indefinitely then set the block time to a
+ value that will be recognised as an indefinite delay inside the
+ prvAddCurrentTaskToDelayedList() function. */
+ if( xWaitIndefinitely != pdFALSE )
{
- if( xWaitIndefinitely == pdTRUE )
- {
- /* Add the task to the suspended task list instead of a delayed
- task list to ensure the task is not woken by a timing event. It
- will block indefinitely. */
- vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* Calculate the time at which the task should be woken if the
- event does not occur. This may overflow but this doesn't
- matter. */
- xTimeToWake = xTickCount + xTicksToWait;
- traceTASK_DELAY_UNTIL();
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
+ xTicksToWait = portMAX_DELAY;
}
- #else
- {
- /* Calculate the time at which the task should be woken if the event
- does not occur. This may overflow but this doesn't matter. */
- xTimeToWake = xTickCount + xTicksToWait;
- traceTASK_DELAY_UNTIL();
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- /* Remove compiler warnings when INCLUDE_vTaskSuspend() is not
- defined. */
- ( void ) xWaitIndefinitely;
- }
- #endif
+ traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
+ prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
}
#endif /* configUSE_TIMERS */
@@ -2486,7 +2922,7 @@ BaseType_t xReturn;
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
- ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );
}
else
@@ -2551,7 +2987,7 @@ BaseType_t xReturn;
/* Remove the task from the delayed list and add it to the ready list. The
scheduler is suspended so interrupts will not be accessing the ready
lists. */
- ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
@@ -2595,29 +3031,41 @@ BaseType_t xReturn;
/* Minor optimisation. The tick count cannot change in this block. */
const TickType_t xConstTickCount = xTickCount;
+ #if( INCLUDE_xTaskAbortDelay == 1 )
+ if( pxCurrentTCB->ucDelayAborted != pdFALSE )
+ {
+ /* The delay was aborted, which is not the same as a time out,
+ but has the same result. */
+ pxCurrentTCB->ucDelayAborted = pdFALSE;
+ xReturn = pdTRUE;
+ }
+ else
+ #endif
+
#if ( INCLUDE_vTaskSuspend == 1 )
- /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
- the maximum block time then the task should block indefinitely, and
- therefore never time out. */
if( *pxTicksToWait == portMAX_DELAY )
{
+ /* If INCLUDE_vTaskSuspend is set to 1 and the block time
+ specified is the maximum block time then the task should block
+ indefinitely, and therefore never time out. */
xReturn = pdFALSE;
}
- else /* We are not blocking indefinitely, perform the checks below. */
+ else
#endif
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
{
- /* The tick count is greater than the time at which vTaskSetTimeout()
- was called, but has also overflowed since vTaskSetTimeOut() was called.
- It must have wrapped all the way around and gone past us again. This
- passed since vTaskSetTimeout() was called. */
+ /* The tick count is greater than the time at which
+ vTaskSetTimeout() was called, but has also overflowed since
+ vTaskSetTimeOut() was called. It must have wrapped all the way
+ around and gone past again. This passed since vTaskSetTimeout()
+ was called. */
xReturn = pdTRUE;
}
- else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
+ else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
{
/* Not a genuine timeout. Adjust parameters for time remaining. */
- *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
+ *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
vTaskSetTimeOutState( pxTimeOut );
xReturn = pdFALSE;
}
@@ -2692,9 +3140,13 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
/* Stop warnings. */
( void ) pvParameters;
+ /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
+ SCHEDULER IS STARTED. **/
+
for( ;; )
{
- /* See if any tasks have been deleted. */
+ /* See if any tasks have deleted themselves - if so then the idle task
+ is responsible for freeing the deleted task's TCB and stack. */
prvCheckTasksWaitingTermination();
#if ( configUSE_PREEMPTION == 0 )
@@ -2830,116 +3282,6 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
-static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-{
-UBaseType_t x;
-
- /* Store the task name in the TCB. */
- for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
- {
- pxTCB->pcTaskName[ x ] = pcName[ x ];
-
- /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
- configMAX_TASK_NAME_LEN characters just in case the memory after the
- string is not accessible (extremely unlikely). */
- if( pcName[ x ] == 0x00 )
- {
- break;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
-
- /* Ensure the name string is terminated in the case that the string length
- was greater or equal to configMAX_TASK_NAME_LEN. */
- pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
-
- /* This is used as an array index so must ensure it's not too large. First
- remove the privilege bit if one is present. */
- if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
- {
- uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- pxTCB->uxPriority = uxPriority;
- #if ( configUSE_MUTEXES == 1 )
- {
- pxTCB->uxBasePriority = uxPriority;
- pxTCB->uxMutexesHeld = 0;
- }
- #endif /* configUSE_MUTEXES */
-
- vListInitialiseItem( &( pxTCB->xGenericListItem ) );
- vListInitialiseItem( &( pxTCB->xEventListItem ) );
-
- /* Set the pxTCB as a link back from the ListItem_t. This is so we can get
- back to the containing TCB from a generic item in a list. */
- listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
-
- /* Event lists are always in priority order. */
- listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
- listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
-
- #if ( portCRITICAL_NESTING_IN_TCB == 1 )
- {
- pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
- }
- #endif /* portCRITICAL_NESTING_IN_TCB */
-
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- {
- pxTCB->pxTaskTag = NULL;
- }
- #endif /* configUSE_APPLICATION_TASK_TAG */
-
- #if ( configGENERATE_RUN_TIME_STATS == 1 )
- {
- pxTCB->ulRunTimeCounter = 0UL;
- }
- #endif /* configGENERATE_RUN_TIME_STATS */
-
- #if ( portUSING_MPU_WRAPPERS == 1 )
- {
- vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
- }
- #else /* portUSING_MPU_WRAPPERS */
- {
- ( void ) xRegions;
- ( void ) usStackDepth;
- }
- #endif /* portUSING_MPU_WRAPPERS */
-
- #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
- {
- for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
- {
- pxTCB->pvThreadLocalStoragePointers[ x ] = NULL;
- }
- }
- #endif
-
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- {
- pxTCB->ulNotifiedValue = 0;
- pxTCB->eNotifyState = eNotWaitingNotification;
- }
- #endif
-
- #if ( configUSE_NEWLIB_REENTRANT == 1 )
- {
- /* Initialise this task's Newlib reent structure. */
- _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
- }
- #endif /* configUSE_NEWLIB_REENTRANT */
-}
-/*-----------------------------------------------------------*/
-
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
@@ -2989,7 +3331,7 @@ UBaseType_t x;
the calling task. */
pxTCB = prvGetTCBFromHandle( xTaskToModify );
- vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
+ vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
}
#endif /* portUSING_MPU_WRAPPERS */
@@ -3029,13 +3371,16 @@ UBaseType_t uxPriority;
static void prvCheckTasksWaitingTermination( void )
{
+
+ /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
+
#if ( INCLUDE_vTaskDelete == 1 )
{
BaseType_t xListIsEmpty;
/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
too often in the idle task. */
- while( uxTasksDeleted > ( UBaseType_t ) 0U )
+ while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
{
vTaskSuspendAll();
{
@@ -3050,9 +3395,9 @@ static void prvCheckTasksWaitingTermination( void )
taskENTER_CRITICAL();
{
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
--uxCurrentNumberOfTasks;
- --uxTasksDeleted;
+ --uxDeletedTasksWaitingCleanUp;
}
taskEXIT_CRITICAL();
@@ -3064,118 +3409,102 @@ static void prvCheckTasksWaitingTermination( void )
}
}
}
- #endif /* vTaskDelete */
+ #endif /* INCLUDE_vTaskDelete */
}
/*-----------------------------------------------------------*/
-static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
-{
- /* The list item will be inserted in wake time order. */
- listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+#if( configUSE_TRACE_FACILITY == 1 )
- if( xTimeToWake < xTickCount )
+ void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
{
- /* Wake time has overflowed. Place this item in the overflow list. */
- vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* The wake time has not overflowed, so the current block list is used. */
- vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
-
- /* If the task entering the blocked state was placed at the head of the
- list of blocked tasks then xNextTaskUnblockTime needs to be updated
- too. */
- if( xTimeToWake < xNextTaskUnblockTime )
- {
- xNextTaskUnblockTime = xTimeToWake;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
-}
-/*-----------------------------------------------------------*/
+ TCB_t *pxTCB;
-static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
-{
-TCB_t *pxNewTCB;
+ /* xTask is NULL then get the state of the calling task. */
+ pxTCB = prvGetTCBFromHandle( xTask );
- /* If the stack grows down then allocate the stack then the TCB so the stack
- does not grow into the TCB. Likewise if the stack grows up then allocate
- the TCB then the stack. */
- #if( portSTACK_GROWTH > 0 )
- {
- /* Allocate space for the TCB. Where the memory comes from depends on
- the implementation of the port malloc function. */
- pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+ pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
+ pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );
+ pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
+ pxTaskStatus->pxStackBase = pxTCB->pxStack;
+ pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
- if( pxNewTCB != NULL )
+ #if ( INCLUDE_vTaskSuspend == 1 )
{
- /* Allocate space for the stack used by the task being created.
- The base of the stack memory stored in the TCB so the task can
- be deleted later if required. */
- pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
-
- if( pxNewTCB->pxStack == NULL )
+ /* If the task is in the suspended list then there is a chance it is
+ actually just blocked indefinitely - so really it should be reported as
+ being in the Blocked state. */
+ if( pxTaskStatus->eCurrentState == eSuspended )
{
- /* Could not allocate the stack. Delete the allocated TCB. */
- vPortFree( pxNewTCB );
- pxNewTCB = NULL;
+ vTaskSuspendAll();
+ {
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ pxTaskStatus->eCurrentState = eBlocked;
+ }
+ }
+ xTaskResumeAll();
}
}
- }
- #else /* portSTACK_GROWTH */
- {
- StackType_t *pxStack;
+ #endif /* INCLUDE_vTaskSuspend */
- /* Allocate space for the stack used by the task being created. */
- pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
+ }
+ #else
+ {
+ pxTaskStatus->uxBasePriority = 0;
+ }
+ #endif
- if( pxStack != NULL )
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
{
- /* Allocate space for the TCB. Where the memory comes from depends
- on the implementation of the port malloc function. */
- pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+ pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
+ }
+ #else
+ {
+ pxTaskStatus->ulRunTimeCounter = 0;
+ }
+ #endif
- if( pxNewTCB != NULL )
+ /* Obtaining the task state is a little fiddly, so is only done if the value
+ of eState passed into this function is eInvalid - otherwise the state is
+ just set to whatever is passed in. */
+ if( eState != eInvalid )
+ {
+ pxTaskStatus->eCurrentState = eState;
+ }
+ else
+ {
+ pxTaskStatus->eCurrentState = eTaskGetState( xTask );
+ }
+
+ /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
+ parameter is provided to allow it to be skipped. */
+ if( xGetFreeStackSpace != pdFALSE )
+ {
+ #if ( portSTACK_GROWTH > 0 )
{
- /* Store the stack location in the TCB. */
- pxNewTCB->pxStack = pxStack;
+ pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
}
- else
+ #else
{
- /* The stack cannot be used as the TCB was not created. Free it
- again. */
- vPortFree( pxStack );
+ pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
}
+ #endif
}
else
{
- pxNewTCB = NULL;
- }
- }
- #endif /* portSTACK_GROWTH */
-
- if( pxNewTCB != NULL )
- {
- /* Avoid dependency on memset() if it is not required. */
- #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
- {
- /* Just to help debugging. */
- ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
+ pxTaskStatus->usStackHighWaterMark = 0;
}
- #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
}
- return pxNewTCB;
-}
+#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
- static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
+ static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
{
volatile TCB_t *pxNextTCB, *pxFirstTCB;
UBaseType_t uxTask = 0;
@@ -3191,60 +3520,8 @@ TCB_t *pxNewTCB;
do
{
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
-
- pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;
- pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );
- pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
- pxTaskStatusArray[ uxTask ].eCurrentState = eState;
- pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
-
- #if ( INCLUDE_vTaskSuspend == 1 )
- {
- /* If the task is in the suspended list then there is a chance
- it is actually just blocked indefinitely - so really it should
- be reported as being in the Blocked state. */
- if( eState == eSuspended )
- {
- if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )
- {
- pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;
- }
- }
- }
- #endif /* INCLUDE_vTaskSuspend */
-
- #if ( configUSE_MUTEXES == 1 )
- {
- pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
- }
- #else
- {
- pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
- }
- #endif
-
- #if ( configGENERATE_RUN_TIME_STATS == 1 )
- {
- pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
- }
- #else
- {
- pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
- }
- #endif
-
- #if ( portSTACK_GROWTH > 0 )
- {
- pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );
- }
- #else
- {
- pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );
- }
- #endif
-
+ vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
uxTask++;
-
} while( pxNextTCB != pxFirstTCB );
}
else
@@ -3323,22 +3600,40 @@ TCB_t *pxNewTCB;
}
#endif /* configUSE_NEWLIB_REENTRANT */
- #if( portUSING_MPU_WRAPPERS == 1 )
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
{
- /* Only free the stack if it was allocated dynamically in the first
- place. */
- if( pxTCB->xUsingStaticallyAllocatedStack == pdFALSE )
- {
- vPortFreeAligned( pxTCB->pxStack );
- }
+ /* The task can only have been allocated dynamically - free both
+ the stack and TCB. */
+ vPortFree( pxTCB->pxStack );
+ vPortFree( pxTCB );
}
- #else
+ #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
{
- vPortFreeAligned( pxTCB->pxStack );
+ /* The task could have been allocated statically or dynamically, so
+ check what was statically allocated before trying to free the
+ memory. */
+ if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
+ {
+ /* Both the stack and TCB were allocated dynamically, so both
+ must be freed. */
+ vPortFree( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+ else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
+ {
+ /* Only the stack was statically allocated, so the TCB is the
+ only memory that must be freed. */
+ vPortFree( pxTCB );
+ }
+ else
+ {
+ /* Neither the stack nor the TCB were allocated dynamically, so
+ nothing needs to be freed. */
+ configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
+ mtCOVERAGE_TEST_MARKER();
+ }
}
- #endif
-
- vPortFree( pxTCB );
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
#endif /* INCLUDE_vTaskDelete */
@@ -3363,7 +3658,7 @@ TCB_t *pxTCB;
which the task at the head of the delayed list should be removed
from the Blocked state. */
( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
- xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
+ xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
}
}
/*-----------------------------------------------------------*/
@@ -3442,9 +3737,9 @@ TCB_t *pxTCB;
/* If the task being modified is in the ready state it will need
to be moved into a new list. */
- if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
{
- if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
@@ -3509,7 +3804,7 @@ TCB_t *pxTCB;
given from an interrupt, and if a mutex is given by the
holding task then it must be the running state task. Remove
the holding task from the ready list. */
- if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
@@ -3689,7 +3984,9 @@ TCB_t *pxTCB;
function is executing. */
uxArraySize = uxCurrentNumberOfTasks;
- /* Allocate an array index for each task. */
+ /* Allocate an array index for each task. NOTE! if
+ configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
+ equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL )
@@ -3729,7 +4026,8 @@ TCB_t *pxTCB;
pcWriteBuffer += strlen( pcWriteBuffer );
}
- /* Free the array again. */
+ /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
+ is 0 then vPortFree() will be #defined to nothing. */
vPortFree( pxTaskStatusArray );
}
else
@@ -3787,7 +4085,9 @@ TCB_t *pxTCB;
function is executing. */
uxArraySize = uxCurrentNumberOfTasks;
- /* Allocate an array index for each task. */
+ /* Allocate an array index for each task. NOTE! If
+ configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
+ equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL )
@@ -3853,7 +4153,8 @@ TCB_t *pxTCB;
mtCOVERAGE_TEST_MARKER();
}
- /* Free the array again. */
+ /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
+ is 0 then vPortFree() will be #defined to nothing. */
vPortFree( pxTaskStatusArray );
}
else
@@ -3900,7 +4201,6 @@ TickType_t uxReturn;
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
{
- TickType_t xTimeToWake;
uint32_t ulReturn;
taskENTER_CRITICAL();
@@ -3909,55 +4209,11 @@ TickType_t uxReturn;
if( pxCurrentTCB->ulNotifiedValue == 0UL )
{
/* Mark this task as waiting for a notification. */
- pxCurrentTCB->eNotifyState = eWaitingNotification;
+ pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 )
{
- /* The task is going to block. First it must be removed
- from the ready list. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is
- no need to check, and the port reset macro can be called
- directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- #if ( INCLUDE_vTaskSuspend == 1 )
- {
- if( xTicksToWait == portMAX_DELAY )
- {
- /* Add the task to the suspended task list instead
- of a delayed task list to ensure the task is not
- woken by a timing event. It will block
- indefinitely. */
- vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* Calculate the time at which the task should be
- woken if no notification events occur. This may
- overflow but this doesn't matter, the scheduler will
- handle it. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- }
- #else /* INCLUDE_vTaskSuspend */
- {
- /* Calculate the time at which the task should be
- woken if the event does not occur. This may
- overflow but this doesn't matter, the scheduler will
- handle it. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- #endif /* INCLUDE_vTaskSuspend */
-
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
traceTASK_NOTIFY_TAKE_BLOCK();
/* All ports are written to allow a yield in a critical
@@ -3991,7 +4247,7 @@ TickType_t uxReturn;
}
else
{
- ( pxCurrentTCB->ulNotifiedValue )--;
+ pxCurrentTCB->ulNotifiedValue = ulReturn - 1;
}
}
else
@@ -3999,7 +4255,7 @@ TickType_t uxReturn;
mtCOVERAGE_TEST_MARKER();
}
- pxCurrentTCB->eNotifyState = eNotWaitingNotification;
+ pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
}
taskEXIT_CRITICAL();
@@ -4013,13 +4269,12 @@ TickType_t uxReturn;
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
{
- TickType_t xTimeToWake;
BaseType_t xReturn;
taskENTER_CRITICAL();
{
/* Only block if a notification is not already pending. */
- if( pxCurrentTCB->eNotifyState != eNotified )
+ if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
{
/* Clear bits in the task's notification value as bits may get
set by the notifying task or interrupt. This can be used to
@@ -4027,55 +4282,11 @@ TickType_t uxReturn;
pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
/* Mark this task as waiting for a notification. */
- pxCurrentTCB->eNotifyState = eWaitingNotification;
+ pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 )
{
- /* The task is going to block. First it must be removed
- from the ready list. */
- if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
- {
- /* The current task must be in a ready list, so there is
- no need to check, and the port reset macro can be called
- directly. */
- portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- #if ( INCLUDE_vTaskSuspend == 1 )
- {
- if( xTicksToWait == portMAX_DELAY )
- {
- /* Add the task to the suspended task list instead
- of a delayed task list to ensure the task is not
- woken by a timing event. It will block
- indefinitely. */
- vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
- }
- else
- {
- /* Calculate the time at which the task should be
- woken if no notification events occur. This may
- overflow but this doesn't matter, the scheduler will
- handle it. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- }
- #else /* INCLUDE_vTaskSuspend */
- {
- /* Calculate the time at which the task should be
- woken if the event does not occur. This may
- overflow but this doesn't matter, the scheduler will
- handle it. */
- xTimeToWake = xTickCount + xTicksToWait;
- prvAddCurrentTaskToDelayedList( xTimeToWake );
- }
- #endif /* INCLUDE_vTaskSuspend */
-
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
traceTASK_NOTIFY_WAIT_BLOCK();
/* All ports are written to allow a yield in a critical
@@ -4107,11 +4318,11 @@ TickType_t uxReturn;
*pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
}
- /* If eNotifyValue is set then either the task never entered the
+ /* If ucNotifyValue is set then either the task never entered the
blocked state (because a notification was already pending) or the
task unblocked because of a notification. Otherwise the task
unblocked because of a timeout. */
- if( pxCurrentTCB->eNotifyState == eWaitingNotification )
+ if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
{
/* A notification was not received. */
xReturn = pdFALSE;
@@ -4124,7 +4335,7 @@ TickType_t uxReturn;
xReturn = pdTRUE;
}
- pxCurrentTCB->eNotifyState = eNotWaitingNotification;
+ pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
}
taskEXIT_CRITICAL();
@@ -4139,8 +4350,8 @@ TickType_t uxReturn;
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
{
TCB_t * pxTCB;
- eNotifyValue eOriginalNotifyState;
BaseType_t xReturn = pdPASS;
+ uint8_t ucOriginalNotifyState;
configASSERT( xTaskToNotify );
pxTCB = ( TCB_t * ) xTaskToNotify;
@@ -4152,9 +4363,9 @@ TickType_t uxReturn;
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
}
- eOriginalNotifyState = pxTCB->eNotifyState;
+ ucOriginalNotifyState = pxTCB->ucNotifyState;
- pxTCB->eNotifyState = eNotified;
+ pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
switch( eAction )
{
@@ -4171,7 +4382,7 @@ TickType_t uxReturn;
break;
case eSetValueWithoutOverwrite :
- if( eOriginalNotifyState != eNotified )
+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{
pxTCB->ulNotifiedValue = ulValue;
}
@@ -4192,9 +4403,9 @@ TickType_t uxReturn;
/* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */
- if( eOriginalNotifyState == eWaitingNotification )
+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
/* The task should not have been on an event list. */
@@ -4245,7 +4456,7 @@ TickType_t uxReturn;
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB;
- eNotifyValue eOriginalNotifyState;
+ uint8_t ucOriginalNotifyState;
BaseType_t xReturn = pdPASS;
UBaseType_t uxSavedInterruptStatus;
@@ -4278,8 +4489,8 @@ TickType_t uxReturn;
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
}
- eOriginalNotifyState = pxTCB->eNotifyState;
- pxTCB->eNotifyState = eNotified;
+ ucOriginalNotifyState = pxTCB->ucNotifyState;
+ pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
switch( eAction )
{
@@ -4296,7 +4507,7 @@ TickType_t uxReturn;
break;
case eSetValueWithoutOverwrite :
- if( eOriginalNotifyState != eNotified )
+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{
pxTCB->ulNotifiedValue = ulValue;
}
@@ -4317,14 +4528,14 @@ TickType_t uxReturn;
/* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */
- if( eOriginalNotifyState == eWaitingNotification )
+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{
/* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
@@ -4342,6 +4553,13 @@ TickType_t uxReturn;
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
+ else
+ {
+ /* Mark that a yield is pending in case the user is not
+ using the "xHigherPriorityTaskWoken" parameter to an ISR
+ safe FreeRTOS function. */
+ xYieldPending = pdTRUE;
+ }
}
else
{
@@ -4362,7 +4580,7 @@ TickType_t uxReturn;
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB;
- eNotifyValue eOriginalNotifyState;
+ uint8_t ucOriginalNotifyState;
UBaseType_t uxSavedInterruptStatus;
configASSERT( xTaskToNotify );
@@ -4389,8 +4607,8 @@ TickType_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
- eOriginalNotifyState = pxTCB->eNotifyState;
- pxTCB->eNotifyState = eNotified;
+ ucOriginalNotifyState = pxTCB->ucNotifyState;
+ pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
/* 'Giving' is equivalent to incrementing a count in a counting
semaphore. */
@@ -4400,14 +4618,14 @@ TickType_t uxReturn;
/* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */
- if( eOriginalNotifyState == eWaitingNotification )
+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{
/* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
@@ -4425,6 +4643,13 @@ TickType_t uxReturn;
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
+ else
+ {
+ /* Mark that a yield is pending in case the user is not
+ using the "xHigherPriorityTaskWoken" parameter in an ISR
+ safe FreeRTOS function. */
+ xYieldPending = pdTRUE;
+ }
}
else
{
@@ -4446,17 +4671,15 @@ TickType_t uxReturn;
TCB_t *pxTCB;
BaseType_t xReturn;
- pxTCB = ( TCB_t * ) xTask;
-
/* If null is passed in here then it is the calling task that is having
its notification state cleared. */
- pxTCB = prvGetTCBFromHandle( pxTCB );
+ pxTCB = prvGetTCBFromHandle( xTask );
taskENTER_CRITICAL();
{
- if( pxTCB->eNotifyState == eNotified )
+ if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
{
- pxTCB->eNotifyState = eNotWaitingNotification;
+ pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
xReturn = pdPASS;
}
else
@@ -4470,8 +4693,133 @@ TickType_t uxReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+
+static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
+{
+TickType_t xTimeToWake;
+const TickType_t xConstTickCount = xTickCount;
+
+ #if( INCLUDE_xTaskAbortDelay == 1 )
+ {
+ /* About to enter a delayed list, so ensure the ucDelayAborted flag is
+ reset to pdFALSE so it can be detected as having been set to pdTRUE
+ when the task leaves the Blocked state. */
+ pxCurrentTCB->ucDelayAborted = pdFALSE;
+ }
+ #endif
+
+ /* Remove the task from the ready list before adding it to the blocked list
+ as the same list item is used for both lists. */
+ if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ /* The current task must be in a ready list, so there is no need to
+ check, and the port reset macro can be called directly. */
+ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
+ {
+ /* Add the task to the suspended task list instead of a delayed task
+ list to ensure it is not woken by a timing event. It will block
+ indefinitely. */
+ vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
+ }
+ else
+ {
+ /* Calculate the time at which the task should be woken if the event
+ does not occur. This may overflow but this doesn't matter, the
+ kernel will manage it correctly. */
+ xTimeToWake = xConstTickCount + xTicksToWait;
+
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
+
+ if( xTimeToWake < xConstTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the overflow
+ list. */
+ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so the current block list
+ is used. */
+ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+
+ /* If the task entering the blocked state was placed at the
+ head of the list of blocked tasks then xNextTaskUnblockTime
+ needs to be updated too. */
+ if( xTimeToWake < xNextTaskUnblockTime )
+ {
+ xNextTaskUnblockTime = xTimeToWake;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ }
+ #else /* INCLUDE_vTaskSuspend */
+ {
+ /* Calculate the time at which the task should be woken if the event
+ does not occur. This may overflow but this doesn't matter, the kernel
+ will manage it correctly. */
+ xTimeToWake = xConstTickCount + xTicksToWait;
+
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
+
+ if( xTimeToWake < xConstTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the overflow list. */
+ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so the current block list is used. */
+ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+
+ /* If the task entering the blocked state was placed at the head of the
+ list of blocked tasks then xNextTaskUnblockTime needs to be updated
+ too. */
+ if( xTimeToWake < xNextTaskUnblockTime )
+ {
+ xNextTaskUnblockTime = xTimeToWake;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
+ ( void ) xCanBlockIndefinitely;
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+}
+
#ifdef FREERTOS_MODULE_TEST
#include "tasks_test_access_functions.h"
#endif
+#if (configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1)
+ #include "freertos_tasks_c_additions.h"
+
+ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+ static void freertos_tasks_c_additions_init( void )
+ {
+ FREERTOS_TASKS_C_ADDITIONS_INIT();
+ }
+ #endif
+#endif
+
diff --git a/freertos/Source/timers.c b/freertos/Source/timers.c
index 560573b..d4a821a 100644
--- a/freertos/Source/timers.c
+++ b/freertos/Source/timers.c
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -112,6 +112,10 @@ typedef struct tmrTimerControl
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
#endif
+
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */
+ #endif
} xTIMER;
/* The old xTIMER name is maintained above then typedefed to the new Timer_t
@@ -167,16 +171,21 @@ PRIVILEGED_DATA static List_t *pxOverflowTimerList;
/* A queue that is used to send commands to the timer service task. */
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
+PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
+/*lint +e956 */
- PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
+/*-----------------------------------------------------------*/
-#endif
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
-/*lint +e956 */
+ /* If static allocation is supported then the application must provide the
+ following callback function - which enables the application to optionally
+ provide the memory that will be used by the timer task as the task's stack
+ and TCB. */
+ extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );
-/*-----------------------------------------------------------*/
+#endif
/*
* Initialise the infrastructure used by the timer service task if it has not
@@ -235,6 +244,16 @@ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIV
*/
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
+/*
+ * Called after a Timer_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewTimer( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/*-----------------------------------------------------------*/
BaseType_t xTimerCreateTimerTask( void )
@@ -249,18 +268,36 @@ BaseType_t xReturn = pdFAIL;
if( xTimerQueue != NULL )
{
- #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
- /* Create the timer task, storing its handle in xTimerTaskHandle so
- it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
- xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );
+ StaticTask_t *pxTimerTaskTCBBuffer = NULL;
+ StackType_t *pxTimerTaskStackBuffer = NULL;
+ uint32_t ulTimerTaskStackSize;
+
+ vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
+ xTimerTaskHandle = xTaskCreateStatic( prvTimerTask,
+ "Tmr Svc",
+ ulTimerTaskStackSize,
+ NULL,
+ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
+ pxTimerTaskStackBuffer,
+ pxTimerTaskTCBBuffer );
+
+ if( xTimerTaskHandle != NULL )
+ {
+ xReturn = pdPASS;
+ }
}
#else
{
- /* Create the timer task without storing its handle. */
- xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);
+ xReturn = xTaskCreate( prvTimerTask,
+ "Tmr Svc",
+ configTIMER_TASK_STACK_DEPTH,
+ NULL,
+ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
+ &xTimerTaskHandle );
}
- #endif
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
}
else
{
@@ -272,44 +309,108 @@ BaseType_t xReturn = pdFAIL;
}
/*-----------------------------------------------------------*/
-TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-{
-Timer_t *pxNewTimer;
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
- /* Allocate the timer structure. */
- if( xTimerPeriodInTicks == ( TickType_t ) 0U )
- {
- pxNewTimer = NULL;
- }
- else
+ TimerHandle_t xTimerCreate( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
+ Timer_t *pxNewTimer;
+
pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );
+
if( pxNewTimer != NULL )
{
- /* Ensure the infrastructure used by the timer service task has been
- created/initialised. */
- prvCheckForValidListAndQueue();
-
- /* Initialise the timer structure members using the function parameters. */
- pxNewTimer->pcTimerName = pcTimerName;
- pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
- pxNewTimer->uxAutoReload = uxAutoReload;
- pxNewTimer->pvTimerID = pvTimerID;
- pxNewTimer->pxCallbackFunction = pxCallbackFunction;
- vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
-
- traceTIMER_CREATE( pxNewTimer );
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
+
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* Timers can be created statically or dynamically, so note this
+ timer was created dynamically in case the timer is later
+ deleted. */
+ pxNewTimer->ucStaticallyAllocated = pdFALSE;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
}
- else
+
+ return pxNewTimer;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ Timer_t *pxNewTimer;
+
+ #if( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ variable of type StaticTimer_t equals the size of the real timer
+ structures. */
+ volatile size_t xSize = sizeof( StaticTimer_t );
+ configASSERT( xSize == sizeof( Timer_t ) );
+ }
+ #endif /* configASSERT_DEFINED */
+
+ /* A pointer to a StaticTimer_t structure MUST be provided, use it. */
+ configASSERT( pxTimerBuffer );
+ pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+
+ if( pxNewTimer != NULL )
{
- traceTIMER_CREATE_FAILED();
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
+
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Timers can be created statically or dynamically so note this
+ timer was created statically in case it is later deleted. */
+ pxNewTimer->ucStaticallyAllocated = pdTRUE;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
+
+ return pxNewTimer;
}
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewTimer( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+{
/* 0 is not a valid value for xTimerPeriodInTicks. */
configASSERT( ( xTimerPeriodInTicks > 0 ) );
- return ( TimerHandle_t ) pxNewTimer;
+ if( pxNewTimer != NULL )
+ {
+ /* Ensure the infrastructure used by the timer service task has been
+ created/initialised. */
+ prvCheckForValidListAndQueue();
+
+ /* Initialise the timer structure members using the function
+ parameters. */
+ pxNewTimer->pcTimerName = pcTimerName;
+ pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
+ pxNewTimer->uxAutoReload = uxAutoReload;
+ pxNewTimer->pvTimerID = pvTimerID;
+ pxNewTimer->pxCallbackFunction = pxCallbackFunction;
+ vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
+ traceTIMER_CREATE( pxNewTimer );
+ }
}
/*-----------------------------------------------------------*/
@@ -356,20 +457,36 @@ DaemonTaskMessage_t xMessage;
}
/*-----------------------------------------------------------*/
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
+TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
+{
+ /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
+ started, then xTimerTaskHandle will be NULL. */
+ configASSERT( ( xTimerTaskHandle != NULL ) );
+ return xTimerTaskHandle;
+}
+/*-----------------------------------------------------------*/
- TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
- {
- /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
- started, then xTimerTaskHandle will be NULL. */
- configASSERT( ( xTimerTaskHandle != NULL ) );
- return xTimerTaskHandle;
- }
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
+{
+Timer_t *pxTimer = ( Timer_t * ) xTimer;
-#endif
+ configASSERT( xTimer );
+ return pxTimer->xTimerPeriodInTicks;
+}
+/*-----------------------------------------------------------*/
+
+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
+{
+Timer_t * pxTimer = ( Timer_t * ) xTimer;
+TickType_t xReturn;
+
+ configASSERT( xTimer );
+ xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );
+ return xReturn;
+}
/*-----------------------------------------------------------*/
-const char * pcTimerGetTimerName( TimerHandle_t xTimer )
+const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
Timer_t *pxTimer = ( Timer_t * ) xTimer;
@@ -395,7 +512,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
/* The timer is inserted into a list using a time relative to anything
other than the current time. It will therefore be inserted into the
correct list relative to the time this task thinks it is now. */
- if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE )
+ if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )
{
/* The timer expired before it was added to the active timer
list. Reload it now. */
@@ -426,6 +543,18 @@ BaseType_t xListWasEmpty;
/* Just to avoid compiler warnings. */
( void ) pvParameters;
+ #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 )
+ {
+ extern void vApplicationDaemonTaskStartupHook( void );
+
+ /* Allow the application writer to execute some code in the context of
+ this task at the point the task starts executing. This is useful if the
+ application includes initialisation code that would benefit from
+ executing after the scheduler has been started. */
+ vApplicationDaemonTaskStartupHook();
+ }
+ #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */
+
for( ;; )
{
/* Query the timers list to see if it contains any timers, and if so,
@@ -562,7 +691,7 @@ BaseType_t xProcessTimerNow = pdFALSE;
{
/* Has the expiry time elapsed between the command to start/reset a
timer was issued, and the time the command was processed? */
- if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks )
+ if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
{
/* The time between a command being issued and the command being
processed actually exceeds the timers period. */
@@ -659,7 +788,7 @@ TickType_t xTimeNow;
case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_DONT_TRACE :
/* Start or restart a timer. */
- if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE )
+ if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )
{
/* The timer expired before it was added to the active
timer list. Process it now. */
@@ -694,19 +823,40 @@ TickType_t xTimeNow;
pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
- /* The new period does not really have a reference, and can be
- longer or shorter than the old one. The command time is
- therefore set to the current time, and as the period cannot be
- zero the next expiry time can only be in the future, meaning
- (unlike for the xTimerStart() case above) there is no fail case
- that needs to be handled here. */
+ /* The new period does not really have a reference, and can
+ be longer or shorter than the old one. The command time is
+ therefore set to the current time, and as the period cannot
+ be zero the next expiry time can only be in the future,
+ meaning (unlike for the xTimerStart() case above) there is
+ no fail case that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
case tmrCOMMAND_DELETE :
/* The timer has already been removed from the active list,
- just free up the memory. */
- vPortFree( pxTimer );
+ just free up the memory if the memory was dynamically
+ allocated. */
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+ {
+ /* The timer can only have been allocated dynamically -
+ free it again. */
+ vPortFree( pxTimer );
+ }
+ #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ {
+ /* The timer could have been allocated statically or
+ dynamically, so check before attempting to free the
+ memory. */
+ if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+ {
+ vPortFree( pxTimer );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
break;
default :
@@ -790,8 +940,21 @@ static void prvCheckForValidListAndQueue( void )
vListInitialise( &xActiveTimerList2 );
pxCurrentTimerList = &xActiveTimerList1;
pxOverflowTimerList = &xActiveTimerList2;
- xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
- configASSERT( xTimerQueue );
+
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* The timer queue is allocated statically in case
+ configSUPPORT_DYNAMIC_ALLOCATION is 0. */
+ static StaticQueue_t xStaticTimerQueue;
+ static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ];
+
+ xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );
+ }
+ #else
+ {
+ xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
+ }
+ #endif
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{