+#endif
/*
* Check all the required application specific macros have been defined.
* These macros are application specific and (as downloaded) are defined
@@ -129,30 +138,6 @@ 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 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.
-#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.
-#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.
-#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.
-#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.
-#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.
-#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
@@ -160,28 +145,41 @@ extern "C" {
#ifndef configMAX_PRIORITIES
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#endif
-
-/* Configuration sanity check. */
-#if ( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) )
- #error configUSE_MUTEXES must be set to 1 to use recursive mutexes
-#endif
#ifndef configUSE_CO_ROUTINES
#define configUSE_CO_ROUTINES 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_vTaskPrioritySet
+ #define INCLUDE_vTaskPrioritySet 0
+#endif
+
+#ifndef INCLUDE_uxTaskPriorityGet
+ #define INCLUDE_uxTaskPriorityGet 0
+#endif
+
+#ifndef INCLUDE_vTaskDelete
+ #define INCLUDE_vTaskDelete 0
+#endif
+
+#ifndef INCLUDE_vTaskSuspend
+ #define INCLUDE_vTaskSuspend 0
+#endif
+
+#ifndef INCLUDE_vTaskDelayUntil
+ #define INCLUDE_vTaskDelayUntil 0
+#endif
+
+#ifndef INCLUDE_vTaskDelay
+ #define INCLUDE_vTaskDelay 0
#endif
#ifndef INCLUDE_xTaskGetIdleTaskHandle
#define INCLUDE_xTaskGetIdleTaskHandle 0
#endif
-#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle
- #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#ifndef INCLUDE_xTaskAbortDelay
+ #define INCLUDE_xTaskAbortDelay 0
#endif
#ifndef INCLUDE_xQueueGetMutexHolder
@@ -192,16 +190,8 @@ extern "C" {
#define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
#endif
-#ifndef INCLUDE_pcTaskGetTaskName
- #define INCLUDE_pcTaskGetTaskName 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
+#ifndef INCLUDE_xTaskGetHandle
+ #define INCLUDE_xTaskGetHandle 0
#endif
#ifndef INCLUDE_uxTaskGetStackHighWaterMark
@@ -212,6 +202,40 @@ extern "C" {
#define INCLUDE_eTaskGetState 0
#endif
+#ifndef INCLUDE_xTaskResumeFromISR
+ #define INCLUDE_xTaskResumeFromISR 1
+#endif
+
+#ifndef INCLUDE_xTimerPendFunctionCall
+ #define INCLUDE_xTimerPendFunctionCall 0
+#endif
+
+#ifndef INCLUDE_xTaskGetSchedulerState
+ #define INCLUDE_xTaskGetSchedulerState 0
+#endif
+
+#ifndef INCLUDE_xTaskGetCurrentTaskHandle
+ #define INCLUDE_xTaskGetCurrentTaskHandle 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
+#endif
+
+#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
#define configUSE_RECURSIVE_MUTEXES 0
#endif
@@ -248,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
@@ -284,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
@@ -320,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
@@ -410,6 +414,10 @@ extern "C" {
#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
@@ -511,7 +519,7 @@ extern "C" {
#endif
#ifndef traceTASK_DELAY_UNTIL
- #define traceTASK_DELAY_UNTIL()
+ #define traceTASK_DELAY_UNTIL( x )
#endif
#ifndef traceTASK_DELAY
@@ -684,14 +692,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
@@ -732,10 +732,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
@@ -776,6 +772,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
@@ -815,6 +836,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. */
@@ -824,14 +849,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 )
+ 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/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h b/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h
index 6d9cf424..d22f7f80 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h
+++ b/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.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.
@@ -8,14 +8,14 @@
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.
+ 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
@@ -37,17 +37,17 @@
***************************************************************************
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()?
+ 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/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/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
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h b/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h
index 1359090c..914c48f3 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h
+++ b/Middlewares/Third_Party/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.
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h b/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h
index dc655ae2..de665453 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h
+++ b/Middlewares/Third_Party/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.
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h b/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h
index 0fad8626..681998c7 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h
+++ b/Middlewares/Third_Party/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/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h b/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h
index a381ed07..bcb3b231 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h
+++ b/Middlewares/Third_Party/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
@@ -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 );
*
- * 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
+ *
+ EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
+
+ *
+ * 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:
+
+ // 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 );
+
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
+#endif
/**
* event_groups.h
@@ -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 will be 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
}
}
- * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
+ * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
@@ -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.
@@ -491,8 +557,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_
* *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 will be 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
- // will be 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 );
}
@@ -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/Middlewares/Third_Party/FreeRTOS/Source/include/list.h b/Middlewares/Third_Party/FreeRTOS/Source/include/list.h
index 75d391d4..cde5453f 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/list.h
+++ b/Middlewares/Third_Party/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.
@@ -414,12 +414,12 @@ void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIV
* 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
+ * 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 pvIndex parameter again points to the item being inserted.
+ * the pxIndex parameter again points to the item being inserted.
*
* @param pxList The list into which the item is to be inserted.
*
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h b/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h
new file mode 100644
index 00000000..b4a1d098
--- /dev/null
+++ b/Middlewares/Third_Party/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/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h b/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h
index 5b2ad474..7d333428 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h
+++ b/Middlewares/Third_Party/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.
@@ -79,79 +79,103 @@ only for ports that are using the MPU. */
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
+ /*
+ * 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.
+ */
- #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
+ /* 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 pvPortMalloc MPU_pvPortMalloc
- #define vPortFree MPU_vPortFree
- #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize
- #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks
- #define xPortGetMinimumEverFreeHeapSize MPU_xPortGetMinimumEverFreeHeapSize
+ #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
+ #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
+ #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
+ #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
- #if configQUEUE_REGISTRY_SIZE > 0
- #define vQueueAddToRegistry MPU_vQueueAddToRegistry
- #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
+ /* 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
+ /* 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
- #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 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/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h b/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h
index cd6a9344..177130cd 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h
+++ b/Middlewares/Third_Party/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.
@@ -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/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h b/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h
index 956264b9..0da6f1bb 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h
+++ b/Middlewares/Third_Party/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/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h b/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h
index 2d7b5e90..b96ed5b3 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h
+++ b/Middlewares/Third_Party/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,8 +123,20 @@ typedef void * QueueSetMemberHandle_t;
);
*
*
- * 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.
*
@@ -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
+ *
+ QueueHandle_t xQueueCreateStatic(
+ UBaseType_t uxQueueLength,
+ UBaseType_t uxItemSize,
+ uint8_t *pucQueueStorageBuffer,
+ StaticQueue_t *pxQueueBuffer
+ );
+ *
+ *
+ * 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:
+
+ 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.
+ }
+
+ * \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
@@ -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;
/*
@@ -1517,7 +1597,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
* 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.
*/
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#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.
+ */
+#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
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h b/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h
index ab00d09d..f9867ae4 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h
+++ b/Middlewares/Third_Party/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
* vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
*
+ * 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
* SemaphoreHandle_t xSemaphoreCreateBinary( void )
*
+ * 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:
@@ -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;
}
}
- * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary
* \ingroup Semaphores
*/
-#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif
+
+/**
+ * semphr. h
+ * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
+ *
+ * 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:
+
+ 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.
+ }
+
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
+ * \ingroup Semaphores
+ */
+#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;
* )
*
* Macro 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.
@@ -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
* xSemaphoreGive( SemaphoreHandle_t xSemaphore )
*
* Macro 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 )
{
@@ -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;
)
*
* Macro 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.
@@ -620,7 +674,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
)
*
* Macro 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())
@@ -649,12 +703,21 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semphr. h
* SemaphoreHandle_t xSemaphoreCreateMutex( void )
*
- * Macro 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.
*
- * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * 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 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:
@@ -687,22 +751,96 @@ typedef QueueHandle_t SemaphoreHandle_t;
}
}
- * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex
* \ingroup Semaphores
*/
-#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ *
+ * 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:
+
+ 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.
+ }
+
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
+ * \ingroup Semaphores
+ */
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
*
- * Macro 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
@@ -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:
@@ -742,17 +880,107 @@ typedef QueueHandle_t SemaphoreHandle_t;
}
}
- * \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
+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ *
+ * 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:
+
+ 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.
+ }
+
+ * \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
* SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
*
- * Macro 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:
*
@@ -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
+ * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )
+ *
+ * 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:
+
+ 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.
+ }
+
+ * \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
+ * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
+ *
+ * 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/Middlewares/Third_Party/FreeRTOS/Source/include/task.h b/Middlewares/Third_Party/FreeRTOS/Source/include/task.h
index b8d6dd89..5e409c8d 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/task.h
+++ b/Middlewares/Third_Party/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. */
@@ -172,6 +173,7 @@ typedef struct xTASK_STATUS
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 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;
@@ -183,7 +185,6 @@ typedef enum
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
@@ -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
+ *
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
+ const char * const pcName,
+ uint32_t ulStackDepth,
+ void *pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t *pxStackBuffer,
+ StaticTask_t *pxTaskBuffer );
+ *
+ * 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:
+
+
+ // 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 );
+ }
+
+ * \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
@@ -613,6 +753,31 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
*/
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;
+/**
+ * task. h
+ * BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
+ *
+ * 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
* UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
@@ -686,6 +851,62 @@ UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
*/
eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+/**
+ * task. h
+ * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
+ *
+ * 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:
+
+ 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.
+ }
+
+ * \defgroup vTaskGetInfo vTaskGetInfo
+ * \ingroup TaskCtrl
+ */
+void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) PRIVILEGED_FUNCTION;
+
/**
* task. h
* void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
@@ -1098,17 +1319,32 @@ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
/**
* task. h
- * char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery );
+ * char *pcTaskGetName( TaskHandle_t xTaskToQuery );
*
* @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
+ * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
+ *
+ * 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
@@ -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
@@ -1979,12 +2215,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.
*/
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h b/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h
index 3c6c6bf3..fda71ca0 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h
+++ b/Middlewares/Third_Party/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
@@ -250,14 +258,151 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
*
* // 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 );
@@ -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.
*/
@@ -677,7 +819,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
*
* // 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( ;; );
@@ -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/Middlewares/Third_Party/FreeRTOS/Source/list.c b/Middlewares/Third_Party/FreeRTOS/Source/list.c
index ebacafdd..0c004742 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/list.c
+++ b/Middlewares/Third_Party/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/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
index 532b7378..c5c3224d 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
+++ b/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/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.
@@ -134,6 +134,10 @@ r0p1 port. */
/* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
+/* 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 )
+
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
@@ -174,7 +178,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Function to enable the VFP.
*/
- static void vPortEnableVFP( void ) __attribute__ (( naked ));
+static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
@@ -233,7 +237,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*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 */
@@ -279,7 +283,7 @@ void vPortSVCHandler( void )
" msr basepri, r0 \n"
" bx r14 \n"
" \n"
- " .align 2 \n"
+ " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
);
}
@@ -452,7 +456,7 @@ void xPortPendSVHandler( void )
" mov r0, %0 \n"
" msr basepri, r0 \n"
" dsb \n"
- " isb \n"
+ " isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
@@ -479,7 +483,7 @@ void xPortPendSVHandler( void )
" \n"
" bx r14 \n"
" \n"
- " .align 2 \n"
+ " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
@@ -492,7 +496,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 )
@@ -502,7 +506,7 @@ void xPortSysTickHandler( void )
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+ portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
@@ -537,6 +541,8 @@ void xPortSysTickHandler( void )
/* 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. */
@@ -636,7 +642,7 @@ void xPortSysTickHandler( void )
/* The reload value is set to whatever fraction of a single tick
period remains. */
- portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h b/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
index 073e408a..b72042d4 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
+++ b/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/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.
@@ -188,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 */
@@ -202,10 +202,32 @@ 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 )
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c b/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c
index f139ef05..1091371e 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c
+++ b/Middlewares/Third_Party/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/Middlewares/Third_Party/FreeRTOS/Source/queue.c b/Middlewares/Third_Party/FreeRTOS/Source/queue.c
index c71ef502..9884658e 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/queue.c
+++ b/Middlewares/Third_Party/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 )
+ 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 );
+
+ /* 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;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#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 )
+ {
+ /* There is not going to be a queue storage area. */
+ xQueueSizeInBytes = ( size_t ) 0;
+ }
+ else
+ {
+ /* 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. */
+ }
+
+ pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
+
+ if( pxNewQueue != NULL )
+ {
+ /* Jump past the queue structure to find the location of the queue
+ storage area. */
+ pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );
+
+ #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 );
+ }
+
+ 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;
- configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
-
if( uxItemSize == ( UBaseType_t ) 0 )
{
- /* There is not going to be a queue storage area. */
- xQueueSizeInBytes = ( size_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
{
- /* 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. */
+ /* Set the head to the start of the queue storage area. */
+ pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
}
- /* Allocate the new queue structure and storage area. */
- pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
+ /* Initialise the queue members as described where the queue type is
+ defined. */
+ pxNewQueue->uxLength = uxQueueLength;
+ pxNewQueue->uxItemSize = uxItemSize;
+ ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
- if( pxNewQueue != NULL )
+ #if ( configUSE_TRACE_FACILITY == 1 )
{
- 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
- {
- /* Jump past the queue structure to find the location of the queue
- storage area. */
- pxNewQueue->pcHead = ( ( int8_t * ) pxNewQueue ) + sizeof( Queue_t );
- }
-
- /* Initialise the queue members as described above where the queue type
- is defined. */
- pxNewQueue->uxLength = uxQueueLength;
- pxNewQueue->uxItemSize = uxItemSize;
- ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
-
- #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 );
- xReturn = pxNewQueue;
+ pxNewQueue->ucQueueType = ucQueueType;
}
- else
+ #endif /* configUSE_TRACE_FACILITY */
+
+ #if( configUSE_QUEUE_SETS == 1 )
{
- mtCOVERAGE_TEST_MARKER();
+ pxNewQueue->pxQueueSetContainer = NULL;
}
+ #endif /* configUSE_QUEUE_SETS */
- configASSERT( xReturn );
-
- return xReturn;
+ 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();
}
@@ -2370,6 +2293,34 @@ BaseType_t xReturn;
#endif /* configQUEUE_REGISTRY_SIZE */
/*-----------------------------------------------------------*/
+#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 )
@@ -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/Middlewares/Third_Party/FreeRTOS/Source/tasks.c b/Middlewares/Third_Party/FreeRTOS/Source/tasks.c
index 11ca0e97..8aea1cd9 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/tasks.c
+++ b/Middlewares/Third_Party/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
#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 )
+ 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 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,186 +556,429 @@ 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 )
- configASSERT( pxTaskCode );
- configASSERT( ( ( uxPriority & ( UBaseType_t ) ( ~portPRIVILEGE_BIT ) ) < ( UBaseType_t ) configMAX_PRIORITIES ) );
-
- /* Allocate the memory required by the TCB and stack for the new task,
- checking that the allocation was successful. */
- pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
-
- if( pxNewTCB != NULL )
+ 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. */
{
- #if( portUSING_MPU_WRAPPERS == 1 )
- /* Should the task be created in privileged mode? */
- BaseType_t xRunPrivileged;
- if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
- {
- xRunPrivileged = pdTRUE;
- }
- else
- {
- xRunPrivileged = pdFALSE;
- }
- uxPriority &= ~portPRIVILEGE_BIT;
+ TCB_t *pxNewTCB;
+ TaskHandle_t xReturn;
- if( puxStackBuffer != 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;
- }
- else
- {
- /* The stack was allocated dynamically. Note this so it can be
- deleted again if the task is deleted. */
- pxNewTCB->xUsingStaticallyAllocatedStack = pdFALSE;
- }
- #endif /* portUSING_MPU_WRAPPERS == 1 */
+ configASSERT( puxStackBuffer != NULL );
+ configASSERT( pxTaskBuffer != NULL );
- /* 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( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != 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. */
+ /* 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;
- /* Check the alignment of the calculated top of stack is correct. */
- configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ #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;
+ }
+
+ return xReturn;
+ }
+
+#endif /* SUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( portUSING_MPU_WRAPPERS == 1 )
+
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+ {
+ 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 )
+ {
+ /* 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;
+ }
+ }
+
+ 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 )
+ {
+ /* 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;
+ }
+ }
}
#else /* portSTACK_GROWTH */
{
- pxTopOfStack = pxNewTCB->pxStack;
+ StackType_t *pxStack;
- /* Check the alignment of the stack buffer is correct. */
- configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ /* 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 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 );
+ if( pxStack != NULL )
+ {
+ /* 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
+ {
+ pxNewTCB = NULL;
+ }
}
#endif /* portSTACK_GROWTH */
- /* Setup the newly allocated TCB with the initial state of the task. */
- prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
+ if( pxNewTCB != NULL )
+ {
+ #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 */
- /* 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 );
+ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
}
- #else /* portUSING_MPU_WRAPPERS */
+ else
{
- pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
- #endif /* portUSING_MPU_WRAPPERS */
- if( ( void * ) pxCreatedTask != NULL )
+ return xReturn;
+ }
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+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;
+
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ /* Should the task be created in privileged mode? */
+ BaseType_t xRunPrivileged;
+ if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
{
- /* 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;
+ xRunPrivileged = pdTRUE;
+ }
+ 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 ) );
+ }
+ #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 ) );
+
+ /* 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 )
+ {
+ break;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
+ }
- /* Ensure interrupts don't access the task lists while they 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;
+ /* 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';
- 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();
- }
- }
- 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 <= uxPriority )
- {
- pxCurrentTCB = pxNewTCB;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
-
- uxTaskNumber++;
-
- #if ( configUSE_TRACE_FACILITY == 1 )
- {
- /* Add a counter into the TCB for tracing only. */
- pxNewTCB->uxTCBNumber = uxTaskNumber;
- }
- #endif /* configUSE_TRACE_FACILITY */
- traceTASK_CREATE( pxNewTCB );
-
- prvAddTaskToReadyList( pxNewTCB );
-
- xReturn = pdPASS;
- portSETUP_TCB( pxNewTCB );
- }
- taskEXIT_CRITICAL();
+ /* 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
{
- xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
- traceTASK_CREATE_FAILED();
+ mtCOVERAGE_TEST_MARKER();
}
- if( xReturn == pdPASS )
+ pxNewTCB->uxPriority = uxPriority;
+ #if ( configUSE_MUTEXES == 1 )
{
- if( xSchedulerRunning != pdFALSE )
+ 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++ )
{
- /* If the created task is of a higher priority than the current task
- then it should run now. */
- if( pxCurrentTCB->uxPriority < uxPriority )
+ pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
+ }
+ }
+ #endif
+
+ #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 )
{
- taskYIELD_IF_USING_PREEMPTION();
+ /* 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
{
@@ -730,12 +986,60 @@ StackType_t *pxTopOfStack;
}
}
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 )
+ {
+ pxCurrentTCB = pxNewTCB;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ uxTaskNumber++;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ /* Add a counter into the TCB for tracing only. */
+ pxNewTCB->uxTCBNumber = uxTaskNumber;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+ traceTASK_CREATE( pxNewTCB );
+
+ prvAddTaskToReadyList( pxNewTCB );
+
+ portSETUP_TCB( pxNewTCB );
+ }
+ taskEXIT_CRITICAL();
+
+ 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 )
+ {
+ taskYIELD_IF_USING_PREEMPTION();
+ }
+ else
{
mtCOVERAGE_TEST_MARKER();
}
}
-
- return xReturn;
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
}
/*-----------------------------------------------------------*/
@@ -751,11 +1055,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,17 +1075,43 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
-
- /* 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;
-
- /* Increment the uxTaskNumberVariable also so kernel aware debuggers
- can detect that the task lists need re-generating. */
+ /* 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++;
+ 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;
+
+ /* 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 );
}
taskEXIT_CRITICAL();
@@ -796,24 +1123,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 +1191,11 @@ StackType_t *pxTopOfStack;
if( xShouldDelay != pdFALSE )
{
- traceTASK_DELAY_UNTIL();
+ traceTASK_DELAY_UNTIL( xTimeToWake );
- /* 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();
- }
-
- 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 +1223,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 +1240,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 +1264,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 +1283,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 +1312,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 +1518,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 +1541,7 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- if( xYieldRequired == pdTRUE )
+ if( xYieldRequired != pdFALSE )
{
taskYIELD_IF_USING_PREEMPTION();
}
@@ -1295,7 +1577,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 +1596,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 +1644,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 +1665,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 +1712,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 +1781,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 +1799,7 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER();
}
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
@@ -1545,18 +1828,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 +1921,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 +1956,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 +1996,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 +2016,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 +2042,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 +2057,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 +2178,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 +2332,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 +2353,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 +2422,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 +2508,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;
+ taskSWITCH_DELAYED_LISTS();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
- if( xConstTickCount == ( TickType_t ) 0U )
+ /* 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( ;; )
{
- 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 )
- {
- for( ;; )
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{
- 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
+ {
+ /* 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();
- }
-
- /* It is time to remove the item from the Blocked state. */
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
-
- /* 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 )
- {
- xSwitchRequired = pdTRUE;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
- #endif /* configUSE_PREEMPTION */
+ mtCOVERAGE_TEST_MARKER();
}
+
+ /* 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 )
+ {
+ ( 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 )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
}
}
}
@@ -2222,9 +2780,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 +2819,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 +2830,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 +2854,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 +2876,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 )
+ /* 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 )
{
- /* 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();
+ xTicksToWait = portMAX_DELAY;
}
- /* 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( 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 );
- }
- }
- #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 +2915,7 @@ BaseType_t xReturn;
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
- ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
+ ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );
}
else
@@ -2551,7 +2980,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 +3024,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 +3133,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 +3275,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 +3324,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 +3364,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 +3388,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 +3402,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 ) );
+ TCB_t *pxTCB;
- /* 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 )
+ /* xTask is NULL then get the state of the calling task. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ 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 ( INCLUDE_vTaskSuspend == 1 )
{
- xNextTaskUnblockTime = xTimeToWake;
+ /* 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 )
+ {
+ vTaskSuspendAll();
+ {
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ pxTaskStatus->eCurrentState = eBlocked;
+ }
+ }
+ xTaskResumeAll();
+ }
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
+ }
+ #else
+ {
+ pxTaskStatus->uxBasePriority = 0;
+ }
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
+ }
+ #else
+ {
+ pxTaskStatus->ulRunTimeCounter = 0;
+ }
+ #endif
+
+ /* 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
{
- mtCOVERAGE_TEST_MARKER();
+ pxTaskStatus->eCurrentState = eTaskGetState( xTask );
}
- }
-}
-/*-----------------------------------------------------------*/
-static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
-{
-TCB_t *pxNewTCB;
-
- /* 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 ) );
-
- if( pxNewTCB != NULL )
+ /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
+ parameter is provided to allow it to be skipped. */
+ if( xGetFreeStackSpace != 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 * ) 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 ( portSTACK_GROWTH > 0 )
{
- /* Could not allocate the stack. Delete the allocated TCB. */
- vPortFree( pxNewTCB );
- pxNewTCB = NULL;
+ pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
}
- }
- }
- #else /* portSTACK_GROWTH */
- {
- StackType_t *pxStack;
-
- /* 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( pxStack != NULL )
- {
- /* 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 ) );
-
- if( pxNewTCB != NULL )
+ #else
{
- /* 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 );
+ pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
}
+ #endif
}
else
{
- pxNewTCB = NULL;
+ pxTaskStatus->usStackHighWaterMark = 0;
}
}
- #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 ) );
- }
- #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 +3513,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 +3593,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 )
+ /* The task can only have been allocated dynamically - free both
+ the stack and TCB. */
+ vPortFree( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+ #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
+ {
+ /* 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 )
{
- vPortFreeAligned( pxTCB->pxStack );
+ /* 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();
}
}
- #else
- {
- vPortFreeAligned( pxTCB->pxStack );
- }
- #endif
-
- vPortFree( pxTCB );
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
#endif /* INCLUDE_vTaskDelete */
@@ -3363,7 +3651,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 +3730,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 +3797,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 +3977,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 +4019,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 +4078,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 +4146,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 +4194,6 @@ TickType_t uxReturn;
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
{
- TickType_t xTimeToWake;
uint32_t ulReturn;
taskENTER_CRITICAL();
@@ -3909,55 +4202,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 +4240,7 @@ TickType_t uxReturn;
}
else
{
- ( pxCurrentTCB->ulNotifiedValue )--;
+ pxCurrentTCB->ulNotifiedValue = ulReturn - 1;
}
}
else
@@ -3999,7 +4248,7 @@ TickType_t uxReturn;
mtCOVERAGE_TEST_MARKER();
}
- pxCurrentTCB->eNotifyState = eNotWaitingNotification;
+ pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
}
taskEXIT_CRITICAL();
@@ -4013,13 +4262,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 +4275,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 +4311,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 +4328,7 @@ TickType_t uxReturn;
xReturn = pdTRUE;
}
- pxCurrentTCB->eNotifyState = eNotWaitingNotification;
+ pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
}
taskEXIT_CRITICAL();
@@ -4139,8 +4343,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 +4356,9 @@ TickType_t uxReturn;
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
}
- eOriginalNotifyState = pxTCB->eNotifyState;
+ ucOriginalNotifyState = pxTCB->ucNotifyState;
- pxTCB->eNotifyState = eNotified;
+ pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
switch( eAction )
{
@@ -4171,7 +4375,7 @@ TickType_t uxReturn;
break;
case eSetValueWithoutOverwrite :
- if( eOriginalNotifyState != eNotified )
+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{
pxTCB->ulNotifiedValue = ulValue;
}
@@ -4192,9 +4396,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 +4449,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 +4482,8 @@ TickType_t uxReturn;
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
}
- eOriginalNotifyState = pxTCB->eNotifyState;
- pxTCB->eNotifyState = eNotified;
+ ucOriginalNotifyState = pxTCB->ucNotifyState;
+ pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
switch( eAction )
{
@@ -4296,7 +4500,7 @@ TickType_t uxReturn;
break;
case eSetValueWithoutOverwrite :
- if( eOriginalNotifyState != eNotified )
+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{
pxTCB->ulNotifiedValue = ulValue;
}
@@ -4317,14 +4521,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 +4546,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 +4573,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 +4600,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 +4611,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 +4636,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 +4664,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,6 +4686,120 @@ 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"
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/timers.c b/Middlewares/Third_Party/FreeRTOS/Source/timers.c
index c7ab9023..e49587f5 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/timers.c
+++ b/Middlewares/Third_Party/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,17 +171,22 @@ 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;
-
-#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 )
-
- PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
-
-#endif
+PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
/*lint +e956 */
/*-----------------------------------------------------------*/
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ /* 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
* been initialised already.
@@ -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();
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
- /* 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 ) );
+ #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 */
+ }
- traceTIMER_CREATE( pxNewTimer );
- }
- else
- {
- traceTIMER_CREATE_FAILED();
- }
+ 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 )
+ {
+ 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;
- }
-
-#endif
+TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
+{
+ /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
+ started, then xTimerTaskHandle will be NULL. */
+ configASSERT( ( xTimerTaskHandle != NULL ) );
+ return xTimerTaskHandle;
+}
/*-----------------------------------------------------------*/
-const char * pcTimerGetTimerName( TimerHandle_t xTimer )
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
+{
+Timer_t *pxTimer = ( Timer_t * ) xTimer;
+
+ 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 * 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 )
{
diff --git a/Odrive.ioc b/Odrive.ioc
index 5522ac64..1cdb9778 100755
--- a/Odrive.ioc
+++ b/Odrive.ioc
@@ -1,4 +1,5 @@
#MicroXplorer Configuration settings - do not modify
+ADC1.AutoInjectedConv=DISABLE
ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_5
ADC1.Channel-1\#ChannelInjectedConversion=ADC_CHANNEL_0
ADC1.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4
@@ -12,9 +13,10 @@ ADC1.ExternalTrigConv=ADC_SOFTWARE_START
ADC1.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE
ADC1.ExternalTrigInjecConv=ADC_EXTERNALTRIGINJECCONV_T1_CC4
ADC1.ExternalTrigInjecConvEdge=ADC_EXTERNALTRIGINJECCONVEDGE_RISING
-ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,master,ClockPrescaler,Resolution,DataAlign,ScanConvMode,ContinuousConvMode,DiscontinuousConvMode,DMAContinuousRequests,EOCSelection,NbrOfConversion,ExternalTrigConvEdge,InjNumberOfConversion,EnableAnalogWatchDog,Rank-1\#ChannelInjectedConversion,Channel-1\#ChannelInjectedConversion,SamplingTime-1\#ChannelInjectedConversion,InjectedOffset-1\#ChannelInjectedConversion,InjectedConvMode,ExternalTrigInjecConvEdge,ExternalTrigInjecConv,ExternalTrigConv
+ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,master,ClockPrescaler,Resolution,DataAlign,ScanConvMode,ContinuousConvMode,DiscontinuousConvMode,DMAContinuousRequests,EOCSelection,NbrOfConversion,ExternalTrigConvEdge,InjNumberOfConversion,EnableAnalogWatchDog,Rank-1\#ChannelInjectedConversion,Channel-1\#ChannelInjectedConversion,SamplingTime-1\#ChannelInjectedConversion,InjectedOffset-1\#ChannelInjectedConversion,InjectedConvMode,ExternalTrigInjecConvEdge,ExternalTrigInjecConv,ExternalTrigConv,AutoInjectedConv,InjectedDiscontinuousConvMode
ADC1.InjNumberOfConversion=1
ADC1.InjectedConvMode=None
+ADC1.InjectedDiscontinuousConvMode=DISABLE
ADC1.InjectedOffset-1\#ChannelInjectedConversion=0
ADC1.NbrOfConversion=1
ADC1.NbrOfConversionFlag=1
@@ -25,6 +27,7 @@ ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC1.SamplingTime-1\#ChannelInjectedConversion=ADC_SAMPLETIME_3CYCLES
ADC1.ScanConvMode=DISABLE
ADC1.master=1
+ADC2.AutoInjectedConv=DISABLE
ADC2.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_13
ADC2.Channel-1\#ChannelInjectedConversion=ADC_CHANNEL_10
ADC2.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4
@@ -38,9 +41,10 @@ ADC2.ExternalTrigConv=ADC_EXTERNALTRIGCONV_T8_TRGO
ADC2.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_RISING
ADC2.ExternalTrigInjecConv=ADC_EXTERNALTRIGINJECCONV_T1_CC4
ADC2.ExternalTrigInjecConvEdge=ADC_EXTERNALTRIGINJECCONVEDGE_RISING
-ADC2.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler,Resolution,DataAlign,ScanConvMode,ContinuousConvMode,DiscontinuousConvMode,DMAContinuousRequests,EOCSelection,NbrOfConversion,InjNumberOfConversion,EnableAnalogWatchDog,Rank-1\#ChannelInjectedConversion,Channel-1\#ChannelInjectedConversion,SamplingTime-1\#ChannelInjectedConversion,InjectedOffset-1\#ChannelInjectedConversion,ExternalTrigInjecConvEdge,ExternalTrigConvEdge,InjectedConvMode,ExternalTrigInjecConv,ExternalTrigConv
+ADC2.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler,Resolution,DataAlign,ScanConvMode,ContinuousConvMode,DiscontinuousConvMode,DMAContinuousRequests,EOCSelection,NbrOfConversion,InjNumberOfConversion,EnableAnalogWatchDog,Rank-1\#ChannelInjectedConversion,Channel-1\#ChannelInjectedConversion,SamplingTime-1\#ChannelInjectedConversion,InjectedOffset-1\#ChannelInjectedConversion,ExternalTrigInjecConvEdge,ExternalTrigConvEdge,InjectedConvMode,ExternalTrigInjecConv,ExternalTrigConv,AutoInjectedConv,InjectedDiscontinuousConvMode
ADC2.InjNumberOfConversion=1
ADC2.InjectedConvMode=None
+ADC2.InjectedDiscontinuousConvMode=DISABLE
ADC2.InjectedOffset-1\#ChannelInjectedConversion=0
ADC2.NbrOfConversion=1
ADC2.NbrOfConversionFlag=1
@@ -50,6 +54,7 @@ ADC2.Resolution=ADC_RESOLUTION_12B
ADC2.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC2.SamplingTime-1\#ChannelInjectedConversion=ADC_SAMPLETIME_3CYCLES
ADC2.ScanConvMode=DISABLE
+ADC3.AutoInjectedConv=DISABLE
ADC3.Channel-7\#ChannelRegularConversion=ADC_CHANNEL_12
ADC3.Channel-8\#ChannelInjectedConversion=ADC_CHANNEL_11
ADC3.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4
@@ -63,9 +68,10 @@ ADC3.ExternalTrigConv=ADC_EXTERNALTRIGCONV_T8_TRGO
ADC3.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_RISING
ADC3.ExternalTrigInjecConv=ADC_EXTERNALTRIGINJECCONV_T1_CC4
ADC3.ExternalTrigInjecConvEdge=ADC_EXTERNALTRIGINJECCONVEDGE_RISING
-ADC3.IPParameters=Rank-7\#ChannelRegularConversion,Channel-7\#ChannelRegularConversion,SamplingTime-7\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler,Resolution,DataAlign,ScanConvMode,ContinuousConvMode,DiscontinuousConvMode,DMAContinuousRequests,EOCSelection,NbrOfConversion,ExternalTrigConvEdge,InjNumberOfConversion,EnableAnalogWatchDog,Rank-8\#ChannelInjectedConversion,Channel-8\#ChannelInjectedConversion,SamplingTime-8\#ChannelInjectedConversion,InjectedOffset-8\#ChannelInjectedConversion,ExternalTrigInjecConvEdge,InjectedConvMode,ExternalTrigInjecConv,ExternalTrigConv
+ADC3.IPParameters=Rank-7\#ChannelRegularConversion,Channel-7\#ChannelRegularConversion,SamplingTime-7\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler,Resolution,DataAlign,ScanConvMode,ContinuousConvMode,DiscontinuousConvMode,DMAContinuousRequests,EOCSelection,NbrOfConversion,ExternalTrigConvEdge,InjNumberOfConversion,EnableAnalogWatchDog,Rank-8\#ChannelInjectedConversion,Channel-8\#ChannelInjectedConversion,SamplingTime-8\#ChannelInjectedConversion,InjectedOffset-8\#ChannelInjectedConversion,ExternalTrigInjecConvEdge,InjectedConvMode,ExternalTrigInjecConv,ExternalTrigConv,AutoInjectedConv,InjectedDiscontinuousConvMode
ADC3.InjNumberOfConversion=1
ADC3.InjectedConvMode=None
+ADC3.InjectedDiscontinuousConvMode=DISABLE
ADC3.InjectedOffset-8\#ChannelInjectedConversion=0
ADC3.NbrOfConversion=1
ADC3.NbrOfConversionFlag=1
@@ -79,8 +85,9 @@ CAN1.CalculateTimeBit=1142
CAN1.CalculateTimeQuantum=380.95238095238096
CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit
FREERTOS.INCLUDE_vTaskDelayUntil=1
-FREERTOS.IPParameters=Tasks01,INCLUDE_vTaskDelayUntil
+FREERTOS.IPParameters=Tasks01,INCLUDE_vTaskDelayUntil,configUSE_ALTERNATIVE_API
FREERTOS.Tasks01=defaultTask,-3,256,StartDefaultTask,Default
+FREERTOS.configUSE_ALTERNATIVE_API=0
File.Version=6
KeepUserPlacement=false
Mcu.Family=STM32F4
@@ -154,18 +161,16 @@ Mcu.Pin51=VP_FREERTOS_VS_ENABLE
Mcu.Pin52=VP_SYS_VS_Systick
Mcu.Pin53=VP_TIM1_VS_ClockSourceINT
Mcu.Pin54=VP_TIM1_VS_no_output4
-Mcu.Pin55=VP_TIM8_VS_ClockSourceINT
-Mcu.Pin56=VP_TIM8_VS_no_output4
-Mcu.Pin57=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
+Mcu.Pin55=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
Mcu.Pin6=PC1
Mcu.Pin7=PC2
Mcu.Pin8=PC3
Mcu.Pin9=PA0-WKUP
-Mcu.PinsNb=55
-Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,8192;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,20
+Mcu.PinsNb=56
+Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,10192;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,20
Mcu.UserName=STM32F405RGTx
-MxCube.Version=4.19.0
-MxDb.Version=DB.4.0.190
+MxCube.Version=4.20.0
+MxDb.Version=DB.4.0.200
NVIC.ADC_IRQn=true\:5\:0\:false\:true\:true\:1\:true
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false
@@ -346,7 +351,7 @@ PC9.Signal=GPIO_Output
PCC.Checker=false
PCC.Line=STM32F405/415
PCC.MCU=STM32F405RGTx
-PCC.MXVersion=4.19.0
+PCC.MXVersion=4.20.0
PCC.PartNumber=STM32F405RGTx
PCC.Seq0=0
PCC.Series=STM32F4
@@ -370,7 +375,7 @@ ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32F405RGTx
-ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.14.0
+ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.15.0
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x3C00
@@ -383,7 +388,7 @@ ProjectManager.ProjectFileName=Odrive.ioc
ProjectManager.ProjectName=Odrive
ProjectManager.StackSize=0x800
ProjectManager.TargetToolchain=SW4STM32
-ProjectManager.ToolChainLocation=/home/oskar/ODriveFirmware
+ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=true
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL,2-MX_ADC1_Init-ADC1-false-HAL,3-MX_ADC2_Init-ADC2-false-HAL,4-MX_CAN1_Init-CAN1-false-HAL,5-MX_TIM1_Init-TIM1-false-HAL,6-MX_TIM8_Init-TIM8-false-HAL,7-MX_TIM3_Init-TIM3-false-HAL,8-MX_TIM4_Init-TIM4-false-HAL,9-MX_SPI3_Init-SPI3-false-HAL,10-MX_ADC3_Init-ADC3-false-HAL,11-SystemClock_Config-RCC-false-HAL,12-MX_TIM2_Init-TIM2-false-HAL,13-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL
RCC.48MHZClocksFreq_Value=48000000
@@ -396,28 +401,54 @@ RCC.APB2CLKDivider=RCC_HCLK_DIV2
RCC.APB2Freq_Value=84000000
RCC.APB2TimCLKDivider=1
RCC.APB2TimFreq_Value=84000000
+RCC.ClockTypeHCLK=RCC_CLOCKTYPE_HCLK
+RCC.ClockTypePCLK1=RCC_CLOCKTYPE_PCLK1
+RCC.ClockTypePCLK2=RCC_CLOCKTYPE_PCLK2
+RCC.ClockTypeSysClk=RCC_CLOCKTYPE_SYSCLK
RCC.CortexFreq_Value=168000000
+RCC.EnableExtClockForI2S=false
+RCC.EnableHSE=true
+RCC.EnableHSERTCDevisor=false
+RCC.EnableLSE=false
+RCC.EnableLSERTC=false
RCC.EthernetFreq_Value=168000000
+RCC.ExtClockEnable=false
RCC.FCLKCortexFreq_Value=168000000
RCC.FamilyName=M
RCC.HCLKFreq_Value=168000000
+RCC.HSEState=RCC_HSE_ON
RCC.HSE_VALUE=8000000
+RCC.HSIState=RCC_HSI_OFF
RCC.HSI_VALUE=16000000
RCC.I2SClocksFreq_Value=192000000
-RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimCLKDivider,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimCLKDivider,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQ,PLLQCLKFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
+RCC.I2SEnable=false
+RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimCLKDivider,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimCLKDivider,APB2TimFreq_Value,ClockTypeHCLK,ClockTypePCLK1,ClockTypePCLK2,ClockTypeSysClk,CortexFreq_Value,EnableExtClockForI2S,EnableHSE,EnableHSERTCDevisor,EnableLSE,EnableLSERTC,EthernetFreq_Value,ExtClockEnable,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSEState,HSE_VALUE,HSIState,HSI_VALUE,I2SClocksFreq_Value,I2SEnable,IWDGEnable,LSE_VALUE,LSIState,LSI_VALUE,MCO1OutPutEnable,MCO2OutPutEnable,MCO2PinFreq_Value,OscillatorTypeHSE,OscillatorTypeLSI,PLLCLKFreq_Value,PLLM,PLLN,PLLQ,PLLQCLKFreq_Value,PLLSource,PLLSourceVirtual,PLLState,RNGEnable,RTCEnable,RTCFreq_Value,RTCHSEDivFreq_Value,SDIOEnable,SYSCLKFreq_VALUE,SYSCLKSource,USBFSEnable,USBHSEnable,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
+RCC.IWDGEnable=false
RCC.LSE_VALUE=32768
+RCC.LSIState=RCC_LSI_OFF
RCC.LSI_VALUE=32000
+RCC.MCO1OutPutEnable=false
+RCC.MCO2OutPutEnable=false
RCC.MCO2PinFreq_Value=168000000
+RCC.OscillatorTypeHSE=RCC_OSCILLATORTYPE_HSE
+RCC.OscillatorTypeLSI=
RCC.PLLCLKFreq_Value=168000000
RCC.PLLM=4
RCC.PLLN=168
RCC.PLLQ=7
RCC.PLLQCLKFreq_Value=48000000
+RCC.PLLSource=RCC_PLLSOURCE_HSE
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
+RCC.PLLState=RCC_PLL_ON
+RCC.RNGEnable=false
+RCC.RTCEnable=false
RCC.RTCFreq_Value=32000
RCC.RTCHSEDivFreq_Value=4000000
+RCC.SDIOEnable=false
RCC.SYSCLKFreq_VALUE=168000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
+RCC.USBFSEnable=true
+RCC.USBHSEnable=false
RCC.VCOI2SOutputFreq_Value=384000000
RCC.VCOInputFreq_Value=2000000
RCC.VCOOutputFreq_Value=336000000
@@ -491,20 +522,26 @@ SH.S_TIM8_CH3.0=TIM8_CH3,PWM Generation3 CH3 CH3N
SH.S_TIM8_CH3.ConfNb=1
SPI3.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16
SPI3.CLKPhase=SPI_PHASE_2EDGE
+SPI3.CRCPolynomial=10
SPI3.CalculateBaudRate=2.625 MBits/s
SPI3.DataSize=SPI_DATASIZE_16BIT
+SPI3.Direction=SPI_DIRECTION_2LINES
SPI3.FirstBit=SPI_FIRSTBIT_MSB
-SPI3.IPParameters=Mode,CalculateBaudRate,BaudRatePrescaler,DataSize,FirstBit,CLKPhase
+SPI3.IPParameters=Mode,CalculateBaudRate,BaudRatePrescaler,DataSize,FirstBit,CLKPhase,VirtualType,Direction,CRCPolynomial
SPI3.Mode=SPI_MODE_MASTER
+SPI3.VirtualType=VM_MASTER
TIM1.Channel-Output\ Compare4\ No\ Output=TIM_CHANNEL_4
+TIM1.Channel-PWM\ Generation1\ CH1\ CH1N=TIM_CHANNEL_1
TIM1.Channel-PWM\ Generation2\ CH2\ CH2N=TIM_CHANNEL_2
TIM1.Channel-PWM\ Generation3\ CH3\ CH3N=TIM_CHANNEL_3
TIM1.CounterMode=TIM_COUNTERMODE_CENTERALIGNED3
TIM1.DeadTime=TIM_1_8_DEADTIME_CLOCKS
-TIM1.IPParameters=Channel-PWM Generation2 CH2 CH2N,Channel-PWM Generation3 CH3 CH3N,OCNPolarity_1,OCNPolarity_2,OCNPolarity_3,CounterMode,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Period,DeadTime,OffStateRunMode,OffStateIDLEMode,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger
+TIM1.DefaultOCFastMode-Output\ Compare4\ No\ Output=TIM_OCFAST_DISABLE
+TIM1.IPParameters=Channel-PWM Generation2 CH2 CH2N,Channel-PWM Generation3 CH3 CH3N,OCNPolarity_1,OCNPolarity_2,OCNPolarity_3,CounterMode,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Period,DeadTime,OffStateRunMode,OffStateIDLEMode,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger,Channel-PWM Generation1 CH1 CH1N,DefaultOCFastMode-Output Compare4 No Output,OCNIdleState_4
TIM1.OCMode_PWM-PWM\ Generation1\ CH1\ CH1N=TIM_OCMODE_PWM2
TIM1.OCMode_PWM-PWM\ Generation2\ CH2\ CH2N=TIM_OCMODE_PWM2
TIM1.OCMode_PWM-PWM\ Generation3\ CH3\ CH3N=TIM_OCMODE_PWM2
+TIM1.OCNIdleState_4=TIM_OCNIDLESTATE_RESET
TIM1.OCNPolarity_1=TIM_OCNPOLARITY_HIGH
TIM1.OCNPolarity_2=TIM_OCNPOLARITY_HIGH
TIM1.OCNPolarity_3=TIM_OCNPOLARITY_HIGH
@@ -536,11 +573,12 @@ TIM4.IC2Polarity=TIM_ICPOLARITY_RISING
TIM4.IPParameters=EncoderMode,IC1Polarity,IC2Polarity,IC1Filter,IC2Filter,Period
TIM4.Period=0xffff
TIM8.Channel-Output\ Compare4\ No\ Output=TIM_CHANNEL_4
+TIM8.Channel-PWM\ Generation1\ CH1\ CH1N=TIM_CHANNEL_1
TIM8.Channel-PWM\ Generation2\ CH2\ CH2N=TIM_CHANNEL_2
TIM8.Channel-PWM\ Generation3\ CH3\ CH3N=TIM_CHANNEL_3
TIM8.CounterMode=TIM_COUNTERMODE_CENTERALIGNED3
TIM8.DeadTime=TIM_1_8_DEADTIME_CLOCKS
-TIM8.IPParameters=Channel-PWM Generation3 CH3 CH3N,Channel-PWM Generation2 CH2 CH2N,CounterMode,Period,OffStateRunMode,OffStateIDLEMode,DeadTime,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger
+TIM8.IPParameters=Channel-PWM Generation3 CH3 CH3N,Channel-PWM Generation2 CH2 CH2N,CounterMode,Period,OffStateRunMode,OffStateIDLEMode,DeadTime,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger,Channel-PWM Generation1 CH1 CH1N
TIM8.OCMode_PWM-PWM\ Generation1\ CH1\ CH1N=TIM_OCMODE_PWM2
TIM8.OCMode_PWM-PWM\ Generation2\ CH2\ CH2N=TIM_OCMODE_PWM2
TIM8.OCMode_PWM-PWM\ Generation3\ CH3\ CH3N=TIM_OCMODE_PWM2
@@ -548,19 +586,19 @@ TIM8.OffStateIDLEMode=TIM_OSSI_ENABLE
TIM8.OffStateRunMode=TIM_OSSR_ENABLE
TIM8.Period=TIM_1_8_PERIOD_CLOCKS
TIM8.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
-USB_DEVICE.CLASS_NAME-CDC_FS=CDC
USB_DEVICE.CLASS_NAME_FS=CDC
-USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,USBD_HandleTypeDef-CDC_FS,CLASS_NAME-CDC_FS,CLASS_NAME_FS,MANUFACTURER_STRING-CDC_FS,PRODUCT_STRING_CDC_FS,VID-CDC_FS,PID_CDC_FS,SERIALNUMBER_STRING_CDC_FS
+USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING-CDC_FS,PRODUCT_STRING_CDC_FS,VID-CDC_FS,PID_CDC_FS,SERIALNUMBER_STRING_CDC_FS,USBD_HandleTypeDef_FS
USB_DEVICE.MANUFACTURER_STRING-CDC_FS=ODrive
USB_DEVICE.PID_CDC_FS=0x0D31
USB_DEVICE.PRODUCT_STRING_CDC_FS=ODrive rev 3.1
USB_DEVICE.SERIALNUMBER_STRING_CDC_FS=000000000001
-USB_DEVICE.USBD_HandleTypeDef-CDC_FS=hUsbDeviceFS
+USB_DEVICE.USBD_HandleTypeDef_FS=hUsbDevice_OTG_FS
USB_DEVICE.VID-CDC_FS=0x1209
USB_DEVICE.VirtualMode-CDC_FS=Cdc
USB_DEVICE.VirtualModeFS=Cdc_FS
-USB_OTG_FS.IPParameters=VirtualMode,vbus_sensing_enable
+USB_OTG_FS.IPParameters=VirtualMode,vbus_sensing_enable,phy_itface
USB_OTG_FS.VirtualMode=Device_Only
+USB_OTG_FS.phy_itface=PCD_PHY_EMBEDDED
USB_OTG_FS.vbus_sensing_enable=DISABLE
VP_FREERTOS_VS_ENABLE.Mode=Enabled
VP_FREERTOS_VS_ENABLE.Signal=FREERTOS_VS_ENABLE
@@ -570,10 +608,6 @@ VP_TIM1_VS_ClockSourceINT.Mode=Internal
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
VP_TIM1_VS_no_output4.Mode=Output Compare4 No Output
VP_TIM1_VS_no_output4.Signal=TIM1_VS_no_output4
-VP_TIM8_VS_ClockSourceINT.Mode=Internal
-VP_TIM8_VS_ClockSourceINT.Signal=TIM8_VS_ClockSourceINT
-VP_TIM8_VS_no_output4.Mode=Output Compare4 No Output
-VP_TIM8_VS_no_output4.Signal=TIM8_VS_no_output4
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS
board=Odrive
diff --git a/Src/freertos.c b/Src/freertos.c
index 0db19c50..7b5ce667 100644
--- a/Src/freertos.c
+++ b/Src/freertos.c
@@ -46,7 +46,7 @@
#include "task.h"
#include "cmsis_os.h"
-/* USER CODE BEGIN Includes */
+/* USER CODE BEGIN Includes */
#include "freertos_vars.h"
#include "low_level.h"
#include "version.h"
diff --git a/Src/tim.c b/Src/tim.c
index 3a00ca75..7199b66d 100644
--- a/Src/tim.c
+++ b/Src/tim.c
@@ -271,7 +271,6 @@ void MX_TIM4_Init(void)
/* TIM8 init function */
void MX_TIM8_Init(void)
{
- TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
@@ -282,27 +281,11 @@ void MX_TIM8_Init(void)
htim8.Init.Period = TIM_1_8_PERIOD_CLOCKS;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
- if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
- {
- Error_Handler();
- }
-
- sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
- if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
- {
- Error_Handler();
- }
-
if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
- if (HAL_TIM_OC_Init(&htim8) != HAL_OK)
- {
- Error_Handler();
- }
-
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
@@ -332,12 +315,6 @@ void MX_TIM8_Init(void)
Error_Handler();
}
- sConfigOC.OCMode = TIM_OCMODE_TIMING;
- if (HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
- {
- Error_Handler();
- }
-
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
@@ -368,17 +345,6 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
/* USER CODE END TIM1_MspInit 1 */
}
- else if(tim_baseHandle->Instance==TIM8)
- {
- /* USER CODE BEGIN TIM8_MspInit 0 */
-
- /* USER CODE END TIM8_MspInit 0 */
- /* Peripheral clock enable */
- __HAL_RCC_TIM8_CLK_ENABLE();
- /* USER CODE BEGIN TIM8_MspInit 1 */
-
- /* USER CODE END TIM8_MspInit 1 */
- }
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
@@ -395,6 +361,17 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
/* USER CODE END TIM2_MspInit 1 */
}
+ else if(tim_pwmHandle->Instance==TIM8)
+ {
+ /* USER CODE BEGIN TIM8_MspInit 0 */
+
+ /* USER CODE END TIM8_MspInit 0 */
+ /* Peripheral clock enable */
+ __HAL_RCC_TIM8_CLK_ENABLE();
+ /* USER CODE BEGIN TIM8_MspInit 1 */
+
+ /* USER CODE END TIM8_MspInit 1 */
+ }
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
@@ -556,21 +533,10 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
+ }
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
- }
- else if(tim_baseHandle->Instance==TIM8)
- {
- /* USER CODE BEGIN TIM8_MspDeInit 0 */
-
- /* USER CODE END TIM8_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_TIM8_CLK_DISABLE();
- /* USER CODE BEGIN TIM8_MspDeInit 1 */
-
- /* USER CODE END TIM8_MspDeInit 1 */
- }
}
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
@@ -583,10 +549,21 @@ void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
- }
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
+ }
+ else if(tim_pwmHandle->Instance==TIM8)
+ {
+ /* USER CODE BEGIN TIM8_MspDeInit 0 */
+
+ /* USER CODE END TIM8_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_TIM8_CLK_DISABLE();
+ /* USER CODE BEGIN TIM8_MspDeInit 1 */
+
+ /* USER CODE END TIM8_MspDeInit 1 */
+ }
}
void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
diff --git a/Src/usbd_conf.c b/Src/usbd_conf.c
index 4d6d9972..0b471eea 100644
--- a/Src/usbd_conf.c
+++ b/Src/usbd_conf.c
@@ -130,7 +130,7 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)
*/
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{
- USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
+ USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}
/**
@@ -141,7 +141,7 @@ void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
*/
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
- USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
+ USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}
/**
@@ -152,7 +152,7 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
*/
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
- USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
+ USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}
/**
@@ -162,7 +162,7 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
*/
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
{
- USBD_LL_SOF(hpcd->pData);
+ USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}
/**
@@ -188,10 +188,10 @@ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
speed = USBD_SPEED_FULL;
break;
}
- USBD_LL_SetSpeed(hpcd->pData, speed);
+ USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
/*Reset Device*/
- USBD_LL_Reset(hpcd->pData);
+ USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
/**
@@ -203,7 +203,7 @@ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
{
/* Inform USB library that core enters in suspend Mode */
- USBD_LL_Suspend(hpcd->pData);
+ USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
__HAL_PCD_GATE_PHYCLOCK(hpcd);
/*Enter in STOP mode */
/* USER CODE BEGIN 2 */
@@ -225,7 +225,8 @@ void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
{
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
- USBD_LL_Resume(hpcd->pData);
+ USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
+
}
/**
@@ -236,7 +237,7 @@ void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
*/
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
- USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum);
+ USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
@@ -247,7 +248,7 @@ void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
*/
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
- USBD_LL_IsoINIncomplete(hpcd->pData, epnum);
+ USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}
/**
@@ -257,7 +258,7 @@ void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
*/
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
{
- USBD_LL_DevConnected(hpcd->pData);
+ USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}
/**
@@ -267,7 +268,7 @@ void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
*/
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
{
- USBD_LL_DevDisconnected(hpcd->pData);
+ USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
@@ -316,8 +317,29 @@ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
*/
USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev)
{
- HAL_PCD_DeInit(pdev->pData);
- return USBD_OK;
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
+
+ hal_status = HAL_PCD_DeInit(pdev->pData);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -327,8 +349,29 @@ USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev)
*/
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
- HAL_PCD_Start(pdev->pData);
- return USBD_OK;
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
+
+ hal_status = HAL_PCD_Start(pdev->pData);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -338,8 +381,29 @@ USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
*/
USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev)
{
- HAL_PCD_Stop(pdev->pData);
- return USBD_OK;
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
+
+ hal_status = HAL_PCD_Stop(pdev->pData);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -355,13 +419,33 @@ USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev,
uint8_t ep_type,
uint16_t ep_mps)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_Open(pdev->pData,
- ep_addr,
- ep_mps,
- ep_type);
+ hal_status = HAL_PCD_EP_Open(pdev->pData,
+ ep_addr,
+ ep_mps,
+ ep_type);
- return USBD_OK;
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -372,9 +456,29 @@ USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev,
*/
USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_Close(pdev->pData, ep_addr);
- return USBD_OK;
+ hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -385,9 +489,29 @@ USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
*/
USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_Flush(pdev->pData, ep_addr);
- return USBD_OK;
+ hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -398,9 +522,29 @@ USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
*/
USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
- return USBD_OK;
+ hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -411,9 +555,29 @@ USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
*/
USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
- return USBD_OK;
+ hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -424,7 +588,7 @@ USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_a
*/
uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
- PCD_HandleTypeDef *hpcd = pdev->pData;
+ PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
if((ep_addr & 0x80) == 0x80)
{
@@ -443,9 +607,29 @@ uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
*/
USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_SetAddress(pdev->pData, dev_addr);
- return USBD_OK;
+ hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -461,9 +645,29 @@ USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t size)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
- return USBD_OK;
+ hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -479,9 +683,29 @@ USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
uint8_t *pbuf,
uint16_t size)
{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+ USBD_StatusTypeDef usb_status = USBD_OK;
- HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
- return USBD_OK;
+ hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
+
+ switch (hal_status) {
+ case HAL_OK :
+ usb_status = USBD_OK;
+ break;
+ case HAL_ERROR :
+ usb_status = USBD_FAIL;
+ break;
+ case HAL_BUSY :
+ usb_status = USBD_BUSY;
+ break;
+ case HAL_TIMEOUT :
+ usb_status = USBD_FAIL;
+ break;
+ default :
+ usb_status = USBD_FAIL;
+ break;
+ }
+ return usb_status;
}
/**
@@ -492,7 +716,7 @@ USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
*/
uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
- return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr);
+ return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}
#if (USBD_LPM_ENABLED == 1)
diff --git a/Src/usbd_desc.c b/Src/usbd_desc.c
index d5741388..e59d892d 100644
--- a/Src/usbd_desc.c
+++ b/Src/usbd_desc.c
@@ -5,37 +5,37 @@
* @brief : This file implements the USB Device descriptors
******************************************************************************
*
- * Copyright (c) 2017 STMicroelectronics International N.V.
+ * Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
- * 1. Redistribution of source code must retain the above copyright notice,
+ * 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
- * 3. Neither the name of STMicroelectronics nor the names of other
- * contributors to this software may be used to endorse or promote products
+ * 3. Neither the name of STMicroelectronics nor the names of other
+ * contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
- * 4. This software, including modifications and/or derivative works of this
+ * 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
- * 5. Redistribution and use of this software other than as permitted under
- * this license is void and will automatically terminate your rights under
- * this license.
+ * 5. Redistribution and use of this software other than as permitted under
+ * this license is void and will automatically terminate your rights under
+ * this license.
*
- * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
- * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
+ * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS 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
+ * 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.
*
@@ -51,21 +51,21 @@
* @{
*/
-/** @defgroup USBD_DESC
+/** @defgroup USBD_DESC
* @brief USBD descriptors module
* @{
- */
+ */
/** @defgroup USBD_DESC_Private_TypesDefinitions
* @{
- */
+ */
/**
* @}
- */
+ */
/** @defgroup USBD_DESC_Private_Defines
* @{
- */
+ */
#define USBD_VID 0x1209
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "ODrive"
@@ -82,18 +82,18 @@
/* USER CODE END 0*/
/**
* @}
- */
+ */
/** @defgroup USBD_DESC_Private_Macros
* @{
- */
+ */
/**
* @}
- */
+ */
/** @defgroup USBD_DESC_Private_Variables
* @{
- */
+ */
uint8_t * USBD_FS_DeviceDescriptor( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t * USBD_FS_LangIDStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t * USBD_FS_ManufacturerStrDescriptor ( USBD_SpeedTypeDef speed , uint16_t *length);
@@ -103,8 +103,8 @@ uint8_t * USBD_FS_ConfigStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *l
uint8_t * USBD_FS_InterfaceStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length);
#ifdef USB_SUPPORT_USER_STRING_DESC
-uint8_t * USBD_FS_USRStringDesc (USBD_SpeedTypeDef speed, uint8_t idx , uint16_t *length);
-#endif /* USB_SUPPORT_USER_STRING_DESC */
+uint8_t * USBD_FS_USRStringDesc (USBD_SpeedTypeDef speed, uint8_t idx , uint16_t *length);
+#endif /* USB_SUPPORT_USER_STRING_DESC */
#if (USBD_LPM_ENABLED == 1)
uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed , uint16_t *length);
@@ -113,19 +113,19 @@ uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed , uint16_t *length);
USBD_DescriptorsTypeDef FS_Desc =
{
USBD_FS_DeviceDescriptor,
- USBD_FS_LangIDStrDescriptor,
+ USBD_FS_LangIDStrDescriptor,
USBD_FS_ManufacturerStrDescriptor,
USBD_FS_ProductStrDescriptor,
USBD_FS_SerialStrDescriptor,
USBD_FS_ConfigStrDescriptor,
USBD_FS_InterfaceStrDescriptor,
-#if (USBD_LPM_ENABLED == 1)
+#if (USBD_LPM_ENABLED == 1)
USBD_FS_USR_BOSDescriptor,
-#endif
+#endif
};
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
+ #pragma data_alignment=4
#endif
/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
@@ -133,10 +133,10 @@ __ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
0x12, /*bLength */
USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
- 0x01, /*bcdUSB */ /* changed to USB version 2.01
+ 0x01, /*bcdUSB */ /* changed to USB version 2.01
in order to support LPM L1 suspend
resume test of USBCV3.0*/
-#else
+#else
0x00, /* bcdUSB */
#endif
0x02,
@@ -146,20 +146,20 @@ __ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
USB_MAX_EP0_SIZE, /*bMaxPacketSize*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
- LOBYTE(USBD_PID_FS), /*idDevice*/
- HIBYTE(USBD_PID_FS), /*idDevice*/
+ LOBYTE(USBD_PID_FS), /*idVendor*/
+ HIBYTE(USBD_PID_FS), /*idVendor*/
0x00, /*bcdDevice rel. 2.00*/
0x02,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
- } ;
+ } ;
/* USB_DeviceDescriptor */
/* BOS descriptor */
#if (USBD_LPM_ENABLED == 1)
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
+ #pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END =
{
@@ -180,39 +180,39 @@ __ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END =
#endif
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
+ #pragma data_alignment=4
#endif
/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END =
{
- USB_LEN_LANGID_STR_DESC,
- USB_DESC_TYPE_STRING,
+ USB_LEN_LANGID_STR_DESC,
+ USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
- HIBYTE(USBD_LANGID_STRING),
+ HIBYTE(USBD_LANGID_STRING),
};
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma data_alignment=4
+ #pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
/**
* @}
- */
+ */
/** @defgroup USBD_DESC_Private_FunctionPrototypes
* @{
- */
+ */
/**
* @}
- */
+ */
/** @defgroup USBD_DESC_Private_Functions
* @{
- */
+ */
/**
-* @brief USBD_FS_DeviceDescriptor
+* @brief USBD_FS_DeviceDescriptor
* return the device descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -225,7 +225,7 @@ uint8_t * USBD_FS_DeviceDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
}
/**
-* @brief USBD_FS_LangIDStrDescriptor
+* @brief USBD_FS_LangIDStrDescriptor
* return the LangID string descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -233,12 +233,12 @@ uint8_t * USBD_FS_DeviceDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
*/
uint8_t * USBD_FS_LangIDStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
{
- *length = sizeof(USBD_LangIDDesc);
+ *length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
-* @brief USBD_FS_ProductStrDescriptor
+* @brief USBD_FS_ProductStrDescriptor
* return the product string descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -247,18 +247,18 @@ uint8_t * USBD_FS_LangIDStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *leng
uint8_t * USBD_FS_ProductStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
{
if(speed == 0)
- {
- USBD_GetString ((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
+ {
+ USBD_GetString (USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
else
{
- USBD_GetString ((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
+ USBD_GetString (USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
-* @brief USBD_FS_ManufacturerStrDescriptor
+* @brief USBD_FS_ManufacturerStrDescriptor
* return the manufacturer string descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -266,12 +266,12 @@ uint8_t * USBD_FS_ProductStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *len
*/
uint8_t * USBD_FS_ManufacturerStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
{
- USBD_GetString ((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
+ USBD_GetString (USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
-* @brief USBD_FS_SerialStrDescriptor
+* @brief USBD_FS_SerialStrDescriptor
* return the serial number string descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -280,18 +280,18 @@ uint8_t * USBD_FS_ManufacturerStrDescriptor( USBD_SpeedTypeDef speed , uint16_t
uint8_t * USBD_FS_SerialStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
- {
- USBD_GetString ((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
+ {
+ USBD_GetString (USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
}
else
{
- USBD_GetString ((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
+ USBD_GetString (USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
-* @brief USBD_FS_ConfigStrDescriptor
+* @brief USBD_FS_ConfigStrDescriptor
* return the configuration string descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -300,18 +300,18 @@ uint8_t * USBD_FS_SerialStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *leng
uint8_t * USBD_FS_ConfigStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
- {
- USBD_GetString ((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
+ {
+ USBD_GetString (USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
}
else
{
- USBD_GetString ((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
+ USBD_GetString (USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
}
- return USBD_StrDesc;
+ return USBD_StrDesc;
}
/**
-* @brief USBD_HS_InterfaceStrDescriptor
+* @brief USBD_HS_InterfaceStrDescriptor
* return the interface string descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -321,17 +321,17 @@ uint8_t * USBD_FS_InterfaceStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *l
{
if(speed == 0)
{
- USBD_GetString ((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
+ USBD_GetString (USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
}
else
{
- USBD_GetString ((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
+ USBD_GetString (USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
}
- return USBD_StrDesc;
+ return USBD_StrDesc;
}
#if (USBD_LPM_ENABLED == 1)
/**
- * @brief USBD_FS_USR_BOSDescriptor
+ * @brief USBD_FS_USR_BOSDescriptor
* return the BOS descriptor
* @param speed : current device speed
* @param length : pointer to data length variable
@@ -345,14 +345,14 @@ uint8_t *USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed , uint16_t *length)
#endif
/**
* @}
- */
+ */
/**
* @}
- */
+ */
/**
* @}
- */
+ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/