From efd78f754efcbb4acc5435734e2840102e02443e Mon Sep 17 00:00:00 2001 From: ourairquality Date: Fri, 21 Oct 2016 19:11:08 +1100 Subject: [PATCH] FreeRTOS v9.0.0 upgrade. --- FreeRTOS/Source/croutine.c | 146 +- FreeRTOS/Source/event_groups.c | 752 ++++ FreeRTOS/Source/include/FreeRTOS.h | 685 ++- FreeRTOS/Source/include/FreeRTOSConfig.h | 16 +- FreeRTOS/Source/include/StackMacros.h | 166 +- FreeRTOS/Source/include/croutine.h | 185 +- .../Source/include/deprecated_definitions.h | 321 ++ FreeRTOS/Source/include/event_groups.h | 797 ++++ FreeRTOS/Source/include/list.h | 215 +- FreeRTOS/Source/include/mpu_prototypes.h | 177 + FreeRTOS/Source/include/mpu_wrappers.h | 209 +- FreeRTOS/Source/include/portable.h | 364 +- FreeRTOS/Source/include/projdefs.h | 155 +- FreeRTOS/Source/include/queue.h | 613 ++- FreeRTOS/Source/include/semphr.h | 812 +++- FreeRTOS/Source/include/task.h | 1212 ++++- FreeRTOS/Source/include/timers.h | 685 ++- FreeRTOS/Source/list.c | 171 +- FreeRTOS/Source/portable/esp8266/port.c | 8 + FreeRTOS/Source/portable/esp8266/portmacro.h | 8 +- FreeRTOS/Source/queue.c | 1740 +++++--- FreeRTOS/Source/tasks.c | 3912 ++++++++++++----- FreeRTOS/Source/timers.c | 839 +++- README.md | 2 +- core/app_main.c | 2 +- examples/access_point/access_point.c | 2 +- examples/aws_iot/aws_iot.c | 6 +- examples/blink/blink.c | 4 +- examples/bmp180_i2c/bmp180_i2c.c | 4 +- examples/bmp280/bmp280_example.c | 4 +- examples/button/button.c | 4 +- examples/dht_sensor/dht_sensor.c | 2 +- .../ds18b20_broadcaster/ds18b20_broadcaster.c | 2 +- examples/ds18b20_onewire/ds18b20_onewire.c | 2 +- examples/ds3231_test/ds3231_test.c | 2 +- examples/experiments/timers/timers.c | 2 +- .../unaligned_load/unaligned_load.c | 2 +- examples/http_get/http_get.c | 2 +- examples/http_get_mbedtls/http_get_mbedtls.c | 2 +- examples/i2s_audio/i2s_audio_example.c | 2 +- examples/json_jsmn_simple/json_jsmn_simple.c | 2 +- examples/mqtt_client/mqtt_client.c | 6 +- examples/ota_basic/ota_basic.c | 2 +- examples/posix_fs/posix_fs_example.c | 2 +- examples/pwm_test/pwm_test.c | 2 +- examples/simple/simple.c | 4 +- examples/simple_cplusplus/simple.cpp | 2 +- examples/sntp/sntp_example.c | 2 +- examples/spiffs/spiffs_example.c | 2 +- examples/sysparam_editor/sysparam_editor.c | 2 +- examples/tls_server/tls_server.c | 2 +- examples/tsl2561/tsl2561_example.c | 2 +- examples/ws2812_i2s/ws2812_i2s_colour_loop.c | 2 +- examples/ws2812_rainbow/ws2812_rainbow.c | 2 +- extras/bmp180/bmp180.c | 2 +- extras/cpp_support/include/task.hpp | 2 +- extras/dhcpserver/dhcpserver.c | 2 +- extras/rboot-ota/ota-tftp.c | 2 +- lwip/lwip | 2 +- lwip/sys_arch.c | 2 +- 60 files changed, 10627 insertions(+), 3653 deletions(-) create mode 100644 FreeRTOS/Source/event_groups.c create mode 100644 FreeRTOS/Source/include/deprecated_definitions.h create mode 100644 FreeRTOS/Source/include/event_groups.h create mode 100644 FreeRTOS/Source/include/mpu_prototypes.h diff --git a/FreeRTOS/Source/croutine.c b/FreeRTOS/Source/croutine.c index b95ff45..993e09b 100644 --- a/FreeRTOS/Source/croutine.c +++ b/FreeRTOS/Source/croutine.c @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -66,6 +71,9 @@ #include "task.h" #include "croutine.h" +/* Remove the whole file is co-routines are not being used. */ +#if( configUSE_CO_ROUTINES != 0 ) + /* * Some kernel aware debuggers require data to be viewed to be global, rather * than file scope. @@ -76,17 +84,17 @@ /* Lists for ready and blocked co-routines. --------------------*/ -static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ -static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */ -static xList xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ -static xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ -static xList * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ -static xList xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ +static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ +static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ +static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ +static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ +static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ +static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ /* Other file private variables. --------------------------------*/ -corCRCB * pxCurrentCoRoutine = NULL; -static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0; -static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; +CRCB_t * pxCurrentCoRoutine = NULL; +static UBaseType_t uxTopCoRoutineReadyPriority = 0; +static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; /* The initial state of the co-routine when it is created. */ #define corINITIAL_STATE ( 0 ) @@ -104,7 +112,7 @@ static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = { \ uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ } \ - vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ + vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ } /* @@ -133,13 +141,13 @@ static void prvCheckDelayedList( void ); /*-----------------------------------------------------------*/ -signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ) +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) { -signed portBASE_TYPE xReturn; -corCRCB *pxCoRoutine; +BaseType_t xReturn; +CRCB_t *pxCoRoutine; /* Allocate the memory that will store the co-routine control block. */ - pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) ); + pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); if( pxCoRoutine ) { /* If pxCurrentCoRoutine is NULL then this is the first co-routine to @@ -166,14 +174,14 @@ corCRCB *pxCoRoutine; vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); - /* Set the co-routine control block as a link back from the xListItem. + /* Set the co-routine control block as a link back from the ListItem_t. This is so we can get back to the containing CRCB from a generic item in a list. */ listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); /* Now the co-routine has been initialised it can be added to the ready list at the correct priority. */ @@ -190,9 +198,9 @@ corCRCB *pxCoRoutine; } /*-----------------------------------------------------------*/ -void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ) +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) { -portTickType xTimeToWake; +TickType_t xTimeToWake; /* Calculate the time to wake - this may overflow but this is not a problem. */ @@ -201,7 +209,7 @@ portTickType xTimeToWake; /* 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. */ - ( void ) uxListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); /* The list item will be inserted in wake time order. */ listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); @@ -210,13 +218,13 @@ portTickType xTimeToWake; { /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); } else { /* The wake time has not overflowed, so we can use the current block list. */ - vListInsert( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); } if( pxEventList ) @@ -235,12 +243,12 @@ static void prvCheckPendingReadyList( void ) the ready lists itself. */ while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) { - corCRCB *pxUnblockedCRCB; + CRCB_t *pxUnblockedCRCB; /* The pending ready list can be accessed by an ISR. */ portDISABLE_INTERRUPTS(); { - pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); } portENABLE_INTERRUPTS(); @@ -253,7 +261,7 @@ static void prvCheckPendingReadyList( void ) static void prvCheckDelayedList( void ) { -corCRCB *pxCRCB; +CRCB_t *pxCRCB; xPassedTicks = xTaskGetTickCount() - xLastTickCount; while( xPassedTicks ) @@ -264,7 +272,7 @@ corCRCB *pxCRCB; /* If the tick count has overflowed we need to swap the ready lists. */ if( xCoRoutineTickCount == 0 ) { - xList * pxTemp; + List_t * pxTemp; /* Tick count has overflowed so we need to swap the delay lists. If there are any items in pxDelayedCoRoutineList here then there is an error! */ @@ -276,7 +284,7 @@ corCRCB *pxCRCB; /* See if this tick has made a timeout expire. */ while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) { - pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); + pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) { @@ -291,7 +299,7 @@ corCRCB *pxCRCB; have been moved to the pending ready list and the following line is still valid. Also the pvContainer parameter will have been set to NULL so the following lines are also valid. */ - uxListRemove( &( pxCRCB->xGenericListItem ) ); + ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); /* Is the co-routine waiting on an event also? */ if( pxCRCB->xEventListItem.pvContainer ) @@ -341,16 +349,16 @@ void vCoRoutineSchedule( void ) static void prvInitialiseCoRoutineLists( void ) { -unsigned portBASE_TYPE uxPriority; +UBaseType_t uxPriority; for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) { - vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); } - vListInitialise( ( xList * ) &xDelayedCoRoutineList1 ); - vListInitialise( ( xList * ) &xDelayedCoRoutineList2 ); - vListInitialise( ( xList * ) &xPendingReadyCoRoutineList ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); /* Start with pxDelayedCoRoutineList using list1 and the pxOverflowDelayedCoRoutineList using list2. */ @@ -359,17 +367,17 @@ unsigned portBASE_TYPE uxPriority; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) { -corCRCB *pxUnblockedCRCB; -signed portBASE_TYPE xReturn; +CRCB_t *pxUnblockedCRCB; +BaseType_t xReturn; /* This function is called from within an interrupt. It can only access event lists and the pending ready list. This function assumes that a check has already been made to ensure pxEventList is not empty. */ - pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) { @@ -383,3 +391,5 @@ signed portBASE_TYPE xReturn; return xReturn; } +#endif /* configUSE_CO_ROUTINES == 0 */ + diff --git a/FreeRTOS/Source/event_groups.c b/FreeRTOS/Source/event_groups.c new file mode 100644 index 0000000..b8df5fd --- /dev/null +++ b/FreeRTOS/Source/event_groups.c @@ -0,0 +1,752 @@ +/* + 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! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "event_groups.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +/* The following bit fields convey control information in a task's event list +item value. It is important they don't clash with the +taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ +#if configUSE_16_BIT_TICKS == 1 + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U + #define eventWAIT_FOR_ALL_BITS 0x0400U + #define eventEVENT_BITS_CONTROL_BYTES 0xff00U +#else + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL + #define eventWAIT_FOR_ALL_BITS 0x04000000UL + #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL +#endif + +typedef struct xEventGroupDefinition +{ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ + #endif +} EventGroup_t; + +/*-----------------------------------------------------------*/ + +/* + * Test the bits set in uxCurrentEventBits to see if the wait condition is met. + * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is + * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor + * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the + * wait condition is met if any of the bits set in uxBitsToWait for are also set + * in uxCurrentEventBits. + */ +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) + { + EventGroup_t *pxEventBits; + + /* A StaticEventGroup_t object must be provided. */ + configASSERT( pxEventGroupBuffer ); + + /* The user has provided a statically allocated event group - use it. */ + pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ + + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Both static and dynamic allocation can be used, so note that + this event group was created statically in case the event group + is later deleted. */ + pxEventBits->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); + } + + return ( EventGroupHandle_t ) pxEventBits; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + EventGroupHandle_t xEventGroupCreate( void ) + { + EventGroup_t *pxEventBits; + + /* Allocate the event group. */ + pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); + + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Both static and dynamic allocation can be used, so note this + event group was allocated statically in case the event group is + later deleted. */ + pxEventBits->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); + } + + return ( EventGroupHandle_t ) pxEventBits; + } + +#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) +{ +EventBits_t uxOriginalBitValue, uxReturn; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + uxOriginalBitValue = pxEventBits->uxEventBits; + + ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); + + if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + /* All the rendezvous bits are now set - no need to block. */ + uxReturn = ( uxOriginalBitValue | uxBitsToSet ); + + /* Rendezvous always clear the bits. They will have been cleared + already unless this is the only task in the rendezvous. */ + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + + xTicksToWait = 0; + } + else + { + if( xTicksToWait != ( TickType_t ) 0 ) + { + traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); + + /* This assignment is obsolete as uxReturn will get set after + the task unblocks, but some compilers mistakenly generate a + warning about uxReturn being returned without being set if the + assignment is omitted. */ + uxReturn = 0; + } + else + { + /* The rendezvous bits were not set, but no block time was + specified - just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + } + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + /* The task timed out, just return the current event bit value. */ + taskENTER_CRITICAL(); + { + uxReturn = pxEventBits->uxEventBits; + + /* Although the task got here because it timed out before the + bits it was waiting for were set, it is possible that since it + unblocked another task has set the bits. If this is the case + then it needs to clear the bits before exiting. */ + if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + xTimeoutOccurred = pdTRUE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* Control bits might be set as the task had blocked should not be + returned. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + + traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn, uxControlBits = 0; +BaseType_t xWaitConditionMet, xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + /* Check the user is not attempting to wait on the bits used by the kernel + itself, and that at least one bit is being requested. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; + + /* Check to see if the wait condition is already met or not. */ + xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); + + if( xWaitConditionMet != pdFALSE ) + { + /* The wait condition has already been met so there is no need to + block. */ + uxReturn = uxCurrentEventBits; + xTicksToWait = ( TickType_t ) 0; + + /* Clear the wait bits if requested to do so. */ + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The wait condition has not been met, but no block time was + specified, so just return the current value. */ + uxReturn = uxCurrentEventBits; + } + else + { + /* The task is going to block to wait for its required bits to be + set. uxControlBits are used to remember the specified behaviour of + this call to xEventGroupWaitBits() - for use when the event bits + unblock the task. */ + if( xClearOnExit != pdFALSE ) + { + uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xWaitForAllBits != pdFALSE ) + { + uxControlBits |= eventWAIT_FOR_ALL_BITS; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); + + /* This is obsolete as it will get set after the task unblocks, but + some compilers mistakenly generate a warning about the variable + being returned without being set if it is not done. */ + uxReturn = 0; + + traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + taskENTER_CRITICAL(); + { + /* The task timed out, just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + + /* It is possible that the event bits were updated between this + task leaving the Blocked state and running again. */ + if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) + { + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + /* Prevent compiler warnings when trace macros are not used. */ + xTimeoutOccurred = pdFALSE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* The task blocked so control bits may have been set. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + /* Check the user is not attempting to clear the bits used by the kernel + itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + taskENTER_CRITICAL(); + { + traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); + + /* The value returned is the event group value prior to the bits being + cleared. */ + uxReturn = pxEventBits->uxEventBits; + + /* Clear the bits. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) +{ +UBaseType_t uxSavedInterruptStatus; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + uxReturn = pxEventBits->uxEventBits; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) +{ +ListItem_t *pxListItem, *pxNext; +ListItem_t const *pxListEnd; +List_t *pxList; +EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xMatchFound = pdFALSE; + + /* Check the user is not attempting to set the bits used by the kernel + itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + pxList = &( pxEventBits->xTasksWaitingForBits ); + pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + vTaskSuspendAll(); + { + traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); + + pxListItem = listGET_HEAD_ENTRY( pxList ); + + /* Set the bits. */ + pxEventBits->uxEventBits |= uxBitsToSet; + + /* See if the new bit value should unblock any tasks. */ + while( pxListItem != pxListEnd ) + { + pxNext = listGET_NEXT( pxListItem ); + uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); + xMatchFound = pdFALSE; + + /* Split the bits waited for from the control bits. */ + uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; + uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; + + if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) + { + /* Just looking for single bit being set. */ + if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) + { + xMatchFound = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) + { + /* All bits are set. */ + xMatchFound = pdTRUE; + } + else + { + /* Need all bits to be set, but not all the bits were set. */ + } + + if( xMatchFound != pdFALSE ) + { + /* The bits match. Should the bits be cleared on exit? */ + if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) + { + uxBitsToClear |= uxBitsWaitedFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the actual event flag value in the task's event list + item before removing the task from the event list. The + eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows + that is was unblocked due to its required bits matching, rather + than because it timed out. */ + ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + /* Move onto the next list item. Note pxListItem->pxNext is not + used here as the list item may have been removed from the event list + and inserted into the ready/pending reading list. */ + pxListItem = pxNext; + } + + /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT + bit was set in the control word. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + ( void ) xTaskResumeAll(); + + return pxEventBits->uxEventBits; +} +/*-----------------------------------------------------------*/ + +void vEventGroupDelete( EventGroupHandle_t xEventGroup ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + + vTaskSuspendAll(); + { + traceEVENT_GROUP_DELETE( xEventGroup ); + + while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) + { + /* Unblock the task, returning 0 as the event list is being deleted + and cannot therefore have any bits set. */ + configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); + ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The event group can only have been allocated dynamically - free + it again. */ + vPortFree( pxEventBits ); + } + #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The event group could have been allocated statically or + dynamically, so check before attempting to free the memory. */ + if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxEventBits ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + } + ( void ) xTaskResumeAll(); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'set bits' command that was pended from +an interrupt. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) +{ + ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'clear bits' command that was pended from +an interrupt. */ +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) +{ + ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) +{ +BaseType_t xWaitConditionMet = pdFALSE; + + if( xWaitForAllBits == pdFALSE ) + { + /* Task only has to wait for one bit within uxBitsToWaitFor to be + set. Is one already set? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Task has to wait for all the bits in uxBitsToWaitFor to be set. + Are they set already? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return xWaitConditionMet; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if (configUSE_TRACE_FACILITY == 1) + + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) + { + UBaseType_t xReturn; + EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; + + if( xEventGroup == NULL ) + { + xReturn = 0; + } + else + { + xReturn = pxEventBits->uxEventGroupNumber; + } + + return xReturn; + } + +#endif + diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 3556bb4..63a08b3 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -65,92 +70,116 @@ #ifndef INC_FREERTOS_H #define INC_FREERTOS_H - /* * Include the generic headers required for the FreeRTOS port being used. */ #include -/* Basic FreeRTOS definitions. */ -#include "projdefs.h" +/* + * If stdint.h cannot be located then: + * + If using GCC ensure the -nostdint options is *not* being used. + * + Ensure the project's include path includes the directory in which your + * compiler stores stdint.h. + * + Set any compiler options necessary for it to support C99, as technically + * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any + * other way). + * + The FreeRTOS download includes a simple stdint.h definition that can be + * used in cases where none is provided by the compiler. The files only + * contains the typedefs required to build FreeRTOS. Read the instructions + * in FreeRTOS/source/stdint.readme for more information. + */ +#include /* READ COMMENT ABOVE. */ + +#ifdef __cplusplus +extern "C" { +#endif /* Application specific configuration options. */ #include -/* configUSE_PORT_OPTIMISED_TASK_SELECTION must be defined before portable.h -is included as it is used by the port layer. */ -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#endif +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" /* Definitions specific to the port being used. */ #include "portable.h" +/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ +#ifndef configUSE_NEWLIB_REENTRANT + #define configUSE_NEWLIB_REENTRANT 0 +#endif -/* Defines the prototype to which the application task hook function must -conform. */ -typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); - - - - - +/* Required if struct _reent is used. */ +#if ( configUSE_NEWLIB_REENTRANT == 1 ) + #include +#endif /* * Check all the required application specific macros have been defined. * These macros are application specific and (as downloaded) are defined * within FreeRTOSConfig.h. */ +#ifndef configMINIMAL_STACK_SIZE + #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. +#endif + +#ifndef configMAX_PRIORITIES + #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + #ifndef configUSE_PREEMPTION - #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_PREEMPTION 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_IDLE_HOOK - #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_TICK_HOOK - #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef configUSE_CO_ROUTINES - #error Missing definition: configUSE_CO_ROUTINES should 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 should 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 should 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 should 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 should 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 should 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 should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_16_BIT_TICKS - #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configMAX_PRIORITIES + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + +#ifndef configUSE_CO_ROUTINES + #define configUSE_CO_ROUTINES 0 +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #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 @@ -161,12 +190,8 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #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 +#ifndef INCLUDE_xTaskGetHandle + #define INCLUDE_xTaskGetHandle 0 #endif #ifndef INCLUDE_uxTaskGetStackHighWaterMark @@ -177,6 +202,40 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #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 @@ -213,10 +272,6 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #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 configASSERT #define configASSERT( x ) #define configASSERT_DEFINED 0 @@ -241,15 +296,6 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #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 @@ -262,6 +308,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB #endif +#ifndef portPRE_TASK_DELETE_HOOK + #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) +#endif + #ifndef portSETUP_TCB #define portSETUP_TCB( pxTCB ) ( void ) pxTCB #endif @@ -273,10 +323,11 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #if ( configQUEUE_REGISTRY_SIZE < 1 ) #define vQueueAddToRegistry( xQueue, pcName ) #define vQueueUnregisterQueue( xQueue ) + #define pcQueueGetName( xQueue ) #endif #ifndef portPOINTER_SIZE_TYPE - #define portPOINTER_SIZE_TYPE unsigned long + #define portPOINTER_SIZE_TYPE uint32_t #endif /* Remove any unused trace macros. */ @@ -363,6 +414,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #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 @@ -464,7 +519,7 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #endif #ifndef traceTASK_DELAY_UNTIL - #define traceTASK_DELAY_UNTIL() + #define traceTASK_DELAY_UNTIL( x ) #endif #ifndef traceTASK_DELAY @@ -511,6 +566,98 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) #endif +#ifndef traceMALLOC + #define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE + #define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef traceEVENT_GROUP_CREATE + #define traceEVENT_GROUP_CREATE( xEventGroup ) +#endif + +#ifndef traceEVENT_GROUP_CREATE_FAILED + #define traceEVENT_GROUP_CREATE_FAILED() +#endif + +#ifndef traceEVENT_GROUP_SYNC_BLOCK + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_SYNC_END + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_END + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS + #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR + #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS + #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_DELETE + #define traceEVENT_GROUP_DELETE( xEventGroup ) +#endif + +#ifndef tracePEND_FUNC_CALL + #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR + #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD + #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) +#endif + +#ifndef traceTASK_NOTIFY_TAKE_BLOCK + #define traceTASK_NOTIFY_TAKE_BLOCK() +#endif + +#ifndef traceTASK_NOTIFY_TAKE + #define traceTASK_NOTIFY_TAKE() +#endif + +#ifndef traceTASK_NOTIFY_WAIT_BLOCK + #define traceTASK_NOTIFY_WAIT_BLOCK() +#endif + +#ifndef traceTASK_NOTIFY_WAIT + #define traceTASK_NOTIFY_WAIT() +#endif + +#ifndef traceTASK_NOTIFY + #define traceTASK_NOTIFY() +#endif + +#ifndef traceTASK_NOTIFY_FROM_ISR + #define traceTASK_NOTIFY_FROM_ISR() +#endif + +#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR + #define traceTASK_NOTIFY_GIVE_FROM_ISR() +#endif + #ifndef configGENERATE_RUN_TIME_STATS #define configGENERATE_RUN_TIME_STATS 0 #endif @@ -538,21 +685,13 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #endif #ifndef portPRIVILEGE_BIT - #define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 ) + #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) #endif #ifndef portYIELD_WITHIN_API #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 @@ -593,10 +732,6 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #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 @@ -605,8 +740,324 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() #endif -/* For backward compatability. */ -#define eTaskStateGet eTaskGetState +#ifndef configUSE_TRACE_FACILITY + #define configUSE_TRACE_FACILITY 0 +#endif + +#ifndef mtCOVERAGE_TEST_MARKER + #define mtCOVERAGE_TEST_MARKER() +#endif + +#ifndef mtCOVERAGE_TEST_DELAY + #define mtCOVERAGE_TEST_DELAY() +#endif + +#ifndef portASSERT_IF_IN_ISR + #define portASSERT_IF_IN_ISR() +#endif + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +#ifndef configAPPLICATION_ALLOCATED_HEAP + #define configAPPLICATION_ALLOCATED_HEAP 0 +#endif + +#ifndef configUSE_TASK_NOTIFICATIONS + #define configUSE_TASK_NOTIFICATIONS 1 +#endif + +#ifndef portTICK_TYPE_IS_ATOMIC + #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 + the tick count is returned to the standard critical section macros. */ + #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) +#else + /* The tick type can be read atomically, so critical sections used when the + tick count is returned can be defined away. */ + #define portTICK_TYPE_ENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x +#endif + +/* Definitions to allow backward compatibility with FreeRTOS versions prior to +V8 if desired. */ +#ifndef configENABLE_BACKWARD_COMPATIBILITY + #define configENABLE_BACKWARD_COMPATIBILITY 1 +#endif + +#if configENABLE_BACKWARD_COMPATIBILITY == 1 + #define eTaskStateGet eTaskGetState + #define portTickType TickType_t + #define xTaskHandle TaskHandle_t + #define xQueueHandle QueueHandle_t + #define xSemaphoreHandle SemaphoreHandle_t + #define xQueueSetHandle QueueSetHandle_t + #define xQueueSetMemberHandle QueueSetMemberHandle_t + #define xTimeOutType TimeOut_t + #define xMemoryRegion MemoryRegion_t + #define xTaskParameters TaskParameters_t + #define xTaskStatusType TaskStatus_t + #define xTimerHandle TimerHandle_t + #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. */ + #define tmrTIMER_CALLBACK TimerCallbackFunction_t + #define pdTASK_CODE TaskFunction_t + #define xListItem ListItem_t + #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 +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 #endif /* INC_FREERTOS_H */ diff --git a/FreeRTOS/Source/include/FreeRTOSConfig.h b/FreeRTOS/Source/include/FreeRTOSConfig.h index d886828..248b65f 100644 --- a/FreeRTOS/Source/include/FreeRTOSConfig.h +++ b/FreeRTOS/Source/include/FreeRTOSConfig.h @@ -34,13 +34,6 @@ #define configUSE_TICK_HOOK 0 #endif #ifndef configCPU_CLOCK_HZ -/* This is the _default_ clock speed for the CPU. Can be either 80MHz - * or 160MHz, and the system will set the clock speed to match at startup. - -Note that it's possible to change the clock speed at runtime, so you -can/should use sdk_system_get_cpu_frequency() in order to determine the -current CPU frequency, in preference to this macro. -*/ #define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) #endif #ifndef configTICK_RATE_HZ @@ -88,6 +81,15 @@ current CPU frequency, in preference to this macro. #define configUSE_TIMERS 1 #endif +#ifndef configUSE_QUEUE_SETS +#define configUSE_QUEUE_SETS 1 +#endif +#ifndef configUSE_TASK_NOTIFICATIONS +#define configUSE_TASK_NOTIFICATIONS 1 +#endif +#ifndef configUSE_COUNTING_SEMAPHORES +#define configUSE_COUNTING_SEMAPHORES 1 +#endif #if configUSE_TIMERS #ifndef configTIMER_TASK_PRIORITY diff --git a/FreeRTOS/Source/include/StackMacros.h b/FreeRTOS/Source/include/StackMacros.h index 0a099df..13c6b82 100644 --- a/FreeRTOS/Source/include/StackMacros.h +++ b/FreeRTOS/Source/include/StackMacros.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -81,49 +86,31 @@ /*-----------------------------------------------------------*/ -#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) - - /* FreeRTOSConfig.h is not set to check for stack overflows. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() - -#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ -/*-----------------------------------------------------------*/ - -#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) - - /* FreeRTOSConfig.h is only set to use the first method of - overflow checking. */ - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() - -#endif -/*-----------------------------------------------------------*/ - -#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) +#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) /* Only the current stack state is to be checked. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + #define taskCHECK_FOR_STACK_OVERFLOW() \ { \ /* Is the currently saved stack pointer within the stack limit? */ \ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ } \ } -#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ -#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) +#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) /* Only the current stack state is to be checked. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + #define taskCHECK_FOR_STACK_OVERFLOW() \ { \ \ /* Is the currently saved stack pointer within the stack limit? */ \ if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ } \ } @@ -132,20 +119,18 @@ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ - static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ - \ - /* Has the extremity of the task stack ever been written over? */ \ - if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ - } \ + #define taskCHECK_FOR_STACK_OVERFLOW() \ + { \ + const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ + const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \ + \ + if( ( pulStack[ 0 ] != ulCheckValue ) || \ + ( pulStack[ 1 ] != ulCheckValue ) || \ + ( pulStack[ 2 ] != ulCheckValue ) || \ + ( pulStack[ 3 ] != ulCheckValue ) ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ @@ -153,27 +138,34 @@ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ - char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \ - static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ - \ - pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ - \ - /* Has the extremity of the task stack ever been written over? */ \ - if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ - } \ + #define taskCHECK_FOR_STACK_OVERFLOW() \ + { \ + int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ /*-----------------------------------------------------------*/ +/* Remove stack overflow macro if not being used. */ +#ifndef taskCHECK_FOR_STACK_OVERFLOW + #define taskCHECK_FOR_STACK_OVERFLOW() +#endif + + + #endif /* STACK_MACROS_H */ diff --git a/FreeRTOS/Source/include/croutine.h b/FreeRTOS/Source/include/croutine.h index 94503e3..4f003a0 100644 --- a/FreeRTOS/Source/include/croutine.h +++ b/FreeRTOS/Source/include/croutine.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -78,28 +83,28 @@ extern "C" { /* Used to hide the implementation of the co-routine control block. The control block structure however has to be included in the header due to the macro implementation of the co-routine functionality. */ -typedef void * xCoRoutineHandle; +typedef void * CoRoutineHandle_t; /* Defines the prototype to which co-routine functions must conform. */ -typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); +typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); typedef struct corCoRoutineControlBlock { - crCOROUTINE_CODE pxCoRoutineFunction; - xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ - unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ - unsigned short uxState; /*< Used internally by the co-routine implementation. */ -} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ + crCOROUTINE_CODE pxCoRoutineFunction; + ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ + UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + uint16_t uxState; /*< Used internally by the co-routine implementation. */ +} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ /** * croutine. h *
- portBASE_TYPE xCoRoutineCreate(
+ BaseType_t xCoRoutineCreate(
                                  crCOROUTINE_CODE pxCoRoutineCode,
-                                 unsigned portBASE_TYPE uxPriority,
-                                 unsigned portBASE_TYPE uxIndex
+                                 UBaseType_t uxPriority,
+                                 UBaseType_t uxIndex
                                );
* * Create a new co-routine and add it to the list of co-routines that are @@ -122,12 +127,12 @@ typedef struct corCoRoutineControlBlock * Example usage:
  // Co-routine to be created.
- void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
  // This may not be necessary for const variables.
  static const char cLedToFlash[ 2 ] = { 5, 6 };
- static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
+ static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
 
      // Must start every co-routine with a call to crSTART();
      crSTART( xHandle );
@@ -137,7 +142,7 @@ typedef struct corCoRoutineControlBlock
          // This co-routine just delays for a fixed period, then toggles
          // an LED.  Two co-routines are created using this function, so
          // the uxIndex parameter is used to tell the co-routine which
-         // LED to flash and how long to delay.  This assumes xQueue has
+         // LED to flash and how int32_t to delay.  This assumes xQueue has
          // already been created.
          vParTestToggleLED( cLedToFlash[ uxIndex ] );
          crDELAY( xHandle, uxFlashRates[ uxIndex ] );
@@ -150,9 +155,9 @@ typedef struct corCoRoutineControlBlock
  // Function that creates two co-routines.
  void vOtherFunction( void )
  {
- unsigned char ucParameterToPass;
- xTaskHandle xHandle;
-		
+ uint8_t ucParameterToPass;
+ TaskHandle_t xHandle;
+
      // Create two co-routines at priority 0.  The first is given index 0
      // so (from the code above) toggles LED 5 every 200 ticks.  The second
      // is given index 1 so toggles LED 6 every 400 ticks.
@@ -165,7 +170,7 @@ typedef struct corCoRoutineControlBlock
  * \defgroup xCoRoutineCreate xCoRoutineCreate
  * \ingroup Tasks
  */
-signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex );
+BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
 
 
 /**
@@ -212,17 +217,17 @@ void vCoRoutineSchedule( void );
 /**
  * croutine. h
  * 
- crSTART( xCoRoutineHandle xHandle );
+ crSTART( CoRoutineHandle_t xHandle );
* * This macro MUST always be called at the start of a co-routine function. * * Example usage:
  // Co-routine to be created.
- void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static long ulAVariable;
+ static int32_t ulAVariable;
 
      // Must start every co-routine with a call to crSTART();
      crSTART( xHandle );
@@ -238,7 +243,7 @@ void vCoRoutineSchedule( void );
  * \defgroup crSTART crSTART
  * \ingroup Tasks
  */
-#define crSTART( pxCRCB ) switch( ( ( corCRCB * )( pxCRCB ) )->uxState ) { case 0:
+#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
 
 /**
  * croutine. h
@@ -250,10 +255,10 @@ void vCoRoutineSchedule( void );
  * Example usage:
    
  // Co-routine to be created.
- void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static long ulAVariable;
+ static int32_t ulAVariable;
 
      // Must start every co-routine with a call to crSTART();
      crSTART( xHandle );
@@ -275,13 +280,13 @@ void vCoRoutineSchedule( void );
  * These macros are intended for internal use by the co-routine implementation
  * only.  The macros should not be used directly by application writers.
  */
-#define crSET_STATE0( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
-#define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
+#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
+#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
 
 /**
  * croutine. h
  *
- crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );
+ crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
* * Delay a co-routine for a fixed period of time. * @@ -294,18 +299,18 @@ void vCoRoutineSchedule( void ); * * @param xTickToDelay The number of ticks that the co-routine should delay * for. The actual amount of time this equates to is defined by - * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS * can be used to convert ticks to milliseconds. * * Example usage:
  // Co-routine to be created.
- void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
  // This may not be necessary for const variables.
  // We are to delay for 200ms.
- static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
+ static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
 
      // Must start every co-routine with a call to crSTART();
      crSTART( xHandle );
@@ -334,11 +339,11 @@ void vCoRoutineSchedule( void );
 /**
  * 
  crQUEUE_SEND(
-                  xCoRoutineHandle xHandle,
-                  xQueueHandle pxQueue,
+                  CoRoutineHandle_t xHandle,
+                  QueueHandle_t pxQueue,
                   void *pvItemToQueue,
-                  portTickType xTicksToWait,
-                  portBASE_TYPE *pxResult
+                  TickType_t xTicksToWait,
+                  BaseType_t *pxResult
              )
* * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine @@ -371,7 +376,7 @@ void vCoRoutineSchedule( void ); * to wait for space to become available on the queue, should space not be * available immediately. The actual amount of time this equates to is defined * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant - * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example * below). * * @param pxResult The variable pointed to by pxResult will be set to pdPASS if @@ -382,11 +387,11 @@ void vCoRoutineSchedule( void );
  // Co-routine function that blocks for a fixed period then posts a number onto
  // a queue.
- static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static portBASE_TYPE xNumberToPost = 0;
- static portBASE_TYPE xResult;
+ static BaseType_t xNumberToPost = 0;
+ static BaseType_t xResult;
 
     // Co-routines must begin with a call to crSTART().
     crSTART( xHandle );
@@ -433,11 +438,11 @@ void vCoRoutineSchedule( void );
  * croutine. h
  * 
   crQUEUE_RECEIVE(
-                     xCoRoutineHandle xHandle,
-                     xQueueHandle pxQueue,
+                     CoRoutineHandle_t xHandle,
+                     QueueHandle_t pxQueue,
                      void *pvBuffer,
-                     portTickType xTicksToWait,
-                     portBASE_TYPE *pxResult
+                     TickType_t xTicksToWait,
+                     BaseType_t *pxResult
                  )
* * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine @@ -469,7 +474,7 @@ void vCoRoutineSchedule( void ); * to wait for data to become available from the queue, should data not be * available immediately. The actual amount of time this equates to is defined * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant - * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the * crQUEUE_SEND example). * * @param pxResult The variable pointed to by pxResult will be set to pdPASS if @@ -480,11 +485,11 @@ void vCoRoutineSchedule( void );
  // A co-routine receives the number of an LED to flash from a queue.  It
  // blocks on the queue until the number is received.
- static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static portBASE_TYPE xResult;
- static unsigned portBASE_TYPE uxLEDToFlash;
+ static BaseType_t xResult;
+ static UBaseType_t uxLEDToFlash;
 
     // All co-routines must start with a call to crSTART().
     crSTART( xHandle );
@@ -525,9 +530,9 @@ void vCoRoutineSchedule( void );
  * croutine. h
  * 
   crQUEUE_SEND_FROM_ISR(
-                            xQueueHandle pxQueue,
+                            QueueHandle_t pxQueue,
                             void *pvItemToQueue,
-                            portBASE_TYPE xCoRoutinePreviouslyWoken
+                            BaseType_t xCoRoutinePreviouslyWoken
                        )
* * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the @@ -565,10 +570,10 @@ void vCoRoutineSchedule( void ); * Example usage:
  // A co-routine that blocks on a queue waiting for characters to be received.
- static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  char cRxedChar;
- portBASE_TYPE xResult;
+ BaseType_t xResult;
 
      // All co-routines must start with a call to crSTART().
      crSTART( xHandle );
@@ -595,7 +600,7 @@ void vCoRoutineSchedule( void );
  void vUART_ISR( void )
  {
  char cRxedChar;
- portBASE_TYPE xCRWokenByPost = pdFALSE;
+ BaseType_t xCRWokenByPost = pdFALSE;
 
      // We loop around reading characters until there are none left in the UART.
      while( UART_RX_REG_NOT_EMPTY() )
@@ -622,9 +627,9 @@ void vCoRoutineSchedule( void );
  * croutine. h
  * 
   crQUEUE_SEND_FROM_ISR(
-                            xQueueHandle pxQueue,
+                            QueueHandle_t pxQueue,
                             void *pvBuffer,
-                            portBASE_TYPE * pxCoRoutineWoken
+                            BaseType_t * pxCoRoutineWoken
                        )
* * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the @@ -663,12 +668,12 @@ void vCoRoutineSchedule( void );
  // A co-routine that posts a character to a queue then blocks for a fixed
  // period.  The character is incremented each time.
- static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
  {
  // cChar holds its value while this co-routine is blocked and must therefore
  // be declared static.
  static char cCharToTx = 'a';
- portBASE_TYPE xResult;
+ BaseType_t xResult;
 
      // All co-routines must start with a call to crSTART().
      crSTART( xHandle );
@@ -711,7 +716,7 @@ void vCoRoutineSchedule( void );
  void vUART_ISR( void )
  {
  char cCharToTx;
- portBASE_TYPE xCRWokenByPost = pdFALSE;
+ BaseType_t xCRWokenByPost = pdFALSE;
 
      while( UART_TX_REG_EMPTY() )
      {
@@ -739,7 +744,7 @@ void vCoRoutineSchedule( void );
  * Removes the current co-routine from its ready list and places it in the
  * appropriate delayed list.
  */
-void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList );
+void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );
 
 /*
  * This function is intended for internal use by the queue implementation only.
@@ -748,7 +753,7 @@ void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList
  * Removes the highest priority co-routine from the event list and places it in
  * the pending ready list.
  */
-signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList );
+BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
 
 #ifdef __cplusplus
 }
diff --git a/FreeRTOS/Source/include/deprecated_definitions.h b/FreeRTOS/Source/include/deprecated_definitions.h
new file mode 100644
index 0000000..4ea816c
--- /dev/null
+++ b/FreeRTOS/Source/include/deprecated_definitions.h
@@ -0,0 +1,321 @@
+/*
+    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!
+*/
+
+#ifndef DEPRECATED_DEFINITIONS_H
+#define DEPRECATED_DEFINITIONS_H
+
+
+/* Each FreeRTOS port has a unique portmacro.h header file.  Originally a
+pre-processor definition was used to ensure the pre-processor found the correct
+portmacro.h file for the port being used.  That scheme was deprecated in favour
+of setting the compiler's include path such that it found the correct
+portmacro.h file - removing the need for the constant and allowing the
+portmacro.h file to be located anywhere in relation to the port being used.  The
+definitions below remain in the code for backward compatibility only.  New
+projects should not use them. */
+
+#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
+	#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
+	typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
+	#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
+	typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef GCC_MEGA_AVR
+	#include "../portable/GCC/ATMega323/portmacro.h"
+#endif
+
+#ifdef IAR_MEGA_AVR
+	#include "../portable/IAR/ATMega323/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC24_PORT
+	#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
+#endif
+
+#ifdef MPLAB_DSPIC_PORT
+	#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC18F_PORT
+	#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC32MX_PORT
+	#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
+#endif
+
+#ifdef _FEDPICC
+	#include "libFreeRTOS/Include/portmacro.h"
+#endif
+
+#ifdef SDCC_CYGNAL
+	#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7
+	#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7_ECLIPSE
+	#include "portmacro.h"
+#endif
+
+#ifdef ROWLEY_LPC23xx
+	#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
+#endif
+
+#ifdef IAR_MSP430
+	#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
+#endif
+
+#ifdef GCC_MSP430
+	#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ROWLEY_MSP430
+	#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ARM7_LPC21xx_KEIL_RVDS
+	#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
+#endif
+
+#ifdef SAM7_GCC
+	#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
+#endif
+
+#ifdef SAM7_IAR
+	#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
+#endif
+
+#ifdef SAM9XE_IAR
+	#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
+#endif
+
+#ifdef LPC2000_IAR
+	#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
+#endif
+
+#ifdef STR71X_IAR
+	#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
+#endif
+
+#ifdef STR75X_IAR
+	#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
+#endif
+
+#ifdef STR75X_GCC
+	#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
+#endif
+
+#ifdef STR91X_IAR
+	#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
+#endif
+
+#ifdef GCC_H8S
+	#include "../../Source/portable/GCC/H8S2329/portmacro.h"
+#endif
+
+#ifdef GCC_AT91FR40008
+	#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
+#endif
+
+#ifdef RVDS_ARMCM3_LM3S102
+	#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3_LM3S102
+	#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3
+	#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARM_CM3
+	#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARMCM3_LM
+	#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef HCS12_CODE_WARRIOR
+	#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
+#endif
+
+#ifdef MICROBLAZE_GCC
+	#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
+#endif
+
+#ifdef TERN_EE
+	#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
+#endif
+
+#ifdef GCC_HCS12
+	#include "../../Source/portable/GCC/HCS12/portmacro.h"
+#endif
+
+#ifdef GCC_MCF5235
+    #include "../../Source/portable/GCC/MCF5235/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_GCC
+	#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_CODEWARRIOR
+	#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef GCC_PPC405
+	#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
+#endif
+
+#ifdef GCC_PPC440
+	#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
+#endif
+
+#ifdef _16FX_SOFTUNE
+	#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
+#endif
+
+#ifdef BCC_INDUSTRIAL_PC_PORT
+	/* A short file name has to be used in place of the normal
+	FreeRTOSConfig.h when using the Borland compiler. */
+	#include "frconfig.h"
+	#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
+    typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef BCC_FLASH_LITE_186_PORT
+	/* A short file name has to be used in place of the normal
+	FreeRTOSConfig.h when using the Borland compiler. */
+	#include "frconfig.h"
+	#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
+    typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef __GNUC__
+   #ifdef __AVR32_AVR32A__
+	   #include "portmacro.h"
+   #endif
+#endif
+
+#ifdef __ICCAVR32__
+   #ifdef __CORE__
+      #if __CORE__ == __AVR32A__
+	      #include "portmacro.h"
+      #endif
+   #endif
+#endif
+
+#ifdef __91467D
+	#include "portmacro.h"
+#endif
+
+#ifdef __96340
+	#include "portmacro.h"
+#endif
+
+
+#ifdef __IAR_V850ES_Fx3__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3_L__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx2__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Hx2__
+	#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3__
+	#include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3L__
+	#include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#endif /* DEPRECATED_DEFINITIONS_H */
+
diff --git a/FreeRTOS/Source/include/event_groups.h b/FreeRTOS/Source/include/event_groups.h
new file mode 100644
index 0000000..7331c91
--- /dev/null
+++ b/FreeRTOS/Source/include/event_groups.h
@@ -0,0 +1,797 @@
+/*
+    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!
+*/
+
+#ifndef EVENT_GROUPS_H
+#define EVENT_GROUPS_H
+
+#ifndef INC_FREERTOS_H
+	#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
+#endif
+
+/* FreeRTOS includes. */
+#include "timers.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An event group is a collection of bits to which an application can assign a
+ * meaning.  For example, an application may create an event group to convey
+ * the status of various CAN bus related events in which bit 0 might mean "A CAN
+ * message has been received and is ready for processing", bit 1 might mean "The
+ * application has queued a message that is ready for sending onto the CAN
+ * network", and bit 2 might mean "It is time to send a SYNC message onto the
+ * CAN network" etc.  A task can then test the bit values to see which events
+ * are active, and optionally enter the Blocked state to wait for a specified
+ * bit or a group of specified bits to be active.  To continue the CAN bus
+ * example, a CAN controlling task can enter the Blocked state (and therefore
+ * not consume any processing time) until either bit 0, bit 1 or bit 2 are
+ * active, at which time the bit that was actually active would inform the task
+ * which action it had to take (process a received message, send a message, or
+ * send a SYNC).
+ *
+ * The event groups implementation contains intelligence to avoid race
+ * conditions that would otherwise occur were an application to use a simple
+ * variable for the same purpose.  This is particularly important with respect
+ * to when a bit within an event group is to be cleared, and when bits have to
+ * be set and then tested atomically - as is the case where event groups are
+ * used to create a synchronisation point between multiple tasks (a
+ * 'rendezvous').
+ *
+ * \defgroup EventGroup
+ */
+
+
+
+/**
+ * event_groups.h
+ *
+ * Type by which event groups are referenced.  For example, a call to
+ * xEventGroupCreate() returns an EventGroupHandle_t variable that can then
+ * be used as a parameter to other event group functions.
+ *
+ * \defgroup EventGroupHandle_t EventGroupHandle_t
+ * \ingroup EventGroup
+ */
+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.
+ *
+ * \defgroup EventBits_t EventBits_t
+ * \ingroup EventGroup
+ */
+typedef TickType_t EventBits_t;
+
+/**
+ * event_groups.h
+ *
+ EventGroupHandle_t xEventGroupCreate( void );
+ 
+ * + * 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. + * + * @return If the event group was created then a handle to the event group is + * returned. If there was insufficient FreeRTOS heap available to create the + * event group then NULL is returned. See http://www.freertos.org/a00111.html + * + * Example usage: +
+	// Declare a variable to hold the created event group.
+	EventGroupHandle_t xCreatedEventGroup;
+
+	// Attempt to create the event group.
+	xCreatedEventGroup = xEventGroupCreate();
+
+	// Was the event group created successfully?
+	if( xCreatedEventGroup == NULL )
+	{
+		// The event group was not created because there was insufficient
+		// FreeRTOS heap available.
+	}
+	else
+	{
+		// The event group was created.
+	}
+   
+ * \defgroup xEventGroupCreate xEventGroupCreate + * \ingroup EventGroup + */ +#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 + *
+	EventBits_t xEventGroupWaitBits( 	EventGroupHandle_t xEventGroup,
+										const EventBits_t uxBitsToWaitFor,
+										const BaseType_t xClearOnExit,
+										const BaseType_t xWaitForAllBits,
+										const TickType_t xTicksToWait );
+ 
+ * + * [Potentially] block to wait for one or more bits to be set within a + * previously created event group. + * + * This function cannot be called from an interrupt. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and/or bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within + * uxBitsToWaitFor that are set within the event group will be cleared before + * xEventGroupWaitBits() returns if the wait condition was met (if the function + * returns for a reason other than a timeout). If xClearOnExit is set to + * pdFALSE then the bits set in the event group are not altered when the call to + * xEventGroupWaitBits() returns. + * + * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then + * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor + * are set or the specified block time expires. If xWaitForAllBits is set to + * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set + * in uxBitsToWaitFor is set or the specified block time expires. The block + * time is specified by the xTicksToWait parameter. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for one/all (depending on the xWaitForAllBits value) of the bits specified by + * uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupWaitBits() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupWaitBits() returned because the bits it was waiting for were set + * then the returned value is the event group value before any bits were + * automatically cleared in the case that xClearOnExit parameter was set to + * pdTRUE. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+   const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+		// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
+		// the event group.  Clear the bits before exiting.
+		uxBits = xEventGroupWaitBits(
+					xEventGroup,	// The event group being tested.
+					BIT_0 | BIT_4,	// The bits within the event group to wait for.
+					pdTRUE,			// BIT_0 and BIT_4 should be cleared before returning.
+					pdFALSE,		// Don't wait for both bits, either bit will do.
+					xTicksToWait );	// Wait a maximum of 100ms for either bit to be set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// xEventGroupWaitBits() returned because both bits were set.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_0 was set.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_4 was set.
+		}
+		else
+		{
+			// xEventGroupWaitBits() returned because xTicksToWait ticks passed
+			// without either BIT_0 or BIT_4 becoming set.
+		}
+   }
+   
+ * \defgroup xEventGroupWaitBits xEventGroupWaitBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+ 
+ * + * Clear bits within an event group. This function cannot be called from an + * interrupt. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear + * in the event group. For example, to clear bit 3 only, set uxBitsToClear to + * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09. + * + * @return The value of the event group before the specified bits were cleared. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Clear bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupClearBits(
+								xEventGroup,	// The event group being updated.
+								BIT_0 | BIT_4 );// The bits being cleared.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
+			// called.  Both will now be clear (not set).
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 were set in the first place.
+		}
+   }
+   
+ * \defgroup xEventGroupClearBits xEventGroupClearBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * A version of xEventGroupClearBits() that can be called from an interrupt. + * + * 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 + * 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 + * task. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. + * 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 + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+		// Clear bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupClearBitsFromISR(
+							xEventGroup,	 // The event group being updated.
+							BIT_0 | BIT_4 ); // The bits being set.
+
+		if( xResult == pdPASS )
+		{
+			// The message was posted successfully.
+		}
+  }
+   
+ * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; +#else + #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * Set bits within an event group. + * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() + * is a version that can be called from an interrupt. + * + * Setting bits in an event group will automatically unblock tasks that are + * blocked waiting for the bits. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @return The value of the event group at the time the call to + * xEventGroupSetBits() returns. There are two reasons why the returned value + * might have the bits specified by the uxBitsToSet parameter cleared. First, + * if setting a bit results in a task that was waiting for the bit leaving the + * blocked state then it is possible the bit will be cleared automatically + * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any + * unblocked (or otherwise Ready state) task that has a priority above that of + * the task that called xEventGroupSetBits() will execute and may change the + * event group value before the call to xEventGroupSetBits() returns. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupSetBits(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4 );// The bits being set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 remained set when the function returned.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 remained set when the function returned, but bit 4 was
+			// cleared.  It might be that bit 4 was cleared automatically as a
+			// task that was waiting for bit 4 was removed from the Blocked
+			// state.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 remained set when the function returned, but bit 0 was
+			// cleared.  It might be that bit 0 was cleared automatically as a
+			// task that was waiting for bit 0 was removed from the Blocked
+			// state.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 remained set.  It might be that a task
+			// was waiting for both of the bits to be set, and the bits were
+			// cleared as the task left the Blocked state.
+		}
+   }
+   
+ * \defgroup xEventGroupSetBits xEventGroupSetBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
+ 
+ * + * A version of xEventGroupSetBits() that can be called from an interrupt. + * + * 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 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. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task is higher than the priority of the + * currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE by + * xEventGroupSetBitsFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+   BaseType_t xHigherPriorityTaskWoken, xResult;
+
+		// xHigherPriorityTaskWoken must be initialised to pdFALSE.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupSetBitsFromISR(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4   // The bits being set.
+							&xHigherPriorityTaskWoken );
+
+		// Was the message posted successfully?
+		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() -
+			// refer to the documentation page for the port being used.
+			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+		}
+  }
+   
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#else + #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSync(	EventGroupHandle_t xEventGroup,
+									const EventBits_t uxBitsToSet,
+									const EventBits_t uxBitsToWaitFor,
+									TickType_t xTicksToWait );
+ 
+ * + * Atomically set bits within an event group, then wait for a combination of + * bits to be set within the same event group. This functionality is typically + * used to synchronise multiple tasks, where each task has to wait for the other + * tasks to reach a synchronisation point before proceeding. + * + * This function cannot be used from an interrupt. + * + * The function will return before its block time expires if the bits specified + * by the uxBitsToWait parameter are set, or become set within that time. In + * this case all the bits specified by uxBitsToWait will be automatically + * cleared before the function returns. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToSet The bits to set in the event group before determining + * if, and possibly waiting for, all the bits specified by the uxBitsToWait + * parameter are set. + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for all of the bits specified by uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupSync() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupSync() returned because all the bits it was waiting for were + * set then the returned value is the event group value before any bits were + * automatically cleared. + * + * Example usage: +
+ // Bits used by the three tasks.
+ #define TASK_0_BIT		( 1 << 0 )
+ #define TASK_1_BIT		( 1 << 1 )
+ #define TASK_2_BIT		( 1 << 2 )
+
+ #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+
+ // Use an event group to synchronise three tasks.  It is assumed this event
+ // group has already been created elsewhere.
+ EventGroupHandle_t xEventBits;
+
+ void vTask0( void *pvParameters )
+ {
+ EventBits_t uxReturn;
+ TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 0 in the event flag to note this task has reached the
+		// sync point.  The other two tasks will set the other two bits defined
+		// by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
+		// point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
+		// for this to happen.
+		uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
+
+		if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
+		{
+			// All three tasks reached the synchronisation point before the call
+			// to xEventGroupSync() timed out.
+		}
+	}
+ }
+
+ void vTask1( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 1 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	 }
+ }
+
+ void vTask2( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 2 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	}
+ }
+
+ 
+ * \defgroup xEventGroupSync xEventGroupSync + * \ingroup EventGroup + */ +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
+ 
+ * + * Returns the current value of the bits in an event group. This function + * cannot be used from an interrupt. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBits() was called. + * + * \defgroup xEventGroupGetBits xEventGroupGetBits + * \ingroup EventGroup + */ +#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
+ 
+ * + * A version of xEventGroupGetBits() that can be called from an ISR. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. + * + * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR + * \ingroup EventGroup + */ +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	void xEventGroupDelete( EventGroupHandle_t xEventGroup );
+ 
+ * + * Delete an event group that was previously created by a call to + * xEventGroupCreate(). Tasks that are blocked on the event group will be + * unblocked and obtain 0 as the event group's value. + * + * @param xEventGroup The event group being deleted. + */ +void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; + +/* For internal use only. */ +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 + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT_GROUPS_H */ + + diff --git a/FreeRTOS/Source/include/list.h b/FreeRTOS/Source/include/list.h index a8bafb0..a080d27 100644 --- a/FreeRTOS/Source/include/list.h +++ b/FreeRTOS/Source/include/list.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -67,7 +72,7 @@ * heavily for the schedulers needs, it is also available for use by * application code. * - * xLists can only store pointers to xListItems. Each xListItem contains a + * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a * numeric value (xItemValue). Most of the time the lists are sorted in * descending item value order. * @@ -90,6 +95,9 @@ * \ingroup FreeRTOSIntro */ +#ifndef INC_FREERTOS_H + #error FreeRTOS.h must be included before list.h +#endif #ifndef LIST_H #define LIST_H @@ -114,8 +122,8 @@ * complete and obvious failure of the scheduler. If this is ever experienced * then the volatile qualifier can be inserted in the relevant places within the * list structures by simply defining configLIST_VOLATILE to volatile in - * FreeRTOSConfig.h (as per the example at the bottom of this comment block). - * If configLIST_VOLATILE is not defined then the preprocessor directives below + * FreeRTOSConfig.h (as per the example at the bottom of this comment block). + * If configLIST_VOLATILE is not defined then the preprocessor directives below * will simply #define configLIST_VOLATILE away completely. * * To use volatile list structure members then add the following line to @@ -129,36 +137,79 @@ #ifdef __cplusplus extern "C" { #endif + +/* Macros that can be used to place known values within the list structures, +then check that the known values do not get corrupted during the execution of +the application. These may catch the list data structures being overwritten in +memory. They will not catch data errors caused by incorrect configuration or +use of FreeRTOS.*/ +#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) + /* Define the macros to do nothing. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) + #define listTEST_LIST_INTEGRITY( pxList ) +#else + /* Define macros that add new members into the list structures. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; + + /* Define macros that set the new structure members to known values. */ + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + + /* Define macros that will assert if one of the structure members does not + contain its expected value. */ + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) + #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) +#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ + + /* * Definition of the only type of object that a list can contain. */ struct xLIST_ITEM { - configLIST_VOLATILE portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ - struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next xListItem in the list. */ - struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;/*< Pointer to the previous xListItem in the list. */ - void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ - void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ + listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ }; -typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ +typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ struct xMINI_LIST_ITEM { - configLIST_VOLATILE portTickType xItemValue; + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; struct xLIST_ITEM * configLIST_VOLATILE pxNext; struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; }; -typedef struct xMINI_LIST_ITEM xMiniListItem; +typedef struct xMINI_LIST_ITEM MiniListItem_t; /* * Definition of the type of queue used by the scheduler. */ typedef struct xLIST { - configLIST_VOLATILE unsigned portBASE_TYPE uxNumberOfItems; - xListItem * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ - xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ -} xList; + listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE UBaseType_t uxNumberOfItems; + ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ + listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +} List_t; /* * Access macro to set the owner of a list item. The owner of a list item @@ -176,7 +227,7 @@ typedef struct xLIST * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \ingroup LinkedList */ -#define listGET_LIST_ITEM_OWNER( pxListItem ) ( pxListItem )->pvOwner +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) /* * Access macro to set the value of the list item. In most cases the value is @@ -185,26 +236,50 @@ typedef struct xLIST * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE * \ingroup LinkedList */ -#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) /* * Access macro to retrieve the value of the list item. The value can - * represent anything - for example a the priority of a task, or the time at + * represent anything - for example the priority of a task, or the time at * which a task should be unblocked. * * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \ingroup LinkedList */ -#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) /* - * Access macro the retrieve the value of the list item at the head of a given + * Access macro to retrieve the value of the list item at the head of a given * list. * * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \ingroup LinkedList */ -#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue ) +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_NEXT listGET_NEXT + * \ingroup LinkedList + */ +#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) + +/* + * Return the list item that marks the end of the list + * + * \page listGET_END_MARKER listGET_END_MARKER + * \ingroup LinkedList + */ +#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) /* * Access macro to determine if a list contains any items. The macro will @@ -213,19 +288,19 @@ typedef struct xLIST * \page listLIST_IS_EMPTY listLIST_IS_EMPTY * \ingroup LinkedList */ -#define listLIST_IS_EMPTY( pxList ) ( ( portBASE_TYPE ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) ) +#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ) /* * Access macro to return the number of items in the list. */ -#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) /* * Access function to obtain the owner of the next entry in a 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 - * and returns that entries pxOwner parameter. Using multiple calls to this + * and returns that entry's pxOwner parameter. Using multiple calls to this * function it is therefore possible to move through every item contained in * a list. * @@ -234,6 +309,7 @@ typedef struct xLIST * The pxOwner parameter effectively creates a two way link between the list * item and its owner. * + * @param pxTCB pxTCB is set to the address of the owner of the next list item. * @param pxList The list from which the next item owner is to be returned. * * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY @@ -241,7 +317,7 @@ typedef struct xLIST */ #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ { \ -xList * const pxConstList = ( pxList ); \ +List_t * const pxConstList = ( pxList ); \ /* Increment the index to the next item and return the item, ensuring */ \ /* we don't return the marker used at the end of the list. */ \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ @@ -278,16 +354,15 @@ xList * const pxConstList = ( pxList ); \ * * @param pxList The list we want to know if the list item is within. * @param pxListItem The list item we want to know if is in the list. - * @return pdTRUE is the list item is in the list, otherwise pdFALSE. - * pointer against + * @return pdTRUE if the list item is in the list, otherwise pdFALSE. */ -#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( portBASE_TYPE ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) /* * Return the list a list item is contained within (referenced from). * * @param pxListItem The list item being queried. - * @return A pointer to the xList object that references the pxListItem + * @return A pointer to the List_t object that references the pxListItem */ #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) @@ -308,7 +383,7 @@ xList * const pxConstList = ( pxList ); \ * \page vListInitialise vListInitialise * \ingroup LinkedList */ -void vListInitialise( xList * const pxList ); +void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION; /* * Must be called before a list item is used. This sets the list container to @@ -319,7 +394,7 @@ void vListInitialise( xList * const pxList ); * \page vListInitialiseItem vListInitialiseItem * \ingroup LinkedList */ -void vListInitialiseItem( xListItem * const pxItem ); +void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; /* * Insert a list item into a list. The item will be inserted into the list in @@ -327,24 +402,24 @@ void vListInitialiseItem( xListItem * const pxItem ); * * @param pxList The list into which the item is to be inserted. * - * @param pxNewListItem The item to that is to be placed in the list. + * @param pxNewListItem The item that is to be placed in the list. * * \page vListInsert vListInsert * \ingroup LinkedList */ -void vListInsert( xList * const pxList, xListItem * const pxNewListItem ); +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; /* * Insert a list item into a list. The item will be inserted in a position * such that it will be the last item within the list returned by multiple * calls to listGET_OWNER_OF_NEXT_ENTRY. * - * The list member pvIndex is used to walk through a list. Calling - * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. * Placing an item in a list using vListInsertEnd effectively places the item - * in the list position pointed to by pvIndex. This means that every other + * 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. * @@ -353,7 +428,7 @@ void vListInsert( xList * const pxList, xListItem * const pxNewListItem ); * \page vListInsertEnd vListInsertEnd * \ingroup LinkedList */ -void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ); +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; /* * Remove an item from a list. The list item has a pointer to the list that @@ -368,7 +443,7 @@ void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ); * \page uxListRemove uxListRemove * \ingroup LinkedList */ -unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove ); +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } diff --git a/FreeRTOS/Source/include/mpu_prototypes.h b/FreeRTOS/Source/include/mpu_prototypes.h new file mode 100644 index 0000000..8f7500b --- /dev/null +++ b/FreeRTOS/Source/include/mpu_prototypes.h @@ -0,0 +1,177 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * When the MPU is used the standard (non MPU) API functions are mapped to + * equivalents that start "MPU_", the prototypes for which are defined in this + * header files. This will cause the application code to call the MPU_ version + * which wraps the non-MPU version with privilege promoting then demoting code, + * so the kernel code always runs will full privileges. + */ + + +#ifndef MPU_PROTOTYPES_H +#define MPU_PROTOTYPES_H + +/* MPU versions of tasks.h API function. */ +BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ); +TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ); +BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); +void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ); +void MPU_vTaskDelay( const TickType_t xTicksToDelay ); +void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ); +BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ); +UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t xTask ); +eTaskState MPU_eTaskGetState( TaskHandle_t xTask ); +void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ); +void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); +void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ); +void MPU_vTaskResume( TaskHandle_t xTaskToResume ); +void MPU_vTaskStartScheduler( void ); +void MPU_vTaskSuspendAll( void ); +BaseType_t MPU_xTaskResumeAll( void ); +TickType_t MPU_xTaskGetTickCount( void ); +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ); +char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ); +TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery ); +UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); +void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ); +TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ); +void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ); +void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ); +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); +TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ); +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ); +void MPU_vTaskList( char * pcWriteBuffer ); +void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ); +BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ); +BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); +uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); +BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ); +BaseType_t MPU_xTaskIncrementTick( void ); +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ); +void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); +BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ); +void MPU_vTaskMissedYield( void ); +BaseType_t MPU_xTaskGetSchedulerState( void ); + +/* MPU versions of queue.h API function. */ +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ); +BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ); +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ); +UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ); +void MPU_vQueueDelete( QueueHandle_t xQueue ); +QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ); +QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ); +QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ); +QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ); +void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ); +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ); +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ); +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ); +void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ); +const char * MPU_pcQueueGetName( QueueHandle_t xQueue ); +QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ); +QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ); +QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ); +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ); +BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ); +void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ); +UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ); +uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ); + +/* MPU versions of timers.h API function. */ +TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ); +TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ); +void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ); +void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); +BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ); +TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ); +BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ); +const char * MPU_pcTimerGetName( TimerHandle_t xTimer ); +TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ); +TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ); +BaseType_t MPU_xTimerCreateTimerTask( void ); +BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ); + +/* MPU versions of event_group.h API function. */ +EventGroupHandle_t MPU_xEventGroupCreate( void ); +EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ); +EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ); +EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); +EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); +EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ); +void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ); +UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup ); + +#endif /* MPU_PROTOTYPES_H */ + diff --git a/FreeRTOS/Source/include/mpu_wrappers.h b/FreeRTOS/Source/include/mpu_wrappers.h index 6635069..78f5a9a 100644 --- a/FreeRTOS/Source/include/mpu_wrappers.h +++ b/FreeRTOS/Source/include/mpu_wrappers.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -74,60 +79,104 @@ 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 xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended - #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 + /* + * 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 xQueuePeekFromISR MPU_xQueuePeekFromISR + /* 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 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 + /* Map standard timer.h API functions to the MPU equivalents. */ + #define xTimerCreate MPU_xTimerCreate + #define xTimerCreateStatic MPU_xTimerCreateStatic + #define pvTimerGetTimerID MPU_pvTimerGetTimerID + #define vTimerSetTimerID MPU_vTimerSetTimerID + #define xTimerIsTimerActive MPU_xTimerIsTimerActive + #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle + #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall + #define pcTimerGetName MPU_pcTimerGetName + #define xTimerGetPeriod MPU_xTimerGetPeriod + #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime + #define xTimerGenericCommand MPU_xTimerGenericCommand + + /* Map standard event_group.h API functions to the MPU equivalents. */ + #define xEventGroupCreate MPU_xEventGroupCreate + #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic + #define xEventGroupWaitBits MPU_xEventGroupWaitBits + #define xEventGroupClearBits MPU_xEventGroupClearBits + #define xEventGroupSetBits MPU_xEventGroupSetBits + #define xEventGroupSync MPU_xEventGroupSync + #define vEventGroupDelete MPU_vEventGroupDelete + /* Remove the privileged function macro. */ #define PRIVILEGED_FUNCTION diff --git a/FreeRTOS/Source/include/portable.h b/FreeRTOS/Source/include/portable.h index cb83f26..b9f8be3 100644 --- a/FreeRTOS/Source/include/portable.h +++ b/FreeRTOS/Source/include/portable.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -69,255 +74,34 @@ #ifndef PORTABLE_H #define PORTABLE_H -/* Include the macro file relevant to the port being used. */ +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. +Purely for reasons of backward compatibility the old method is still valid, but +to make it clear that new projects should not use it, support for the port +specific constants has been moved into the deprecated_definitions.h header +file. */ +#include "deprecated_definitions.h" -#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT - #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT - #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef GCC_MEGA_AVR - #include "../portable/GCC/ATMega323/portmacro.h" -#endif - -#ifdef IAR_MEGA_AVR - #include "../portable/IAR/ATMega323/portmacro.h" -#endif - -#ifdef MPLAB_PIC24_PORT - #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" -#endif - -#ifdef MPLAB_DSPIC_PORT - #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" -#endif - -#ifdef MPLAB_PIC18F_PORT - #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" -#endif - -#ifdef MPLAB_PIC32MX_PORT - #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" -#endif - -#ifdef _FEDPICC - #include "libFreeRTOS/Include/portmacro.h" -#endif - -#ifdef SDCC_CYGNAL - #include "../../Source/portable/SDCC/Cygnal/portmacro.h" -#endif - -#ifdef GCC_ARM7 - #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" -#endif - -#ifdef GCC_ARM7_ECLIPSE - #include "portmacro.h" -#endif - -#ifdef ROWLEY_LPC23xx - #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" -#endif - -#ifdef IAR_MSP430 - #include "..\..\Source\portable\IAR\MSP430\portmacro.h" -#endif - -#ifdef GCC_MSP430 - #include "../../Source/portable/GCC/MSP430F449/portmacro.h" -#endif - -#ifdef ROWLEY_MSP430 - #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" -#endif - -#ifdef ARM7_LPC21xx_KEIL_RVDS - #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" -#endif - -#ifdef SAM7_GCC - #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" -#endif - -#ifdef SAM7_IAR - #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" -#endif - -#ifdef SAM9XE_IAR - #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" -#endif - -#ifdef LPC2000_IAR - #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" -#endif - -#ifdef STR71X_IAR - #include "..\..\Source\portable\IAR\STR71x\portmacro.h" -#endif - -#ifdef STR75X_IAR - #include "..\..\Source\portable\IAR\STR75x\portmacro.h" -#endif - -#ifdef STR75X_GCC - #include "..\..\Source\portable\GCC\STR75x\portmacro.h" -#endif - -#ifdef STR91X_IAR - #include "..\..\Source\portable\IAR\STR91x\portmacro.h" -#endif - -#ifdef GCC_H8S - #include "../../Source/portable/GCC/H8S2329/portmacro.h" -#endif - -#ifdef GCC_AT91FR40008 - #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" -#endif - -#ifdef RVDS_ARMCM3_LM3S102 - #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" -#endif - -#ifdef GCC_ARMCM3_LM3S102 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" -#endif - -#ifdef GCC_ARMCM3 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" -#endif - -#ifdef IAR_ARM_CM3 - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" -#endif - -#ifdef IAR_ARMCM3_LM - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" -#endif - -#ifdef HCS12_CODE_WARRIOR - #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" -#endif - -#ifdef MICROBLAZE_GCC - #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" -#endif - -#ifdef TERN_EE - #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" -#endif - -#ifdef GCC_HCS12 - #include "../../Source/portable/GCC/HCS12/portmacro.h" -#endif - -#ifdef GCC_MCF5235 - #include "../../Source/portable/GCC/MCF5235/portmacro.h" -#endif - -#ifdef COLDFIRE_V2_GCC - #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" -#endif - -#ifdef COLDFIRE_V2_CODEWARRIOR - #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" -#endif - -#ifdef GCC_PPC405 - #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" -#endif - -#ifdef GCC_PPC440 - #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" -#endif - -#ifdef _16FX_SOFTUNE - #include "..\..\Source\portable\Softune\MB96340\portmacro.h" -#endif - -#ifdef BCC_INDUSTRIAL_PC_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef BCC_FLASH_LITE_186_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef __GNUC__ - #ifdef __AVR32_AVR32A__ - #include "portmacro.h" - #endif -#endif - -#ifdef __ICCAVR32__ - #ifdef __CORE__ - #if __CORE__ == __AVR32A__ - #include "portmacro.h" - #endif - #endif -#endif - -#ifdef __91467D - #include "portmacro.h" -#endif - -#ifdef __96340 - #include "portmacro.h" -#endif - - -#ifdef __IAR_V850ES_Fx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx3_L__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Hx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_78K0R_Kx3__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" -#endif - -#ifdef __IAR_78K0R_Kx3L__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" -#endif - -/* Catch all to ensure portmacro.h is included in the build. Newer demos -have the path as part of the project options, rather than as relative from -the project location. If portENTER_CRITICAL() has not been defined then -portmacro.h has not yet been included - as every portmacro.h provides a -portENTER_CRITICAL() definition. Check the demo application for your demo -to find the path to the correct portmacro.h file. */ +/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h +did not result in a portmacro.h header file being included - and it should be +included here. In this case the path to the correct portmacro.h header file +must be set in the compiler's include path. */ #ifndef portENTER_CRITICAL #include "portmacro.h" #endif +#if portBYTE_ALIGNMENT == 32 + #define portBYTE_ALIGNMENT_MASK ( 0x001f ) +#endif + +#if portBYTE_ALIGNMENT == 16 + #define portBYTE_ALIGNMENT_MASK ( 0x000f ) +#endif + #if portBYTE_ALIGNMENT == 8 #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) #endif @@ -355,11 +139,32 @@ extern "C" { * */ #if( portUSING_MPU_WRAPPERS == 1 ) - portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION; + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; #else - portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; #endif +/* Used by heap_5.c. */ +typedef struct HeapRegion +{ + uint8_t *pucStartAddress; + size_t xSizeInBytes; +} HeapRegion_t; + +/* + * Used to define multiple heap regions for use by heap_5.c. This function + * must be called before any calls to pvPortMalloc() - not creating a task, + * queue, semaphore, mutex, software timer, event group, etc. will result in + * pvPortMalloc being called. + * + * pxHeapRegions passes in an array of HeapRegion_t structures - each of which + * defines a region of memory that can be used as the heap. The array is + * terminated by a HeapRegions_t structure that has a size of 0. The region + * with the lowest start address must appear first in the array. + */ +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; + + /* * Map to the memory management routines required for the port. */ @@ -367,12 +172,13 @@ void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; void vPortFree( void *pv ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; +size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; /* * Setup the hardware ready for the scheduler to take control. This generally * sets up a tick interrupt and sets timers for the correct tick frequency. */ -portBASE_TYPE xPortStartScheduler( void ) PRIVILEGED_FUNCTION; +BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; /* * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so @@ -390,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, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; #endif #ifdef __cplusplus diff --git a/FreeRTOS/Source/include/projdefs.h b/FreeRTOS/Source/include/projdefs.h index e2531bc..0b63fd8 100644 --- a/FreeRTOS/Source/include/projdefs.h +++ b/FreeRTOS/Source/include/projdefs.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -65,23 +70,91 @@ #ifndef PROJDEFS_H #define PROJDEFS_H -/* Defines the prototype to which task functions must conform. */ -typedef void (*pdTASK_CODE)( void * ); +/* + * Defines the prototype to which task functions must conform. Defined in this + * file to ensure the type is known before portable.h is included. + */ +typedef void (*TaskFunction_t)( void * ); -#define pdFALSE ( ( portBASE_TYPE ) 0 ) -#define pdTRUE ( ( portBASE_TYPE ) 1 ) +/* 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 pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) -#define errQUEUE_EMPTY ( ( portBASE_TYPE ) 0 ) -#define errQUEUE_FULL ( ( portBASE_TYPE ) 0 ) +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) -/* Error definitions. */ +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) +#define errQUEUE_FULL ( ( BaseType_t ) 0 ) + +/* FreeRTOS error definitions. */ #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) -#define errNO_TASK_TO_RUN ( -2 ) #define errQUEUE_BLOCKED ( -4 ) #define errQUEUE_YIELD ( -5 ) +/* Macros used for basic data corruption checks. */ +#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES + #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 +#endif + +#if( configUSE_16_BIT_TICKS == 1 ) + #define pdINTEGRITY_CHECK_VALUE 0x5a5a +#else + #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL +#endif + +/* The following errno values are used by FreeRTOS+ components, not FreeRTOS +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 */ +#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ +#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ +#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ +#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ +#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ +#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ +#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ +#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ +#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ +#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ +#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ +#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ +#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ +#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ +#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ +#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ +#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ +#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ +#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ +#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ +#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ +#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ +#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ +#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ +#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ +#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ +#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ +#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ +#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ +#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ +#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ +#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ +#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ + +/* The following endian values are used by FreeRTOS+ components, not FreeRTOS +itself. */ +#define pdFREERTOS_LITTLE_ENDIAN 0 +#define pdFREERTOS_BIG_ENDIAN 1 + #endif /* PROJDEFS_H */ diff --git a/FreeRTOS/Source/include/queue.h b/FreeRTOS/Source/include/queue.h index 3968cff..30be360 100644 --- a/FreeRTOS/Source/include/queue.h +++ b/FreeRTOS/Source/include/queue.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -77,49 +82,61 @@ extern "C" { /** * Type by which queues are referenced. For example, a call to xQueueCreate() - * returns an xQueueHandle variable that can then be used as a parameter to + * returns an QueueHandle_t variable that can then be used as a parameter to * xQueueSend(), xQueueReceive(), etc. */ -typedef void * xQueueHandle; +typedef void * QueueHandle_t; /** * Type by which queue sets are referenced. For example, a call to * xQueueCreateSet() returns an xQueueSet variable that can then be used as a * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. */ -typedef void * xQueueSetHandle; +typedef void * QueueSetHandle_t; /** * Queue sets can contain both queues and semaphores, so the - * xQueueSetMemberHandle is defined as a type to be used where a parameter or - * return value can be either an xQueueHandle or an xSemaphoreHandle. + * QueueSetMemberHandle_t is defined as a type to be used where a parameter or + * return value can be either an QueueHandle_t or an SemaphoreHandle_t. */ -typedef void * xQueueSetMemberHandle; +typedef void * QueueSetMemberHandle_t; /* For internal use only. */ -#define queueSEND_TO_BACK ( ( portBASE_TYPE ) 0 ) -#define queueSEND_TO_FRONT ( ( portBASE_TYPE ) 1 ) -#define queueOVERWRITE ( ( portBASE_TYPE ) 2 ) +#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) +#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) +#define queueOVERWRITE ( ( BaseType_t ) 2 ) /* For internal use only. These definitions *must* match those in queue.c. */ -#define queueQUEUE_TYPE_BASE ( ( unsigned char ) 0U ) -#define queueQUEUE_TYPE_SET ( ( unsigned char ) 0U ) -#define queueQUEUE_TYPE_MUTEX ( ( unsigned char ) 1U ) -#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( unsigned char ) 2U ) -#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( unsigned char ) 3U ) -#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( unsigned char ) 4U ) +#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) /** * queue. h *
- xQueueHandle xQueueCreate(
-							  unsigned portBASE_TYPE uxQueueLength,
-							  unsigned portBASE_TYPE uxItemSize
+ QueueHandle_t xQueueCreate(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize
 						  );
  * 
* - * 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. * @@ -142,10 +159,10 @@ typedef void * xQueueSetMemberHandle; void vATask( void *pvParameters ) { - xQueueHandle xQueue1, xQueue2; + QueueHandle_t xQueue1, xQueue2; - // Create a queue capable of containing 10 unsigned long values. - xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); + // Create a queue capable of containing 10 uint32_t values. + xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); if( xQueue1 == 0 ) { // Queue was not created and must not be used. @@ -165,15 +182,103 @@ typedef void * xQueueSetMemberHandle; * \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 *
- portBASE_TYPE xQueueSendToToFront(
-								   xQueueHandle	xQueue,
-								   const void	*	pvItemToQueue,
-								   portTickType	xTicksToWait
+ 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 + *
+ BaseType_t xQueueSendToToFront(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
 							   );
  * 
* @@ -195,7 +300,7 @@ typedef void * xQueueSetMemberHandle; * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the * queue is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. + * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * @@ -207,15 +312,15 @@ typedef void * xQueueSetMemberHandle; char ucData[ 20 ]; } xMessage; - unsigned long ulVar = 10UL; + uint32_t ulVar = 10UL; void vATask( void *pvParameters ) { - xQueueHandle xQueue1, xQueue2; + QueueHandle_t xQueue1, xQueue2; struct AMessage *pxMessage; - // Create a queue capable of containing 10 unsigned long values. - xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); + // Create a queue capable of containing 10 uint32_t values. + xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); // Create a queue capable of containing 10 pointers to AMessage structures. // These should be passed by pointer as they contain a lot of data. @@ -225,9 +330,9 @@ typedef void * xQueueSetMemberHandle; if( xQueue1 != 0 ) { - // Send an unsigned long. Wait for 10 ticks for space to become + // Send an uint32_t. Wait for 10 ticks for space to become // available if necessary. - if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS ) + if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS ) { // Failed to post the message, even after 10 ticks. } @@ -238,7 +343,7 @@ typedef void * xQueueSetMemberHandle; // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 ); + xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 ); } // ... Rest of task code. @@ -252,10 +357,10 @@ typedef void * xQueueSetMemberHandle; /** * queue. h *
- portBASE_TYPE xQueueSendToBack(
-								   xQueueHandle	xQueue,
-								   const	void	*	pvItemToQueue,
-								   portTickType	xTicksToWait
+ BaseType_t xQueueSendToBack(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
 							   );
  * 
* @@ -277,7 +382,7 @@ typedef void * xQueueSetMemberHandle; * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the queue * is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. + * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * @@ -289,15 +394,15 @@ typedef void * xQueueSetMemberHandle; char ucData[ 20 ]; } xMessage; - unsigned long ulVar = 10UL; + uint32_t ulVar = 10UL; void vATask( void *pvParameters ) { - xQueueHandle xQueue1, xQueue2; + QueueHandle_t xQueue1, xQueue2; struct AMessage *pxMessage; - // Create a queue capable of containing 10 unsigned long values. - xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); + // Create a queue capable of containing 10 uint32_t values. + xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); // Create a queue capable of containing 10 pointers to AMessage structures. // These should be passed by pointer as they contain a lot of data. @@ -307,9 +412,9 @@ typedef void * xQueueSetMemberHandle; if( xQueue1 != 0 ) { - // Send an unsigned long. Wait for 10 ticks for space to become + // Send an uint32_t. Wait for 10 ticks for space to become // available if necessary. - if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS ) + if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS ) { // Failed to post the message, even after 10 ticks. } @@ -320,7 +425,7 @@ typedef void * xQueueSetMemberHandle; // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 ); + xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 ); } // ... Rest of task code. @@ -334,10 +439,10 @@ typedef void * xQueueSetMemberHandle; /** * queue. h *
- portBASE_TYPE xQueueSend(
-							  xQueueHandle xQueue,
+ BaseType_t xQueueSend(
+							  QueueHandle_t xQueue,
 							  const void * pvItemToQueue,
-							  portTickType xTicksToWait
+							  TickType_t xTicksToWait
 						 );
  * 
* @@ -361,7 +466,7 @@ typedef void * xQueueSetMemberHandle; * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the * queue is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. + * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. * @@ -373,15 +478,15 @@ typedef void * xQueueSetMemberHandle; char ucData[ 20 ]; } xMessage; - unsigned long ulVar = 10UL; + uint32_t ulVar = 10UL; void vATask( void *pvParameters ) { - xQueueHandle xQueue1, xQueue2; + QueueHandle_t xQueue1, xQueue2; struct AMessage *pxMessage; - // Create a queue capable of containing 10 unsigned long values. - xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); + // Create a queue capable of containing 10 uint32_t values. + xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); // Create a queue capable of containing 10 pointers to AMessage structures. // These should be passed by pointer as they contain a lot of data. @@ -391,9 +496,9 @@ typedef void * xQueueSetMemberHandle; if( xQueue1 != 0 ) { - // Send an unsigned long. Wait for 10 ticks for space to become + // Send an uint32_t. Wait for 10 ticks for space to become // available if necessary. - if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS ) + if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS ) { // Failed to post the message, even after 10 ticks. } @@ -404,7 +509,7 @@ typedef void * xQueueSetMemberHandle; // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 ); + xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 ); } // ... Rest of task code. @@ -418,8 +523,8 @@ typedef void * xQueueSetMemberHandle; /** * queue. h *
- portBASE_TYPE xQueueOverwrite(
-							  xQueueHandle xQueue,
+ BaseType_t xQueueOverwrite(
+							  QueueHandle_t xQueue,
 							  const void * pvItemToQueue
 						 );
  * 
@@ -450,14 +555,14 @@ typedef void * xQueueSetMemberHandle; void vFunction( void *pvParameters ) { - xQueueHandle xQueue; - unsigned long ulVarToSend, ulValReceived; + QueueHandle_t xQueue; + uint32_t ulVarToSend, ulValReceived; - // Create a queue to hold one unsigned long value. It is strongly + // Create a queue to hold one uint32_t value. It is strongly // recommended *not* to use xQueueOverwrite() on queues that can // contain more than one value, and doing so will trigger an assertion // if configASSERT() is defined. - xQueue = xQueueCreate( 1, sizeof( unsigned long ) ); + xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); // Write the value 10 to the queue using xQueueOverwrite(). ulVarToSend = 10; @@ -502,11 +607,11 @@ typedef void * xQueueSetMemberHandle; /** * queue. h *
- portBASE_TYPE xQueueGenericSend(
-									xQueueHandle xQueue,
+ BaseType_t xQueueGenericSend(
+									QueueHandle_t xQueue,
 									const void * pvItemToQueue,
-									portTickType xTicksToWait
-									portBASE_TYPE xCopyPosition
+									TickType_t xTicksToWait
+									BaseType_t xCopyPosition
 								);
  * 
* @@ -528,7 +633,7 @@ typedef void * xQueueSetMemberHandle; * waiting for space to become available on the queue, should it already * be full. The call will return immediately if this is set to 0 and the * queue is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. + * portTICK_PERIOD_MS should be used to convert to real time if this is required. * * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the * item at the back of the queue, or queueSEND_TO_FRONT to place the item @@ -544,15 +649,15 @@ typedef void * xQueueSetMemberHandle; char ucData[ 20 ]; } xMessage; - unsigned long ulVar = 10UL; + uint32_t ulVar = 10UL; void vATask( void *pvParameters ) { - xQueueHandle xQueue1, xQueue2; + QueueHandle_t xQueue1, xQueue2; struct AMessage *pxMessage; - // Create a queue capable of containing 10 unsigned long values. - xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) ); + // Create a queue capable of containing 10 uint32_t values. + xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); // Create a queue capable of containing 10 pointers to AMessage structures. // These should be passed by pointer as they contain a lot of data. @@ -562,9 +667,9 @@ typedef void * xQueueSetMemberHandle; if( xQueue1 != 0 ) { - // Send an unsigned long. Wait for 10 ticks for space to become + // Send an uint32_t. Wait for 10 ticks for space to become // available if necessary. - if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS ) + if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS ) { // Failed to post the message, even after 10 ticks. } @@ -575,7 +680,7 @@ typedef void * xQueueSetMemberHandle; // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK ); + xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK ); } // ... Rest of task code. @@ -584,15 +689,15 @@ typedef void * xQueueSetMemberHandle; * \defgroup xQueueSend xQueueSend * \ingroup QueueManagement */ -signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; /** * queue. h *
- portBASE_TYPE xQueuePeek(
-							 xQueueHandle xQueue,
+ BaseType_t xQueuePeek(
+							 QueueHandle_t xQueue,
 							 void *pvBuffer,
-							 portTickType xTicksToWait
+							 TickType_t xTicksToWait
 						 );
* * This is a macro that calls the xQueueGenericReceive() function. @@ -618,7 +723,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time * of the call. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. + * portTICK_PERIOD_MS should be used to convert to real time if this is required. * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue * is empty. * @@ -633,7 +738,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const char ucData[ 20 ]; } xMessage; - xQueueHandle xQueue; + QueueHandle_t xQueue; // Task to create a queue and post a value. void vATask( void *pvParameters ) @@ -653,7 +758,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 ); + xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); // ... Rest of task code. } @@ -667,7 +772,7 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const { // Peek a message on the created queue. Block for 10 ticks if a // message is not immediately available. - if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) ) + if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) ) { // pcRxedMessage now points to the struct AMessage variable posted // by vATask, but the item still remains on the queue. @@ -685,8 +790,8 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const /** * queue. h *
- portBASE_TYPE xQueuePeekFromISR(
-									xQueueHandle xQueue,
+ BaseType_t xQueuePeekFromISR(
+									QueueHandle_t xQueue,
 									void *pvBuffer,
 								);
* @@ -713,15 +818,15 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const * \defgroup xQueuePeekFromISR xQueuePeekFromISR * \ingroup QueueManagement */ -signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION; +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; /** * queue. h *
- portBASE_TYPE xQueueReceive(
-								 xQueueHandle xQueue,
+ BaseType_t xQueueReceive(
+								 QueueHandle_t xQueue,
 								 void *pvBuffer,
-								 portTickType xTicksToWait
+								 TickType_t xTicksToWait
 							);
* * This is a macro that calls the xQueueGenericReceive() function. @@ -745,7 +850,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const * waiting for an item to receive should the queue be empty at the time * of the call. xQueueReceive() will return immediately if xTicksToWait * is zero and the queue is empty. The time is defined in tick periods so the - * constant portTICK_RATE_MS should be used to convert to real time if this is + * constant portTICK_PERIOD_MS should be used to convert to real time if this is * required. * * @return pdTRUE if an item was successfully received from the queue, @@ -759,7 +864,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const char ucData[ 20 ]; } xMessage; - xQueueHandle xQueue; + QueueHandle_t xQueue; // Task to create a queue and post a value. void vATask( void *pvParameters ) @@ -779,7 +884,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 ); + xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); // ... Rest of task code. } @@ -793,7 +898,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const { // Receive a message on the created queue. Block for 10 ticks if a // message is not immediately available. - if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) ) + if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) ) { // pcRxedMessage now points to the struct AMessage variable posted // by vATask. @@ -812,11 +917,11 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const /** * queue. h *
- portBASE_TYPE xQueueGenericReceive(
-									   xQueueHandle	xQueue,
+ BaseType_t xQueueGenericReceive(
+									   QueueHandle_t	xQueue,
 									   void	*pvBuffer,
-									   portTickType	xTicksToWait
-									   portBASE_TYPE	xJustPeek
+									   TickType_t	xTicksToWait
+									   BaseType_t	xJustPeek
 									);
* * It is preferred that the macro xQueueReceive() be used rather than calling @@ -838,7 +943,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time * of the call. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. + * portTICK_PERIOD_MS should be used to convert to real time if this is required. * xQueueGenericReceive() will return immediately if the queue is empty and * xTicksToWait is 0. * @@ -858,7 +963,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const char ucData[ 20 ]; } xMessage; - xQueueHandle xQueue; + QueueHandle_t xQueue; // Task to create a queue and post a value. void vATask( void *pvParameters ) @@ -878,7 +983,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const // Send a pointer to a struct AMessage object. Don't block if the // queue is already full. pxMessage = & xMessage; - xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 ); + xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); // ... Rest of task code. } @@ -892,7 +997,7 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const { // Receive a message on the created queue. Block for 10 ticks if a // message is not immediately available. - if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) ) + if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) ) { // pcRxedMessage now points to the struct AMessage variable posted // by vATask. @@ -905,11 +1010,11 @@ signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const * \defgroup xQueueReceive xQueueReceive * \ingroup QueueManagement */ -signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION; /** * queue. h - *
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );
+ *
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
* * Return the number of messages stored in a queue. * @@ -920,11 +1025,28 @@ signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * con * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting * \ingroup QueueManagement */ -unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h - *
void vQueueDelete( xQueueHandle xQueue );
+ *
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * + * Return the number of free spaces available in a queue. This is equal to the + * number of items that can be sent to the queue before the queue becomes full + * if no items are removed. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of spaces available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
void vQueueDelete( QueueHandle_t xQueue );
* * Delete a queue - freeing all the memory allocated for storing of items * placed on the queue. @@ -934,15 +1056,15 @@ unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) PRIVI * \defgroup vQueueDelete vQueueDelete * \ingroup QueueManagement */ -void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** * queue. h *
- portBASE_TYPE xQueueSendToFrontFromISR(
-										 xQueueHandle xQueue,
+ BaseType_t xQueueSendToFrontFromISR(
+										 QueueHandle_t xQueue,
 										 const void *pvItemToQueue,
-										 portBASE_TYPE *pxHigherPriorityTaskWoken
+										 BaseType_t *pxHigherPriorityTaskWoken
 									  );
  
* @@ -977,7 +1099,7 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; void vBufferISR( void ) { char cIn; - portBASE_TYPE xHigherPrioritTaskWoken; + BaseType_t xHigherPrioritTaskWoken; // We have not woken a task at the start of the ISR. xHigherPriorityTaskWoken = pdFALSE; @@ -1010,10 +1132,10 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; /** * queue. h *
- portBASE_TYPE xQueueSendToBackFromISR(
-										 xQueueHandle xQueue,
+ BaseType_t xQueueSendToBackFromISR(
+										 QueueHandle_t xQueue,
 										 const void *pvItemToQueue,
-										 portBASE_TYPE *pxHigherPriorityTaskWoken
+										 BaseType_t *pxHigherPriorityTaskWoken
 									  );
  
* @@ -1048,7 +1170,7 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; void vBufferISR( void ) { char cIn; - portBASE_TYPE xHigherPriorityTaskWoken; + BaseType_t xHigherPriorityTaskWoken; // We have not woken a task at the start of the ISR. xHigherPriorityTaskWoken = pdFALSE; @@ -1080,10 +1202,10 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; /** * queue. h *
- portBASE_TYPE xQueueOverwriteFromISR(
-							  xQueueHandle xQueue,
+ BaseType_t xQueueOverwriteFromISR(
+							  QueueHandle_t xQueue,
 							  const void * pvItemToQueue,
-							  portBASE_TYPE *pxHigherPriorityTaskWoken
+							  BaseType_t *pxHigherPriorityTaskWoken
 						 );
  * 
* @@ -1118,22 +1240,22 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; * Example usage:
 
- xQueueHandle xQueue;
- 
+ QueueHandle_t xQueue;
+
  void vFunction( void *pvParameters )
  {
- 	// Create a queue to hold one unsigned long value.  It is strongly
+ 	// Create a queue to hold one uint32_t value.  It is strongly
 	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
 	// contain more than one value, and doing so will trigger an assertion
 	// if configASSERT() is defined.
-	xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
 }
 
 void vAnInterruptHandler( void )
 {
 // xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
-portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
-unsigned long ulVarToSend, ulValReceived;
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+uint32_t ulVarToSend, ulValReceived;
 
 	// Write the value 10 to the queue using xQueueOverwriteFromISR().
 	ulVarToSend = 10;
@@ -1148,7 +1270,7 @@ unsigned long ulVarToSend, ulValReceived;
 	// Reading from the queue will now return 100.
 
 	// ...
-	
+
 	if( xHigherPrioritytaskWoken == pdTRUE )
 	{
 		// Writing to the queue caused a task to unblock and the unblocked task
@@ -1167,10 +1289,10 @@ unsigned long ulVarToSend, ulValReceived;
 /**
  * queue. h
  * 
- portBASE_TYPE xQueueSendFromISR(
-									 xQueueHandle xQueue,
+ BaseType_t xQueueSendFromISR(
+									 QueueHandle_t xQueue,
 									 const void *pvItemToQueue,
-									 portBASE_TYPE *pxHigherPriorityTaskWoken
+									 BaseType_t *pxHigherPriorityTaskWoken
 								);
  
* @@ -1208,7 +1330,7 @@ unsigned long ulVarToSend, ulValReceived; void vBufferISR( void ) { char cIn; - portBASE_TYPE xHigherPriorityTaskWoken; + BaseType_t xHigherPriorityTaskWoken; // We have not woken a task at the start of the ISR. xHigherPriorityTaskWoken = pdFALSE; @@ -1228,7 +1350,7 @@ unsigned long ulVarToSend, ulValReceived; if( xHigherPriorityTaskWoken ) { // Actual macro used here is port specific. - taskYIELD_FROM_ISR (); + portYIELD_FROM_ISR (); } }
@@ -1241,17 +1363,18 @@ unsigned long ulVarToSend, ulValReceived; /** * queue. h *
- portBASE_TYPE xQueueGenericSendFromISR(
-										   xQueueHandle		xQueue,
+ BaseType_t xQueueGenericSendFromISR(
+										   QueueHandle_t		xQueue,
 										   const	void	*pvItemToQueue,
-										   portBASE_TYPE	*pxHigherPriorityTaskWoken,
-										   portBASE_TYPE	xCopyPosition
+										   BaseType_t	*pxHigherPriorityTaskWoken,
+										   BaseType_t	xCopyPosition
 									   );
  
* * It is preferred that the macros xQueueSendFromISR(), * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place - * of calling this function directly. + * of calling this function directly. xQueueGiveFromISR() is an + * equivalent for use by semaphores that don't actually copy any data. * * Post an item on a queue. It is safe to use this function from within an * interrupt service routine. @@ -1286,7 +1409,7 @@ unsigned long ulVarToSend, ulValReceived; void vBufferISR( void ) { char cIn; - portBASE_TYPE xHigherPriorityTaskWokenByPost; + BaseType_t xHigherPriorityTaskWokenByPost; // We have not woken a task at the start of the ISR. xHigherPriorityTaskWokenByPost = pdFALSE; @@ -1314,15 +1437,16 @@ unsigned long ulVarToSend, ulValReceived; * \defgroup xQueueSendFromISR xQueueSendFromISR * \ingroup QueueManagement */ -signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** * queue. h *
- portBASE_TYPE xQueueReceiveFromISR(
-									   xQueueHandle	xQueue,
+ BaseType_t xQueueReceiveFromISR(
+									   QueueHandle_t	xQueue,
 									   void	*pvBuffer,
-									   portBASE_TYPE *pxTaskWoken
+									   BaseType_t *pxTaskWoken
 								   );
  * 
* @@ -1346,13 +1470,13 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * * Example usage:
 
- xQueueHandle xQueue;
+ QueueHandle_t xQueue;
 
  // Function to create a queue and post some values.
  void vAFunction( void *pvParameters )
  {
  char cValueToPost;
- const portTickType xBlockTime = ( portTickType )0xff;
+ const TickType_t xTicksToWait = ( TickType_t )0xff;
 
 	// Create a queue capable of containing 10 characters.
 	xQueue = xQueueCreate( 10, sizeof( char ) );
@@ -1364,23 +1488,23 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
 	// ...
 
 	// Post some characters that will be used within an ISR.  If the queue
-	// is full then this task will block for xBlockTime ticks.
+	// is full then this task will block for xTicksToWait ticks.
 	cValueToPost = 'a';
-	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
 	cValueToPost = 'b';
-	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
 
 	// ... keep posting characters ... this task may block when the queue
 	// becomes full.
 
 	cValueToPost = 'c';
-	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
  }
 
  // ISR that outputs all the characters received on the queue.
  void vISR_Routine( void )
  {
- portBASE_TYPE xTaskWokenByReceive = pdFALSE;
+ BaseType_t xTaskWokenByReceive = pdFALSE;
  char cRxedChar;
 
 	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
@@ -1403,37 +1527,15 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void *
  * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
  * \ingroup QueueManagement
  */
-signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
 
 /*
  * Utilities to query queues that are safe to use from an ISR.  These utilities
  * should be used only from witin an ISR, or within a critical section.
  */
-signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
-signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
-unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle 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.
- */
-signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
-signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
-#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 )
+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
 
 /*
  * The functions defined above are for passing data to and from tasks.  The
@@ -1444,32 +1546,32 @@ signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const
  * should not be called directly from application code.  Instead use the macro
  * wrappers defined within croutine.h.
  */
-signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
-signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
-signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait );
-signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait );
+BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken );
+BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken );
+BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );
+BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );
 
 /*
  * For internal use only.  Use xSemaphoreCreateMutex(),
  * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
  * these functions directly.
  */
-xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION;
-xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
-void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION;
+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;
 
 /*
  * For internal use only.  Use xSemaphoreTakeMutexRecursive() or
  * xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
  */
-portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
-portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION;
 
 /*
- * Reset a queue back to its original empty state.  pdPASS is returned if the
- * queue is successfully reset.  pdFAIL is returned if the queue could not be
- * reset because there are tasks blocked on the queue waiting to either
- * receive from the queue or send to the queue.
+ * Reset a queue back to its original empty state.  The return value is now
+ * obsolete and is always set to pdPASS.
  */
 #define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE )
 
@@ -1491,10 +1593,12 @@ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTI
  * handles can also be passed in here.
  *
  * @param pcName The name to be associated with the handle.  This is the
- * name that the kernel aware debugger will display.
+ * name that the kernel aware debugger will display.  The queue registry only
+ * stores a pointer to the string - so the string must be persistent (global or
+ * preferably in ROM/Flash), not on the stack.
  */
-#if configQUEUE_REGISTRY_SIZE > 0
-	void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName ) PRIVILEGED_FUNCTION;
+#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
 
 /*
@@ -1507,15 +1611,42 @@ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTI
  *
  * @param xQueue The handle of the queue being removed from the registry.
  */
-#if configQUEUE_REGISTRY_SIZE > 0
-	void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+#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.
  */
-xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char 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
@@ -1565,7 +1696,7 @@ xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned
  * @return If the queue set is created successfully then a handle to the created
  * queue set is returned.  Otherwise NULL is returned.
  */
-xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRIVILEGED_FUNCTION;
+QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION;
 
 /*
  * Adds a queue or semaphore to a queue set that was previously created by a
@@ -1579,7 +1710,7 @@ xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRI
  * a call to xQueueSelectFromSet() has first returned a handle to that set member.
  *
  * @param xQueueOrSemaphore The handle of the queue or semaphore being added to
- * the queue set (cast to an xQueueSetMemberHandle type).
+ * the queue set (cast to an QueueSetMemberHandle_t type).
  *
  * @param xQueueSet The handle of the queue set to which the queue or semaphore
  * is being added.
@@ -1589,7 +1720,7 @@ xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRI
  * queue set because it is already a member of a different queue set then pdFAIL
  * is returned.
  */
-portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
 
 /*
  * Removes a queue or semaphore from a queue set.  A queue or semaphore can only
@@ -1599,7 +1730,7 @@ portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSet
  * function.
  *
  * @param xQueueOrSemaphore The handle of the queue or semaphore being removed
- * from the queue set (cast to an xQueueSetMemberHandle type).
+ * from the queue set (cast to an QueueSetMemberHandle_t type).
  *
  * @param xQueueSet The handle of the queue set in which the queue or semaphore
  * is included.
@@ -1608,7 +1739,7 @@ portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSet
  * then pdPASS is returned.  If the queue was not in the queue set, or the
  * queue (or semaphore) was not empty, then pdFAIL is returned.
  */
-portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
 
 /*
  * xQueueSelectFromSet() selects from the members of a queue set a queue or
@@ -1633,30 +1764,30 @@ portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQue
  *
  * @param xQueueSet The queue set on which the task will (potentially) block.
  *
- * @param xBlockTimeTicks The maximum time, in ticks, that the calling task will
+ * @param xTicksToWait The maximum time, in ticks, that the calling task will
  * remain in the Blocked state (with other tasks executing) to wait for a member
  * of the queue set to be ready for a successful queue read or semaphore take
  * operation.
  *
  * @return xQueueSelectFromSet() will return the handle of a queue (cast to
- * a xQueueSetMemberHandle type) contained in the queue set that contains data,
- * or the handle of a semaphore (cast to a xQueueSetMemberHandle type) contained
+ * a QueueSetMemberHandle_t type) contained in the queue set that contains data,
+ * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained
  * in the queue set that is available, or NULL if no such queue or semaphore
  * exists before before the specified block time expires.
  */
-xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION;
+QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
 
 /*
  * A version of xQueueSelectFromSet() that can be used from an ISR.
  */
-xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
+QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
 
 /* Not public API functions. */
-void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
-portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION;
-void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) PRIVILEGED_FUNCTION;
-unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
-unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
+void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION;
+UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
 
 
 #ifdef __cplusplus
diff --git a/FreeRTOS/Source/include/semphr.h b/FreeRTOS/Source/include/semphr.h
index 04957f5..a674b02 100644
--- a/FreeRTOS/Source/include/semphr.h
+++ b/FreeRTOS/Source/include/semphr.h
@@ -1,59 +1,64 @@
 /*
-    FreeRTOS V7.5.2 - Copyright (C) 2013 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.
 
-    ***************************************************************************
-     *                                                                       *
-     *    FreeRTOS provides completely free yet professionally developed,    *
-     *    robust, strictly quality controlled, supported, and cross          *
-     *    platform software that has become a de facto standard.             *
-     *                                                                       *
-     *    Help yourself get started quickly and support the FreeRTOS         *
-     *    project by purchasing a FreeRTOS tutorial book, reference          *
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *
-     *                                                                       *
-     *    Thank you!                                                         *
-     *                                                                       *
-    ***************************************************************************
-
     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.
+    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.
+    ***************************************************************************
+    >>!   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 from the following
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
     link: http://www.freertos.org/a00114.html
 
-    1 tab == 4 spaces!
-
     ***************************************************************************
      *                                                                       *
-     *    Having a problem?  Start by reading the FAQ "My application does   *
-     *    not run, what could be wrong?"                                     *
+     *    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.                               *
      *                                                                       *
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *
+     *    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 - Documentation, books, training, latest versions,
-    license and Real Time Engineers Ltd. contact details.
+    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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS
-    licenses offer ticketed support, indemnification and middleware.
+    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
@@ -71,16 +76,27 @@
 
 #include "queue.h"
 
-typedef xQueueHandle xSemaphoreHandle;
+typedef QueueHandle_t SemaphoreHandle_t;
 
-#define semBINARY_SEMAPHORE_QUEUE_LENGTH	( ( unsigned char ) 1U )
-#define semSEMAPHORE_QUEUE_ITEM_LENGTH		( ( unsigned char ) 0U )
-#define semGIVE_BLOCK_TIME					( ( portTickType ) 0U )
+#define semBINARY_SEMAPHORE_QUEUE_LENGTH	( ( uint8_t ) 1U )
+#define semSEMAPHORE_QUEUE_ITEM_LENGTH		( ( uint8_t ) 0U )
+#define semGIVE_BLOCK_TIME					( ( TickType_t ) 0U )
 
 
 /**
  * semphr. h
- * 
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
+ *
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 + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. * * Macro that implements a semaphore by using the existing queue mechanism. * The queue length is 1 as this is a binary semaphore. The data size is 0 @@ -94,11 +110,11 @@ typedef xQueueHandle xSemaphoreHandle; * semaphore does not use a priority inheritance mechanism. For an alternative * that does use priority inheritance see xSemaphoreCreateMutex(). * - * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. + * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. * * Example usage:
- xSemaphoreHandle xSemaphore;
+ SemaphoreHandle_t xSemaphore = NULL;
 
  void vATask( void * pvParameters )
  {
@@ -109,38 +125,160 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xSemaphore != NULL )
     {
         // The semaphore was created successfully.
-        // The semaphore can now be used.  
+        // The semaphore can now be used.
     }
  }
  
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ -#define vSemaphoreCreateBinary( xSemaphore ) \ - { \ - ( xSemaphore ) = xQueueGenericCreate( ( unsigned portBASE_TYPE ) 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 - *
xSemaphoreTake( 
- *                   xSemaphoreHandle xSemaphore, 
- *                   portTickType xBlockTime 
+ * 
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 + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * 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(). + * + * @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: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif + +/** + * semphr. h + *
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 + *
xSemaphoreTake(
+ *                   SemaphoreHandle_t xSemaphore,
+ *                   TickType_t xBlockTime
  *               )
* * 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 * the semaphore was created. * * @param xBlockTime The time in ticks to wait for the semaphore to become - * available. The macro portTICK_RATE_MS can be used to convert this to a + * available. The macro portTICK_PERIOD_MS can be used to convert this to a * real time. A block time of zero can be used to poll the semaphore. A block * time of portMAX_DELAY can be used to block indefinitely (provided * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). @@ -150,13 +288,13 @@ typedef xQueueHandle xSemaphoreHandle; * * Example usage:
- xSemaphoreHandle xSemaphore = NULL;
+ SemaphoreHandle_t xSemaphore = NULL;
 
  // A task that creates a semaphore.
  void vATask( void * pvParameters )
  {
     // Create the semaphore to guard a shared resource.
-    vSemaphoreCreateBinary( xSemaphore );
+    xSemaphore = xSemaphoreCreateBinary();
  }
 
  // A task that uses the semaphore.
@@ -167,15 +305,15 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xSemaphore != NULL )
     {
         // See if we can obtain the semaphore.  If the semaphore is not available
-        // wait 10 ticks to see if it becomes free.	
-        if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
         {
             // We were able to obtain the semaphore and can now access the
             // shared resource.
 
             // ...
 
-            // We have finished accessing the shared resource.  Release the 
+            // We have finished accessing the shared resource.  Release the
             // semaphore.
             xSemaphoreGive( xSemaphore );
         }
@@ -190,28 +328,28 @@ typedef xQueueHandle xSemaphoreHandle;
  * \defgroup xSemaphoreTake xSemaphoreTake
  * \ingroup Semaphores
  */
-#define xSemaphoreTake( xSemaphore, xBlockTime )		xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+#define xSemaphoreTake( xSemaphore, xBlockTime )		xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
 
 /**
  * semphr. h
- * xSemaphoreTakeRecursive( 
- *                          xSemaphoreHandle xMutex, 
- *                          portTickType xBlockTime 
+ * xSemaphoreTakeRecursive(
+ *                          SemaphoreHandle_t xMutex,
+ *                          TickType_t xBlockTime
  *                        )
  *
- * Macro to recursively obtain, or 'take', a mutex type semaphore.  
- * The mutex must have previously been created using a call to 
+ * Macro to recursively obtain, or 'take', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
  * xSemaphoreCreateRecursiveMutex();
- * 
+ *
  * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
  * macro to be available.
- * 
+ *
  * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
  *
- * 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 
+ * 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.
  *
@@ -219,17 +357,17 @@ typedef xQueueHandle xSemaphoreHandle;
  * handle returned by xSemaphoreCreateRecursiveMutex();
  *
  * @param xBlockTime The time in ticks to wait for the semaphore to become
- * available.  The macro portTICK_RATE_MS can be used to convert this to a
+ * available.  The macro portTICK_PERIOD_MS can be used to convert this to a
  * real time.  A block time of zero can be used to poll the semaphore.  If
  * the task already owns the semaphore then xSemaphoreTakeRecursive() will
- * return immediately no matter what the value of xBlockTime. 
+ * return immediately no matter what the value of xBlockTime.
  *
  * @return pdTRUE if the semaphore was obtained.  pdFALSE if xBlockTime
  * expired without the semaphore becoming available.
  *
  * Example usage:
  
- xSemaphoreHandle xMutex = NULL;
+ SemaphoreHandle_t xMutex = NULL;
 
  // A task that creates a mutex.
  void vATask( void * pvParameters )
@@ -246,22 +384,22 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xMutex != NULL )
     {
         // See if we can obtain the mutex.  If the mutex is not available
-        // wait 10 ticks to see if it becomes free.	
-        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
         {
             // We were able to obtain the mutex and can now access the
             // shared resource.
 
             // ...
-            // For some reason due to the nature of the code further calls to 
+            // For some reason due to the nature of the code further calls to
 			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
 			// code these would not be just sequential calls as this would make
 			// no sense.  Instead the calls are likely to be buried inside
 			// a more complex call structure.
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
 
-            // The mutex has now been 'taken' three times, so will not be 
+            // The mutex has now been 'taken' three times, so will not be
 			// available to another task until it has also been given back
 			// three times.  Again it is unlikely that real code would have
 			// these calls sequentially, but instead buried in a more complex
@@ -283,35 +421,22 @@ typedef xQueueHandle xSemaphoreHandle;
  * \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( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+#if( configUSE_RECURSIVE_MUTEXES == 1 )
+	#define xSemaphoreTakeRecursive( xMutex, xBlockTime )	xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
+#endif
 
 /**
  * semphr. h
- * 
xSemaphoreGive( xSemaphoreHandle xSemaphore )
+ *
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 * an alternative which can be used from an ISR. * - * This macro must also not be used on semaphores created using + * This macro must also not be used on semaphores created using * xSemaphoreCreateRecursiveMutex(). * * @param xSemaphore A handle to the semaphore being released. This is the @@ -319,17 +444,17 @@ typedef xQueueHandle xSemaphoreHandle; * * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. * Semaphores are implemented using queues. An error can occur if there is - * no space on the queue to post a message - indicating that the + * no space on the queue to post a message - indicating that the * semaphore was not first obtained correctly. * * Example usage:
- xSemaphoreHandle xSemaphore = NULL;
+ SemaphoreHandle_t xSemaphore = NULL;
 
  void vATask( void * pvParameters )
  {
     // Create the semaphore to guard a shared resource.
-    vSemaphoreCreateBinary( xSemaphore );
+    xSemaphore = vSemaphoreCreateBinary();
 
     if( xSemaphore != NULL )
     {
@@ -341,7 +466,7 @@ typedef xQueueHandle xSemaphoreHandle;
 
         // Obtain the semaphore - don't block if the semaphore is not
         // immediately available.
-        if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
         {
             // We now have the semaphore and can access the shared resource.
 
@@ -361,25 +486,25 @@ typedef xQueueHandle xSemaphoreHandle;
  * \defgroup xSemaphoreGive xSemaphoreGive
  * \ingroup Semaphores
  */
-#define xSemaphoreGive( xSemaphore )		xQueueGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+#define xSemaphoreGive( xSemaphore )		xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
 
 /**
  * semphr. h
- * 
xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )
+ *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
* * Macro to recursively release, or 'give', a mutex type semaphore. - * The mutex must have previously been created using a call to + * The mutex must have previously been created using a call to * xSemaphoreCreateRecursiveMutex(); - * + * * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this * macro to be available. * * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). - * - * 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 + * + * 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. * @@ -390,7 +515,7 @@ typedef xQueueHandle xSemaphoreHandle; * * Example usage:
- xSemaphoreHandle xMutex = NULL;
+ SemaphoreHandle_t xMutex = NULL;
 
  // A task that creates a mutex.
  void vATask( void * pvParameters )
@@ -407,22 +532,22 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xMutex != NULL )
     {
         // See if we can obtain the mutex.  If the mutex is not available
-        // wait 10 ticks to see if it becomes free.	
-        if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
         {
             // We were able to obtain the mutex and can now access the
             // shared resource.
 
             // ...
-            // For some reason due to the nature of the code further calls to 
+            // For some reason due to the nature of the code further calls to
 			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
 			// code these would not be just sequential calls as this would make
 			// no sense.  Instead the calls are likely to be buried inside
 			// a more complex call structure.
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
 
-            // The mutex has now been 'taken' three times, so will not be 
+            // The mutex has now been 'taken' three times, so will not be
 			// available to another task until it has also been given back
 			// three times.  Again it is unlikely that real code would have
 			// these calls sequentially, it would be more likely that the calls
@@ -445,32 +570,20 @@ typedef xQueueHandle xSemaphoreHandle;
  * \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( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+#if( configUSE_RECURSIVE_MUTEXES == 1 )
+	#define xSemaphoreGiveRecursive( xMutex )	xQueueGiveMutexRecursive( ( xMutex ) )
+#endif
 
 /**
  * semphr. h
  * 
- xSemaphoreGiveFromISR( 
-                          xSemaphoreHandle xSemaphore, 
-                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
+ xSemaphoreGiveFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
                       )
* * 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. @@ -492,14 +605,14 @@ typedef xQueueHandle xSemaphoreHandle;
  \#define LONG_TIME 0xffff
  \#define TICKS_TO_WAIT	10
- xSemaphoreHandle xSemaphore = NULL;
+ SemaphoreHandle_t xSemaphore = NULL;
 
  // Repetitive task.
  void vATask( void * pvParameters )
  {
     for( ;; )
     {
-        // We want this task to run every 10 ticks of a timer.  The semaphore 
+        // We want this task to run every 10 ticks of a timer.  The semaphore
         // was created before this task was started.
 
         // Block waiting for the semaphore to become available.
@@ -510,7 +623,7 @@ typedef xQueueHandle xSemaphoreHandle;
             // ...
 
             // We have finished our task.  Return to the top of the loop where
-            // we will block on the semaphore until it is time to execute 
+            // we will block on the semaphore until it is time to execute
             // again.  Note when using the semaphore for synchronisation with an
 			// ISR in this manner there is no need to 'give' the semaphore back.
         }
@@ -520,8 +633,8 @@ typedef xQueueHandle xSemaphoreHandle;
  // Timer ISR
  void vTimerISR( void * pvParameters )
  {
- static unsigned char ucLocalTickCount = 0;
- static signed portBASE_TYPE xHigherPriorityTaskWoken;
+ static uint8_t ucLocalTickCount = 0;
+ static BaseType_t xHigherPriorityTaskWoken;
 
     // A timer tick has occurred.
 
@@ -550,18 +663,18 @@ typedef xQueueHandle xSemaphoreHandle;
  * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
  * \ingroup Semaphores
  */
-#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )			xQueueGenericSendFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
+#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )	xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
 
 /**
  * semphr. h
  * 
- xSemaphoreTakeFromISR( 
-                          xSemaphoreHandle xSemaphore, 
-                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
+ xSemaphoreTakeFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
                       )
* - * Macro to take a semaphore from an ISR. The semaphore must have - * previously been created with a call to vSemaphoreCreateBinary() or + * Macro to take a semaphore from an ISR. The semaphore must have + * previously been created with a call to xSemaphoreCreateBinary() or * xSemaphoreCreateCounting(). * * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) @@ -581,39 +694,49 @@ typedef xQueueHandle xSemaphoreHandle; * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then * a context switch should be requested before the interrupt is exited. * - * @return pdTRUE if the semaphore was successfully taken, otherwise + * @return pdTRUE if the semaphore was successfully taken, otherwise * pdFALSE */ -#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) /** * semphr. h - *
xSemaphoreHandle xSemaphoreCreateMutex( void )
+ *
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() - * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and - * xSemaphoreGiveRecursive() macros should 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. + * 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. * - * Mutex type semaphores cannot be used from within interrupt service routines. + * Mutexes created using this function can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros must not be used. * - * See vSemaphoreCreateBinary() 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 + * 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. * - * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * xSemaphoreHandle. + * @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:
- xSemaphoreHandle xSemaphore;
+ SemaphoreHandle_t xSemaphore;
 
  void vATask( void * pvParameters )
  {
@@ -624,51 +747,125 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xSemaphore != NULL )
     {
         // The semaphore was created successfully.
-        // The semaphore can now be used.  
+        // The semaphore can now be used.
     }
  }
  
- * \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 - *
xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )
+ *
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. * - * Mutexes created using this macro can be accessed using the - * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The - * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * 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. * - * 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 + * 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. + * 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. * - * See vSemaphoreCreateBinary() 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 + * 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. * - * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * xSemaphoreHandle. + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. * * Example usage:
- xSemaphoreHandle xSemaphore;
+ SemaphoreHandle_t xSemaphore;
 
  void vATask( void * pvParameters )
  {
@@ -679,45 +876,135 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xSemaphore != NULL )
     {
         // The semaphore was created successfully.
-        // The semaphore can now be used.  
+        // The semaphore can now be used.
     }
  }
  
- * \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 - *
xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
+ *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
* - * Macro that creates a counting semaphore 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 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 )
+ * + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer can + * instead optionally provide the memory that will get used by the counting + * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting + * semaphore to be created without using any dynamic memory allocation. * * Counting semaphores are typically used for two things: * - * 1) Counting events. + * 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 + * 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 + * 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 + * @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 @@ -725,14 +1012,14 @@ typedef xQueueHandle xSemaphoreHandle; * * @return Handle to the created semaphore. Null if the semaphore could not be * created. - * + * * Example usage:
- xSemaphoreHandle xSemaphore;
+ SemaphoreHandle_t xSemaphore;
 
  void vATask( void * pvParameters )
  {
- xSemaphoreHandle xSemaphore = NULL;
+ SemaphoreHandle_t xSemaphore = NULL;
 
     // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
     // The max value to which the semaphore can count should be 10, and the
@@ -742,18 +1029,105 @@ typedef xQueueHandle xSemaphoreHandle;
     if( xSemaphore != NULL )
     {
         // The semaphore was created successfully.
-        // The semaphore can now be used.  
+        // The semaphore can now be used.
     }
  }
  
* \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 - *
void vSemaphoreDelete( xSemaphoreHandle xSemaphore );
+ *
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 + *
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
* * Delete a semaphore. This function must be used with care. For example, * do not delete a mutex type semaphore if the mutex is held by a task. @@ -763,23 +1137,35 @@ typedef xQueueHandle xSemaphoreHandle; * \defgroup vSemaphoreDelete vSemaphoreDelete * \ingroup Semaphores */ -#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) ( xSemaphore ) ) +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) /** * semphr.h - *
xTaskHandle xSemaphoreGetMutexHolder( xSemaphoreHandle xMutex );
+ *
TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
* * If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is not a mutex type semaphore, or the mutex is available (not held * by a task), return NULL. * - * Note: This Is is a good way of determining if the calling task is the mutex + * Note: This is a good way of determining if the calling task is the mutex * holder, but not a good way of determining the identity of the mutex holder as * the holder may change between the function exiting and the returned value * being tested. */ #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/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h index 9881084..d0643c0 100644 --- a/FreeRTOS/Source/include/task.h +++ b/FreeRTOS/Source/include/task.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -80,19 +85,28 @@ extern "C" { * MACROS AND DEFINITIONS *----------------------------------------------------------*/ -#define tskKERNEL_VERSION_NUMBER "V7.5.2" +#define tskKERNEL_VERSION_NUMBER "V9.0.0" +#define tskKERNEL_VERSION_MAJOR 9 +#define tskKERNEL_VERSION_MINOR 0 +#define tskKERNEL_VERSION_BUILD 0 /** * task. h * * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an xTaskHandle variable that can then + * returns (via a pointer parameter) an TaskHandle_t variable that can then * be used as a parameter to vTaskDelete to delete the task. * - * \defgroup xTaskHandle xTaskHandle + * \defgroup TaskHandle_t TaskHandle_t * \ingroup Tasks */ -typedef void * xTaskHandle; +typedef void * TaskHandle_t; + +/* + * Defines the prototype to which the application task hook function must + * conform. + */ +typedef BaseType_t (*TaskHookFunction_t)( void * ); /* Task states returned by eTaskGetState. */ typedef enum @@ -101,17 +115,28 @@ 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. */ +typedef enum +{ + eNoAction = 0, /* Notify the task without updating its notify value. */ + eSetBits, /* Set bits in the task's notification value. */ + eIncrement, /* Increment the task's notification value. */ + eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ + eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ +} eNotifyAction; + /* * Used internally only. */ typedef struct xTIME_OUT { - portBASE_TYPE xOverflowCount; - portTickType xTimeOnEntering; -} xTimeOutType; + BaseType_t xOverflowCount; + TickType_t xTimeOnEntering; +} TimeOut_t; /* * Defines the memory ranges allocated to the task when an MPU is used. @@ -119,37 +144,38 @@ typedef struct xTIME_OUT typedef struct xMEMORY_REGION { void *pvBaseAddress; - unsigned long ulLengthInBytes; - unsigned long ulParameters; -} xMemoryRegion; + uint32_t ulLengthInBytes; + uint32_t ulParameters; +} MemoryRegion_t; /* * Parameters required to create an MPU protected task. */ -typedef struct xTASK_PARAMTERS +typedef struct xTASK_PARAMETERS { - pdTASK_CODE pvTaskCode; - const signed char * const pcName; - unsigned short usStackDepth; + TaskFunction_t pvTaskCode; + const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + uint16_t usStackDepth; void *pvParameters; - unsigned portBASE_TYPE uxPriority; - portSTACK_TYPE *puxStackBuffer; - xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ]; -} xTaskParameters; + UBaseType_t uxPriority; + StackType_t *puxStackBuffer; + MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} TaskParameters_t; /* Used with the uxTaskGetSystemState() function to return the state of each task in the system. */ typedef struct xTASK_STATUS { - xTaskHandle xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ - const signed char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ - unsigned portBASE_TYPE xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ - unsigned portBASE_TYPE uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ - unsigned portBASE_TYPE 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. */ - unsigned long 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. */ - unsigned short 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. */ -} xTaskStatusType; + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */ + uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ +} TaskStatus_t; /* Possible return values for eTaskConfirmSleepModeStatus(). */ typedef enum @@ -159,13 +185,12 @@ 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. * * \ingroup TaskUtils */ -#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0U ) +#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) /** * task. h @@ -190,6 +215,7 @@ typedef enum * \ingroup SchedulerControl */ #define taskENTER_CRITICAL() portENTER_CRITICAL() +#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() /** * task. h @@ -204,7 +230,7 @@ typedef enum * \ingroup SchedulerControl */ #define taskEXIT_CRITICAL() portEXIT_CRITICAL() - +#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) /** * task. h * @@ -225,10 +251,13 @@ typedef enum */ #define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() -/* Definitions returned by xTaskGetSchedulerState(). */ -#define taskSCHEDULER_NOT_STARTED ( ( portBASE_TYPE ) 0 ) -#define taskSCHEDULER_RUNNING ( ( portBASE_TYPE ) 1 ) -#define taskSCHEDULER_SUSPENDED ( ( portBASE_TYPE ) 2 ) +/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is +0 to generate more optimal code when configASSERT() is defined as the constant +is used in assert() statements. */ +#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) +#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) +#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) + /*----------------------------------------------------------- * TASK CREATION API @@ -237,17 +266,30 @@ typedef enum /** * task. h *
- portBASE_TYPE xTaskCreate(
-							  pdTASK_CODE pvTaskCode,
+ BaseType_t xTaskCreate(
+							  TaskFunction_t pvTaskCode,
 							  const char * const pcName,
-							  unsigned short usStackDepth,
+							  uint16_t usStackDepth,
 							  void *pvParameters,
-							  unsigned portBASE_TYPE uxPriority,
-							  xTaskHandle *pvCreatedTask
+							  UBaseType_t uxPriority,
+							  TaskHandle_t *pvCreatedTask
 						  );
* * 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 @@ -257,7 +299,7 @@ typedef enum * 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. Max length defined by tskMAX_TASK_NAME_LEN - default + * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default * is 16. * * @param usStackDepth The size of the task stack specified as the number of @@ -278,7 +320,7 @@ typedef enum * can be referenced. * * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file errors. h + * list, otherwise an error code defined in the file projdefs.h * * Example usage:
@@ -294,28 +336,156 @@ typedef enum
  // Function that creates a task.
  void vOtherFunction( void )
  {
- static unsigned char ucParameterToPass;
- xTaskHandle xHandle;
+ static uint8_t ucParameterToPass;
+ TaskHandle_t xHandle = NULL;
 
 	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
 	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
 	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
 	 // the new task attempts to access it.
 	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+     configASSERT( xHandle );
 
 	 // Use the handle to delete the task.
-	 vTaskDelete( xHandle );
+     if( xHandle != NULL )
+     {
+	     vTaskDelete( xHandle );
+     }
  }
    
* \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 *
- portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );
+ 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 + *
+ BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
* * xTaskCreateRestricted() should only be used in systems that include an MPU * implementation. @@ -333,12 +503,12 @@ typedef enum * can be referenced. * * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file errors. h + * list, otherwise an error code defined in the file projdefs.h * * Example usage:
-// Create an xTaskParameters structure that defines the task to be created.
-static const xTaskParameters xCheckTaskParameters =
+// Create an TaskParameters_t structure that defines the task to be created.
+static const TaskParameters_t xCheckTaskParameters =
 {
 	vATask,		// pvTaskCode - the function that implements the task.
 	"ATask",	// pcName - just a text name for the task to assist debugging.
@@ -361,7 +531,7 @@ static const xTaskParameters xCheckTaskParameters =
 
 int main( void )
 {
-xTaskHandle xHandle;
+TaskHandle_t xHandle;
 
 	// Create a task from the const structure defined above.  The task handle
 	// is requested (the second parameter is not NULL) but in this case just for
@@ -372,19 +542,21 @@ xTaskHandle xHandle;
 	vTaskStartScheduler();
 
 	// Will only get here if there was insufficient memory to create the idle
-	// task.
+	// and/or timer task.
 	for( ;; );
 }
    
* \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 *
- void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );
+ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
* * Memory regions are assigned to a restricted task when the task is created by * a call to xTaskCreateRestricted(). These regions can be redefined using @@ -392,16 +564,16 @@ xTaskHandle xHandle; * * @param xTask The handle of the task being updated. * - * @param xRegions A pointer to an xMemoryRegion structure that contains the + * @param xRegions A pointer to an MemoryRegion_t structure that contains the * new memory region definitions. * * Example usage:
-// Define an array of xMemoryRegion structures that configures an MPU region
+// Define an array of MemoryRegion_t structures that configures an MPU region
 // allowing read/write access for 1024 bytes starting at the beginning of the
 // ucOneKByte array.  The other two of the maximum 3 definable regions are
 // unused so set to zero.
-static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
 {
 	// Base address		Length		Parameters
 	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
@@ -427,16 +599,16 @@ void vATask( void *pvParameters )
  * \defgroup xTaskCreateRestricted xTaskCreateRestricted
  * \ingroup Tasks
  */
-void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions ) PRIVILEGED_FUNCTION;
+void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION;
 
 /**
  * task. h
- * 
void vTaskDelete( xTaskHandle xTask );
+ *
void vTaskDelete( TaskHandle_t xTask );
* * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. * See the configuration section for more information. * - * Remove a task from the RTOS real time kernels management. The task being + * Remove a task from the RTOS real time kernel's management. The task being * deleted will be removed from all ready, blocked, suspended and event lists. * * NOTE: The idle task is responsible for freeing the kernel allocated @@ -456,7 +628,7 @@ void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxR
  void vOtherFunction( void )
  {
- xTaskHandle xHandle;
+ TaskHandle_t xHandle;
 
 	 // Create the task, storing the handle.
 	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@@ -468,7 +640,7 @@ void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxR
  * \defgroup vTaskDelete vTaskDelete
  * \ingroup Tasks
  */
-void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION;
+void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
 
 /*-----------------------------------------------------------
  * TASK CONTROL API
@@ -476,11 +648,11 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION;
 
 /**
  * task. h
- * 
void vTaskDelay( portTickType xTicksToDelay );
+ *
void vTaskDelay( const TickType_t xTicksToDelay );
* * Delay a task for a given number of ticks. The actual time that the * task remains blocked depends on the tick rate. The constant - * portTICK_RATE_MS can be used to calculate real time from the tick + * portTICK_PERIOD_MS can be used to calculate real time from the tick * rate - with the resolution of one tick period. * * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. @@ -491,7 +663,7 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION; * the time at which vTaskDelay() is called. For example, specifying a block * period of 100 ticks will cause the task to unblock 100 ticks after * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method - * of controlling the frequency of a cyclical task as the path taken through the + * of controlling the frequency of a periodic task as the path taken through the * code, as well as other task and interrupt activity, will effect the frequency * at which vTaskDelay() gets called and therefore the time at which the task * next executes. See vTaskDelayUntil() for an alternative API function designed @@ -504,12 +676,10 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION; * * Example usage: - void vTaskFunction( void * pvParameters ) - { void vTaskFunction( void * pvParameters ) { // Block for 500ms. - const portTickType xDelay = 500 / portTICK_RATE_MS; + const TickType_t xDelay = 500 / portTICK_PERIOD_MS; for( ;; ) { @@ -522,16 +692,16 @@ void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION; * \defgroup vTaskDelay vTaskDelay * \ingroup TaskCtrl */ -void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; +void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; /** * task. h - *
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
+ *
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
* * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. * See the configuration section for more information. * - * Delay a task until a specified time. This function can be used by cyclical + * Delay a task until a specified time. This function can be used by periodic * tasks to ensure a constant execution frequency. * * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will @@ -546,7 +716,7 @@ void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to * unblock. * - * The constant portTICK_RATE_MS can be used to calculate real time from the tick + * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick * rate - with the resolution of one tick period. * * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the @@ -564,8 +734,8 @@ void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; // Perform an action every 10 ticks. void vTaskFunction( void * pvParameters ) { - portTickType xLastWakeTime; - const portTickType xFrequency = 10; + TickType_t xLastWakeTime; + const TickType_t xFrequency = 10; // Initialise the xLastWakeTime variable with the current time. xLastWakeTime = xTaskGetTickCount (); @@ -581,13 +751,38 @@ void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; * \defgroup vTaskDelayUntil vTaskDelayUntil * \ingroup TaskCtrl */ -void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) PRIVILEGED_FUNCTION; +void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; /** * task. h - *
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask );
+ *
BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
* - * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available. + * 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 );
+ * + * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. * See the configuration section for more information. * * Obtain the priority of any task. @@ -601,7 +796,7 @@ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTim
  void vAFunction( void )
  {
- xTaskHandle xHandle;
+ TaskHandle_t xHandle;
 
 	 // Create a task, storing the handle.
 	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@@ -628,11 +823,19 @@ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTim
  * \defgroup uxTaskPriorityGet uxTaskPriorityGet
  * \ingroup TaskCtrl
  */
-unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
+UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
 
 /**
  * task. h
- * 
eTaskState eTaskGetState( xTaskHandle xTask );
+ *
UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask );
+ * + * A version of uxTaskPriorityGet() that can be used from an ISR. + */ +UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
eTaskState eTaskGetState( TaskHandle_t xTask );
* * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. * See the configuration section for more information. @@ -646,11 +849,67 @@ unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) PRIVILEGED_FUNCTIO * state of the task might change between the function being called, and the * functions return value being tested by the calling task. */ -eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION; +eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** * task. h - *
void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority );
+ *
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 );
* * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. * See the configuration section for more information. @@ -669,7 +928,7 @@ eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
  void vAFunction( void )
  {
- xTaskHandle xHandle;
+ TaskHandle_t xHandle;
 
 	 // Create a task, storing the handle.
 	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@@ -688,11 +947,11 @@ eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
  * \defgroup vTaskPrioritySet vTaskPrioritySet
  * \ingroup TaskCtrl
  */
-void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority ) PRIVILEGED_FUNCTION;
+void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
 
 /**
  * task. h
- * 
void vTaskSuspend( xTaskHandle xTaskToSuspend );
+ *
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
* * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. @@ -711,7 +970,7 @@ void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
  void vAFunction( void )
  {
- xTaskHandle xHandle;
+ TaskHandle_t xHandle;
 
 	 // Create a task, storing the handle.
 	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@@ -739,18 +998,18 @@ void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
  * \defgroup vTaskSuspend vTaskSuspend
  * \ingroup TaskCtrl
  */
-void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION;
+void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
 
 /**
  * task. h
- * 
void vTaskResume( xTaskHandle xTaskToResume );
+ *
void vTaskResume( TaskHandle_t xTaskToResume );
* * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. * * Resumes a suspended task. * - * A task that has been suspended by one of more calls to vTaskSuspend () + * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * vTaskResume (). * @@ -760,7 +1019,7 @@ void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION;
  void vAFunction( void )
  {
- xTaskHandle xHandle;
+ TaskHandle_t xHandle;
 
 	 // Create a task, storing the handle.
 	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
@@ -782,33 +1041,42 @@ void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION;
 	 vTaskResume( xHandle );
 
 	 // The created task will once again get microcontroller processing
-	 // time in accordance with it priority within the system.
+	 // time in accordance with its priority within the system.
  }
    
* \defgroup vTaskResume vTaskResume * \ingroup TaskCtrl */ -void vTaskResume( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION; +void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; /** * task. h - *
void xTaskResumeFromISR( xTaskHandle xTaskToResume );
+ *
void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
* * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be * available. See the configuration section for more information. * * An implementation of vTaskResume() that can be called from within an ISR. * - * A task that has been suspended by one of more calls to vTaskSuspend () + * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * xTaskResumeFromISR (). * + * xTaskResumeFromISR() should not be used to synchronise a task with an + * interrupt if there is a chance that the interrupt could arrive prior to the + * task being suspended - as this can lead to interrupts being missed. Use of a + * semaphore as a synchronisation mechanism would avoid this eventuality. + * * @param xTaskToResume Handle to the task being readied. * + * @return pdTRUE if resuming the task should result in a context switch, + * otherwise pdFALSE. This is used by the ISR to determine if a context switch + * may be required following the ISR. + * * \defgroup vTaskResumeFromISR vTaskResumeFromISR * \ingroup TaskCtrl */ -portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION; +BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; /*----------------------------------------------------------- * SCHEDULER CONTROL @@ -819,12 +1087,7 @@ portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTIO *
void vTaskStartScheduler( void );
* * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. This function - * does not return until an executing task calls vTaskEndScheduler (). - * - * At least one task should be created via a call to xTaskCreate () - * before calling vTaskStartScheduler (). The idle task is created - * automatically when the first application task is created. + * has control over which tasks are executed and when. * * See the demo application file main.c for an example of creating * tasks and starting the kernel. @@ -852,6 +1115,9 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; * task. h *
void vTaskEndScheduler( void );
* + * NOTE: At the time of writing only the x86 real mode port, which runs on a PC + * in place of DOS, implements this function. + * * Stops the real time kernel tick. All created tasks will be automatically * deleted and multitasking (either preemptive or cooperative) will * stop. Execution then resumes from the point where vTaskStartScheduler () @@ -905,8 +1171,8 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; * task. h *
void vTaskSuspendAll( void );
* - * Suspends all real time kernel activity while keeping interrupts (including the - * kernel tick) enabled. + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. * * After calling vTaskSuspendAll () the calling task will continue to execute * without risk of being swapped out until a call to xTaskResumeAll () has been @@ -954,11 +1220,13 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; /** * task. h - *
char xTaskResumeAll( void );
+ *
BaseType_t xTaskResumeAll( void );
* - * Resumes real time kernel activity following a call to vTaskSuspendAll (). - * After a call to vTaskSuspendAll () the kernel will take control of which - * task is executing at any time. + * Resumes scheduler activity after it was suspended by a call to + * vTaskSuspendAll(). + * + * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks + * that were previously suspended by a call to vTaskSuspend(). * * @return If resuming the scheduler caused a context switch then pdTRUE is * returned, otherwise pdFALSE is returned. @@ -1002,18 +1270,7 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; * \defgroup xTaskResumeAll xTaskResumeAll * \ingroup SchedulerControl */ -signed portBASE_TYPE xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
signed portBASE_TYPE xTaskIsTaskSuspended( const xTaskHandle xTask );
- * - * Utility task that simply returns pdTRUE if the task referenced by xTask is - * currently in the Suspended state, or pdFALSE if the task referenced by xTask - * is in any other state. - * - */ -signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTION; +BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; /*----------------------------------------------------------- * TASK UTILITIES @@ -1021,34 +1278,34 @@ signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTI /** * task. h - *
portTickType xTaskGetTickCount( void );
+ *
TickType_t xTaskGetTickCount( void );
* * @return The count of ticks since vTaskStartScheduler was called. * * \defgroup xTaskGetTickCount xTaskGetTickCount * \ingroup TaskUtils */ -portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; +TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; /** * task. h - *
portTickType xTaskGetTickCountFromISR( void );
+ *
TickType_t xTaskGetTickCountFromISR( void );
* * @return The count of ticks since vTaskStartScheduler was called. * * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that portTickType is the natural word size of the + * ISR - provided that TickType_t is the natural word size of the * microcontroller being used or interrupt nesting is either not supported or * not being used. * - * \defgroup xTaskGetTickCount xTaskGetTickCount + * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR * \ingroup TaskUtils */ -portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; +TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; /** * task. h - *
unsigned short uxTaskGetNumberOfTasks( void );
+ *
uint16_t uxTaskGetNumberOfTasks( void );
* * @return The number of tasks that the real time kernel is currently managing. * This includes all ready, blocked and suspended tasks. A task that @@ -1058,25 +1315,40 @@ portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks * \ingroup TaskUtils */ -unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; +UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; /** * task. h - *
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
+ *
char *pcTaskGetName( TaskHandle_t xTaskToQuery );
* * @return The text (human readable) name of the task referenced by the handle - * xTaskToQueury. 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. + * xTaskToQuery. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. * - * \defgroup pcTaskGetTaskName pcTaskGetTaskName + * \defgroup pcTaskGetName pcTaskGetName * \ingroup TaskUtils */ -signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ); +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 - *
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );
+ *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
* * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for * this function to be available. @@ -1089,13 +1361,14 @@ signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ); * @param xTask Handle of the task associated with the stack to be checked. * Set xTask to NULL to check the stack of the calling task. * - * @return The smallest amount of free stack space there has been (in bytes) - * since the task referenced by xTask was created. + * @return The smallest amount of free stack space there has been (in words, so + * actual spaces on the stack rather than bytes) since the task referenced by + * xTask was created. */ -unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) PRIVILEGED_FUNCTION; +UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -/* When using trace macros it is sometimes necessary to include tasks.h before -FreeRTOS.h. When this is done pdTASK_HOOK_CODE will not yet have been defined, +/* When using trace macros it is sometimes necessary to include task.h before +FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, so the following two prototypes will cause a compilation error. This can be fixed by simply guarding against the inclusion of these two prototypes unless they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration @@ -1104,35 +1377,48 @@ constant. */ #if configUSE_APPLICATION_TASK_TAG == 1 /** * task.h - *
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ *
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
* * Sets pxHookFunction to be the task hook function used by the task xTask. * Passing xTask as NULL has the effect of setting the calling tasks hook * function. */ - void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) PRIVILEGED_FUNCTION; + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; /** * task.h - *
void xTaskGetApplicationTaskTag( xTaskHandle xTask );
+ *
void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
* * Returns the pxHookFunction value assigned to the task xTask. */ - pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ #endif /* ifdef configUSE_APPLICATION_TASK_TAG */ +#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + + /* Each task contains an array of pointers that is dimensioned by the + configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The + kernel does not use the pointers itself, so the application writer can use + the pointers for any purpose they wish. The following two functions are + used to set and query a pointer respectively. */ + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION; + void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; + +#endif + /** * task.h - *
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ *
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
* * Calls the hook function associated with xTask. Passing xTask as NULL has * the effect of calling the Running tasks (the calling task) hook function. * * pvParameter is passed to the hook function for the task to interpret as it - * wants. + * wants. The return value is the value returned by the task hook function + * registered by the user. */ -portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) PRIVILEGED_FUNCTION; +BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION; /** * xTaskGetIdleTaskHandle() is only available if @@ -1141,29 +1427,29 @@ portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter * Simply returns the handle of the idle task. It is not valid to call * xTaskGetIdleTaskHandle() before the scheduler has been started. */ -xTaskHandle xTaskGetIdleTaskHandle( void ); +TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; /** - * configUSE_TRACE_FACILITY must bet defined as 1 in FreeRTOSConfig.h for + * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for * uxTaskGetSystemState() to be available. * - * uxTaskGetSystemState() populates an xTaskStatusType structure for each task in - * the system. xTaskStatusType structures contain, among other things, members + * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in + * the system. TaskStatus_t structures contain, among other things, members * for the task handle, task name, task priority, task state, and total amount - * of run time consumed by the task. See the xTaskStatusType structure + * of run time consumed by the task. See the TaskStatus_t structure * definition in this file for the full member list. * * NOTE: This function is intended for debugging use only as its use results in * the scheduler remaining suspended for an extended period. * - * @param pxTaskStatusArray A pointer to an array of xTaskStatusType structures. - * The array must contain at least one xTaskStatusType structure for each task - * that is under the control of the RTOS. The number of tasks under the control + * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. + * The array must contain at least one TaskStatus_t structure for each task + * that is under the control of the RTOS. The number of tasks under the control * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. * * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray * parameter. The size is specified as the number of indexes in the array, or - * the number of xTaskStatusType structures contained in the array, not by the + * the number of TaskStatus_t structures contained in the array, not by the * number of bytes in the array. * * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in @@ -1172,7 +1458,7 @@ xTaskHandle xTaskGetIdleTaskHandle( void ); * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. * pulTotalRunTime can be set to NULL to omit the total run time information. * - * @return The number of xTaskStatusType structures that were populated by + * @return The number of TaskStatus_t structures that were populated by * uxTaskGetSystemState(). This should equal the number returned by the * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed * in the uxArraySize parameter was too small. @@ -1182,22 +1468,22 @@ xTaskHandle xTaskGetIdleTaskHandle( void ); // This example demonstrates how a human readable table of run time stats // information is generated from raw data provided by uxTaskGetSystemState(). // The human readable table is written to pcWriteBuffer - void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) + void vTaskGetRunTimeStats( char *pcWriteBuffer ) { - xTaskStatusType *pxTaskStatusArray; - volatile unsigned portBASE_TYPE uxArraySize, x; - unsigned long ulTotalRunTime, ulStatsAsPercentage; + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + uint32_t ulTotalRunTime, ulStatsAsPercentage; // Make sure the write buffer does not contain a string. *pcWriteBuffer = 0x00; // Take a snapshot of the number of tasks in case it changes while this // function is executing. - uxArraySize = uxCurrentNumberOfTasks(); + uxArraySize = uxTaskGetNumberOfTasks(); - // Allocate a xTaskStatusType structure for each task. An array could be + // Allocate a TaskStatus_t structure for each task. An array could be // allocated statically at compile time. - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); + pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) ); if( pxTaskStatusArray != NULL ) { @@ -1221,13 +1507,13 @@ xTaskHandle xTaskGetIdleTaskHandle( void ); if( ulStatsAsPercentage > 0UL ) { - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); } else { // If the percentage is zero here then the task has // consumed less than 1% of the total run time. - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); + sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); } pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); @@ -1240,7 +1526,7 @@ xTaskHandle xTaskGetIdleTaskHandle( void ); }
*/ -unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime ); +UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; /** * task. h @@ -1280,14 +1566,14 @@ unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, * call to vTaskList(). * * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ascii form. This buffer is assumed to be large + * will be written, in ASCII form. This buffer is assumed to be large * enough to contain the generated report. Approximately 40 bytes per * task should be sufficient. * * \defgroup vTaskList vTaskList * \ingroup TaskUtils */ -void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; +void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * task. h @@ -1296,7 +1582,7 @@ void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS * must both be defined as 1 for this function to be available. The application * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() * to configure a peripheral timer/counter and return the timers current count * value respectively. The counter should be at least 10 times the frequency of * the tick count. @@ -1334,14 +1620,449 @@ void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; * vTaskGetRunTimeStats(). * * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ascii form. This buffer is assumed to be large enough to + * written, in ASCII form. This buffer is assumed to be large enough to * contain the generated report. Approximately 40 bytes per task should * be sufficient. * * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats * \ingroup TaskUtils */ -void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; +void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * pulPreviousNotificationValue - + * Can be used to pass out the subject task's notification value before any + * bits are modified by the notify function. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; +#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) +#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * A version of xTaskNotify() that can be used from an interrupt service routine + * (ISR). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the + * task to which the notification was sent to leave the Blocked state, and the + * unblocked task has a priority higher than the currently running task. If + * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should + * be requested before the interrupt is exited. How a context switch is + * requested from an ISR is dependent on the port - see the documentation page + * for the port in use. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value + * will be cleared in the calling task's notification value before the task + * checks to see if any notifications are pending, and optionally blocks if no + * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if + * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have + * the effect of resetting the task's notification value to 0. Setting + * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. + * + * @param ulBitsToClearOnExit If a notification is pending or received before + * the calling task exits the xTaskNotifyWait() function then the task's + * notification value (see the xTaskNotify() API function) is passed out using + * the pulNotificationValue parameter. Then any bits that are set in + * ulBitsToClearOnExit will be cleared in the task's notification value (note + * *pulNotificationValue is set before any bits are cleared). Setting + * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL + * (if limits.h is not included) will have the effect of resetting the task's + * notification value to 0 before the function exits. Setting + * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged + * when the function exits (in which case the value passed out in + * pulNotificationValue will match the task's notification value). + * + * @param pulNotificationValue Used to pass the task's notification value out + * of the function. Note the value passed out will not be effected by the + * clearing of any bits caused by ulBitsToClearOnExit being non-zero. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for a notification to be received, should a notification + * not already be pending when xTaskNotifyWait() was called. The task + * will not consume any processing time while it is in the Blocked state. This + * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be + * used to convert a time specified in milliseconds to a time specified in + * ticks. + * + * @return If a notification was received (including notifications that were + * already pending when xTaskNotifyWait was called) then pdPASS is + * returned. Otherwise pdFAIL is returned. + * + * \defgroup xTaskNotifyWait xTaskNotifyWait + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro + * to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * xTaskNotifyGive() is a helper macro intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. + * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, + * the equivalent action that instead uses a task notification is + * xTaskNotifyGive(). + * + * When task notifications are being used as a binary or counting semaphore + * equivalent then the task being notified should wait for the notification + * using the ulTaskNotificationTake() API function rather than the + * xTaskNotifyWait() API function. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the + * eAction parameter set to eIncrement - so pdPASS is always returned. + * + * \defgroup xTaskNotifyGive xTaskNotifyGive + * \ingroup TaskNotifications + */ +#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) + +/** + * task. h + *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
+ * to be available.
+ *
+ * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
+ * "notification value", which is a 32-bit unsigned integer (uint32_t).
+ *
+ * A version of xTaskNotifyGive() that can be called from an interrupt service
+ * routine (ISR).
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment the task's notification value.  In that way
+ * task notifications can be used to send data to a task, or be used as light
+ * weight and fast binary or counting semaphores.
+ *
+ * vTaskNotifyGiveFromISR() is intended for use when task notifications are
+ * used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given from an ISR using the
+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
+ * a task notification is vTaskNotifyGiveFromISR().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotificationTake() API function rather than the
+ * xTaskNotifyWait() API function.
+ *
+ * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param pxHigherPriorityTaskWoken  vTaskNotifyGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task.  If
+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
+ * should be requested before the interrupt is exited.  How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * \defgroup xTaskNotifyWait xTaskNotifyWait
+ * \ingroup TaskNotifications
+ */
+void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * 
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * ulTaskNotifyTake() is intended for use when a task notification is used as a + * faster and lighter weight binary or counting semaphore alternative. Actual + * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the + * equivalent action that instead uses a task notification is + * ulTaskNotifyTake(). + * + * When a task is using its notification value as a binary or counting semaphore + * other tasks should send notifications to it using the xTaskNotifyGive() + * macro, or xTaskNotify() function with the eAction parameter set to + * eIncrement. + * + * ulTaskNotifyTake() can either clear the task's notification value to + * zero on exit, in which case the notification value acts like a binary + * semaphore, or decrement the task's notification value on exit, in which case + * the notification value acts like a counting semaphore. + * + * A task can use ulTaskNotifyTake() to [optionally] block to wait for a + * the task's notification value to be non-zero. The task does not consume any + * CPU time while it is in the Blocked state. + * + * Where as xTaskNotifyWait() will return when a notification is pending, + * ulTaskNotifyTake() will return when the task's notification value is + * not zero. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's + * notification value is decremented when the function exits. In this way the + * notification value acts like a counting semaphore. If xClearCountOnExit is + * not pdFALSE then the task's notification value is cleared to zero when the + * function exits. In this way the notification value acts like a binary + * semaphore. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for the task's notification value to be greater than zero, + * should the count not already be greater than zero when + * ulTaskNotifyTake() was called. The task will not consume any processing + * time while it is in the Blocked state. This is specified in kernel ticks, + * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time + * specified in milliseconds to a time specified in ticks. + * + * @return The task's notification count before it is either cleared to zero or + * decremented (see the xClearCountOnExit parameter). + * + * \defgroup ulTaskNotifyTake ulTaskNotifyTake + * \ingroup TaskNotifications + */ +uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * + * If the notification state of the task referenced by the handle xTask is + * eNotified, then set the task's notification state to eNotWaitingNotification. + * The task's notification value is not altered. Set xTask to NULL to clear the + * notification state of the calling task. + * + * @return pdTRUE if the task's notification state was set to + * eNotWaitingNotification, otherwise pdFALSE. + * \defgroup xTaskNotifyStateClear xTaskNotifyStateClear + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); /*----------------------------------------------------------- * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES @@ -1362,7 +2083,7 @@ void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; * + Time slicing is in use and there is a task of equal priority to the * currently running task. */ -portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; +BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN @@ -1377,15 +2098,26 @@ portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; * there be no higher priority tasks waiting on the same event) or * the delay period expires. * + * The 'unordered' version replaces the event list item value with the + * xItemValue value, and inserts the list item at the end of the list. + * + * The 'ordered' version uses the existing event list item value (which is the + * owning tasks priority) to insert the list item into the event list is task + * priority order. + * * @param pxEventList The list containing tasks that are blocked waiting * for the event to occur. * + * @param xItemValue The item value to use for the event list item when the + * event list is not ordered by task priority. + * * @param xTicksToWait The maximum amount of time that the task should wait * for the event to occur. This is specified in kernel ticks,the constant - * portTICK_RATE_MS can be used to convert kernel ticks into a real time + * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time * period. */ -void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN @@ -1397,10 +2129,8 @@ void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait * The difference being that this function does not permit tasks to block * indefinitely, whereas vTaskPlaceOnEventList() does. * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. */ -void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) 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 @@ -1411,13 +2141,23 @@ void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xT * Removes a task from both the specified event list and the list of blocked * tasks, and places it on a ready queue. * - * xTaskRemoveFromEventList () will be called if either an event occurs to - * unblock a task, or the block timeout period expires. + * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called + * if either an event occurs to unblock a task, or the block timeout period + * expires. + * + * xTaskRemoveFromEventList() is used when the event list is in task priority + * order. It removes the list item from the head of the event list as that will + * have the highest priority owning task of all the tasks on the event list. + * xTaskRemoveFromUnorderedEventList() is used when the event list is not + * ordered and the event list items hold something other than the owning tasks + * priority. In this case the event list item value is updated to the value + * passed in the xItemValue parameter. * * @return pdTRUE if the task being removed has a higher priority than the task * making the call, otherwise pdFALSE. */ -signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION; +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY @@ -1429,21 +2169,27 @@ signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) */ void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; +/* + * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY + * THE EVENT BITS MODULE. + */ +TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; + /* * Return the handle of the calling task. */ -xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; +TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; /* * Capture the current time status for future reference. */ -void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) PRIVILEGED_FUNCTION; +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; /* * Compare the time status now with that previously captured to see if the * timeout has expired. */ -portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; /* * Shortcut used by the queue implementation to prevent unnecessary call to @@ -1455,47 +2201,43 @@ void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; * Returns the scheduler state as taskSCHEDULER_RUNNING, * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. */ -portBASE_TYPE xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; +BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; /* * Raises the priority of the mutex holder to that of the calling task should * the mutex holder have a priority less than the calling task. */ -void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION; +void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; /* * Set the priority of a task back to its proper priority in the case that it * inherited a higher priority while it was holding a semaphore. */ -void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION; - -/* - * Generic version of the task creation function which is in turn called by the - * xTaskCreate() and xTaskCreateRestricted() macros. - */ -signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION; +BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; /* * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. */ -unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ); +UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /* - * Set the uxTCBNumber of the task referenced by the xTask parameter to - * ucHandle. + * Set the uxTaskNumber of the task referenced by the xTask parameter to + * uxHandle. */ -void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ); +void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; /* + * Only available when configUSE_TICKLESS_IDLE is set to 1. * If tickless mode is being used, or a low power mode is implemented, then * the tick interrupt will not execute during idle periods. When this is the * case, the tick count value maintained by the scheduler needs to be kept up - * to date with the actual execution time by being skipped forward by the by - * a time equal to the idle period. + * to date with the actual execution time by being skipped forward by a time + * equal to the idle period. */ -void vTaskStepTick( portTickType xTicksToJump ); +void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; /* + * Only avilable when configUSE_TICKLESS_IDLE is set to 1. * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port * specific sleep function to determine if it is ok to proceed with the sleep, * and if it is ok to proceed, if it is ok to sleep indefinitely. @@ -1508,7 +2250,13 @@ void vTaskStepTick( portTickType xTicksToJump ); * critical section between the timer being stopped and the sleep mode being * entered to ensure it is ok to proceed into the sleep mode. */ -eSleepModeStatus eTaskConfirmSleepModeStatus( void ); +eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Increment the mutex held count when a mutex is + * taken and return the handle of the task that has taken the mutex. + */ +void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } diff --git a/FreeRTOS/Source/include/timers.h b/FreeRTOS/Source/include/timers.h index 04ad690..798c955 100644 --- a/FreeRTOS/Source/include/timers.h +++ b/FreeRTOS/Source/include/timers.h @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -73,65 +78,95 @@ /*lint -e537 This headers are only multiply included if the application code happens to also be including task.h. */ #include "task.h" -/*lint +e956 */ +/*lint +e537 */ #ifdef __cplusplus extern "C" { #endif -/* IDs for commands that can be sent/received on the timer queue. These are to -be used solely through the macros that make up the public software timer API, -as defined below. */ -#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 ) -#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 ) -#define tmrCOMMAND_CHANGE_PERIOD ( ( portBASE_TYPE ) 2 ) -#define tmrCOMMAND_DELETE ( ( portBASE_TYPE ) 3 ) - /*----------------------------------------------------------- * MACROS AND DEFINITIONS *----------------------------------------------------------*/ - /** +/* IDs for commands that can be sent/received on the timer queue. These are to +be used solely through the macros that make up the public software timer API, +as defined below. The commands that are sent from interrupts must use the +highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task +or interrupt version of the queue send function should be used. */ +#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) +#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) +#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) +#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) +#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) +#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) +#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) + +#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) +#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) +#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) + + +/** * Type by which software timers are referenced. For example, a call to - * xTimerCreate() returns an xTimerHandle variable that can then be used to + * xTimerCreate() returns an TimerHandle_t variable that can then be used to * reference the subject timer in calls to other software timer API functions * (for example, xTimerStart(), xTimerReset(), etc.). */ -typedef void * xTimerHandle; +typedef void * TimerHandle_t; -/* Define the prototype to which timer callback functions must conform. */ -typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); +/* + * Defines the prototype to which timer callback functions must conform. + */ +typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); + +/* + * Defines the prototype to which functions used with the + * xTimerPendFunctionCallFromISR() function must conform. + */ +typedef void (*PendedFunction_t)( void *, uint32_t ); /** - * xTimerHandle xTimerCreate( const signed char *pcTimerName, - * portTickType xTimerPeriodInTicks, - * unsigned portBASE_TYPE uxAutoReload, + * TimerHandle_t xTimerCreate( const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, * void * pvTimerID, - * tmrTIMER_CALLBACK pxCallbackFunction ); + * 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 - * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the - * active state. + * 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. + * 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_RATE_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_RATE_MS ) - * provided configTICK_RATE_HZ is less than or equal to 1000. + * @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 + * 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. @@ -140,38 +175,38 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); * timer. * * @param pxCallbackFunction The function to call when the timer expires. - * Callback functions must have the prototype defined by tmrTIMER_CALLBACK, - * which is "void vCallbackFunction( xTimerHandle xTimer );". + * Callback functions must have the prototype defined by TimerCallbackFunction_t, + * which is "void vCallbackFunction( TimerHandle_t xTimer );". * - * @return If the timer is successfully create then a handle to the newly + * @return If the timer is successfully created then a handle to the newly * created timer is returned. If the timer cannot be created (because either * there is insufficient FreeRTOS heap remaining to allocate the timer - * structures, or the timer period was set to 0) then 0 is returned. + * structures, or the timer period was set to 0) then NULL is returned. * * Example usage: * @verbatim * #define NUM_TIMERS 5 * * // An array to hold handles to the created timers. - * xTimerHandle xTimers[ NUM_TIMERS ]; + * TimerHandle_t xTimers[ NUM_TIMERS ]; * * // An array to hold a count of the number of times each timer expires. - * long lExpireCounters[ NUM_TIMERS ] = { 0 }; + * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 }; * * // Define a callback function that will be used by multiple timer instances. * // The callback function does nothing but count the number of times the * // associated timer expires, and stop the timer once the timer has expired * // 10 times. - * void vTimerCallback( xTimerHandle pxTimer ) + * void vTimerCallback( TimerHandle_t pxTimer ) * { - * long lArrayIndex; - * const long xMaxExpiryCountBeforeStopping = 10; + * int32_t lArrayIndex; + * const int32_t xMaxExpiryCountBeforeStopping = 10; * * // Optionally do something if the pxTimer parameter is NULL. * configASSERT( pxTimer ); - * + * * // Which timer expired? - * lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer ); + * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); * * // Increment the number of times that pxTimer has expired. * lExpireCounters[ lArrayIndex ] += 1; @@ -187,18 +222,18 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); * * void main( void ) * { - * long x; + * int32_t x; * * // Create then start some timers. Starting the timers before the scheduler * // has been started means the timers will start running immediately that * // the scheduler starts. * for( x = 0; x < NUM_TIMERS; x++ ) * { - * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. - * ( 100 * x ), // The timer period in ticks. - * pdTRUE, // The timers will auto-reload themselves when they expire. - * ( void * ) x, // Assign each timer a unique id equal to its array index. - * vTimerCallback // Each timer calls the same callback when it expires. + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * x ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. * ); * * if( xTimers[ x ] == NULL ) @@ -223,26 +258,163 @@ typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); * * // 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 */ -xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void * pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) PRIVILEGED_FUNCTION; +#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 /** - * void *pvTimerGetTimerID( xTimerHandle xTimer ); + * 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 ); * * Returns the ID assigned to the timer. * * IDs are assigned to timers using the pvTimerID parameter of the call to - * xTimerCreated() that was used to create the timer. + * xTimerCreated() that was used to create the timer, and by calling the + * vTimerSetTimerID() API function. * * If the same callback function is assigned to multiple timers then the timer - * ID can be used within the callback function to identify which timer actually - * expired. + * ID can be used as time specific (timer local) storage. * * @param xTimer The timer being queried. * @@ -252,16 +424,37 @@ xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType x * * See the xTimerCreate() API function example usage scenario. */ -void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; +void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** - * portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ); + * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); + * + * Sets the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used as time specific (timer local) storage. + * + * @param xTimer The timer being updated. + * + * @param pvNewID The ID to assign to the timer. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION; + +/** + * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); * * Queries a timer to see if it is active or dormant. * * A timer will be dormant if: * 1) It has been created but not started, or - * 2) It is an expired on-shot timer that has not been restarted. + * 2) It is an expired one-shot timer that has not been restarted. * * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and @@ -276,7 +469,7 @@ void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; * Example usage: * @verbatim * // This function assumes xTimer has already been created. - * void vAFunction( xTimerHandle xTimer ) + * void vAFunction( TimerHandle_t xTimer ) * { * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" * { @@ -289,23 +482,22 @@ void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; * } * @endverbatim */ -portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** - * xTimerGetTimerDaemonTaskHandle() is only available if - * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. + * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * Simply returns the handle of the timer service/daemon task. It it not valid * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. */ -xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); +TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; /** - * portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime ); + * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is + * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. @@ -330,14 +522,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being started/restarted. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the start command to be successfully * sent to the timer command queue, should the queue already be full when - * xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called + * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called * before the scheduler is started. * * @return pdFAIL will be returned if the start command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system, although the @@ -350,14 +542,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * See the xTimerCreate() API function example usage scenario. * */ -#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) +#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** - * portBASE_TYPE xTimerStop( xTimerHandle xTimer, portTickType xBlockTime ); + * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is + * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. @@ -373,14 +565,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being stopped. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the stop command to be successfully * sent to the timer command queue, should the queue already be full when - * xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called + * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called * before the scheduler is started. * * @return pdFAIL will be returned if the stop command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system. The timer @@ -392,16 +584,16 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * See the xTimerCreate() API function example usage scenario. * */ -#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) ) +#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) /** - * portBASE_TYPE xTimerChangePeriod( xTimerHandle xTimer, - * portTickType xNewPeriod, - * portTickType xBlockTime ); + * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is + * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. @@ -418,21 +610,21 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * @param xTimer The handle of the timer that is having its period changed. * * @param xNewPeriod The new period for xTimer. Timer periods are specified in - * tick periods, so the constant portTICK_RATE_MS can be used to convert a time + * 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 xNewPeriod should be set to 100. Alternatively, * if the timer must expire after 500ms, then xNewPeriod can be set to - * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than * or equal to 1000. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the change period command to be * successfully sent to the timer command queue, should the queue already be - * full when xTimerChangePeriod() was called. xBlockTime is ignored if + * full when xTimerChangePeriod() was called. xTicksToWait is ignored if * xTimerChangePeriod() is called before the scheduler is started. * * @return pdFAIL will be returned if the change period command could not be - * sent to the timer command queue even after xBlockTime ticks had passed. + * sent to the timer command queue even after xTicksToWait ticks had passed. * pdPASS will be returned if the command was successfully sent to the timer * command queue. When the command is actually processed will depend on the * priority of the timer service/daemon task relative to other tasks in the @@ -446,7 +638,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // is deleted. If the timer referenced by xTimer is not active when it is * // called, then the period of the timer is set to 500ms and the timer is * // started. - * void vAFunction( xTimerHandle xTimer ) + * void vAFunction( TimerHandle_t xTimer ) * { * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" * { @@ -459,7 +651,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // cause the timer to start. Block for a maximum of 100 ticks if the * // change period command cannot immediately be sent to the timer * // command queue. - * if( xTimerChangePeriod( xTimer, 500 / portTICK_RATE_MS, 100 ) == pdPASS ) + * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS ) * { * // The command was successfully sent. * } @@ -472,14 +664,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * } * @endverbatim */ - #define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) ) + #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) /** - * portBASE_TYPE xTimerDelete( xTimerHandle xTimer, portTickType xBlockTime ); + * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is + * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. @@ -492,14 +684,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being deleted. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the delete command to be * successfully sent to the timer command queue, should the queue already be - * full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete() + * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() * is called before the scheduler is started. * * @return pdFAIL will be returned if the delete command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system. The timer @@ -510,14 +702,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * See the xTimerChangePeriod() API function example usage scenario. */ -#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) ) +#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) /** - * portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType xBlockTime ); + * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is + * through a queue called the timer command queue. The timer command queue is * private to the kernel itself and is not directly accessible to application * code. The length of the timer command queue is set by the * configTIMER_QUEUE_LENGTH configuration constant. @@ -544,14 +736,14 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being reset/started/restarted. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the reset command to be successfully * sent to the timer command queue, should the queue already be full when - * xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called + * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called * before the scheduler is started. * * @return pdFAIL will be returned if the reset command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system, although the @@ -565,11 +757,11 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // without a key being pressed, then the LCD back-light is switched off. In * // this case, the timer is a one-shot timer. * - * xTimerHandle xBacklightTimer = NULL; + * TimerHandle_t xBacklightTimer = NULL; * * // The callback function assigned to the one-shot timer. In this case the * // parameter is not used. - * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) * { * // The timer expired, therefore 5 seconds must have passed since a key * // was pressed. Switch off the LCD back-light. @@ -595,12 +787,12 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * void main( void ) * { - * long x; + * int32_t x; * * // Create then start the one-shot timer that is responsible for turning * // the back-light off if no keys are pressed within a 5 second period. * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. - * ( 5000 / portTICK_RATE_MS), // The timer period in ticks. + * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks. * pdFALSE, // The timer is a one-shot timer. * 0, // The id is not used by the callback so can take any value. * vBacklightTimerCallback // The callback function that switches the LCD back-light off. @@ -627,18 +819,18 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * // 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( ;; ); * } * @endverbatim */ -#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) +#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** - * portBASE_TYPE xTimerStartFromISR( xTimerHandle xTimer, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerStart() that can be called from an interrupt service * routine. @@ -662,8 +854,9 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * successfully sent to the timer command queue. When the command is actually * processed will depend on the priority of the timer service/daemon task * relative to other tasks in the system, although the timers expiry time is - * relative to when xTimerStartFromISR() is actually called. The timer service/daemon - * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * relative to when xTimerStartFromISR() is actually called. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. * * Example usage: * @verbatim @@ -676,7 +869,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * // The callback function assigned to the one-shot timer. In this case the * // parameter is not used. - * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) * { * // The timer expired, therefore 5 seconds must have passed since a key * // was pressed. Switch off the LCD back-light. @@ -686,7 +879,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // The key press interrupt service routine. * void vKeyPressEventInterruptHandler( void ) * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // Ensure the LCD back-light is on, then restart the timer that is * // responsible for turning the back-light off after 5 seconds of @@ -714,16 +907,16 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. + * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ -#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) /** - * portBASE_TYPE xTimerStopFromISR( xTimerHandle xTimer, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerStop() that can be called from an interrupt service * routine. @@ -757,7 +950,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // The interrupt service routine that stops the timer. * void vAnExampleInterruptServiceRoutine( void ) * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // The interrupt has occurred - simply stop the timer. * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined @@ -777,17 +970,17 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. + * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ -#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0, ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) /** - * portBASE_TYPE xTimerChangePeriodFromISR( xTimerHandle xTimer, - * portTickType xNewPeriod, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerChangePeriod() that can be called from an interrupt * service routine. @@ -795,11 +988,11 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * @param xTimer The handle of the timer that is having its period changed. * * @param xNewPeriod The new period for xTimer. Timer periods are specified in - * tick periods, so the constant portTICK_RATE_MS can be used to convert a time + * 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 xNewPeriod should be set to 100. Alternatively, * if the timer must expire after 500ms, then xNewPeriod can be set to - * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than * or equal to 1000. * * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most @@ -830,7 +1023,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // The interrupt service routine that changes the period of xTimer. * void vAnExampleInterruptServiceRoutine( void ) * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // The interrupt has occurred - change the period of xTimer to 500ms. * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined @@ -850,16 +1043,16 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. + * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ -#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) /** - * portBASE_TYPE xTimerResetFromISR( xTimerHandle xTimer, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); * * A version of xTimerReset() that can be called from an interrupt service * routine. @@ -898,7 +1091,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * * // The callback function assigned to the one-shot timer. In this case the * // parameter is not used. - * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) * { * // The timer expired, therefore 5 seconds must have passed since a key * // was pressed. Switch off the LCD back-light. @@ -908,7 +1101,7 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * // The key press interrupt service routine. * void vKeyPressEventInterruptHandler( void ) * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * * // Ensure the LCD back-light is on, then reset the timer that is * // responsible for turning the back-light off after 5 seconds of @@ -936,19 +1129,181 @@ xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); * if( xHigherPriorityTaskWoken != pdFALSE ) * { * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. + * // depends on the FreeRTOS port being used). * } * } * @endverbatim */ -#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + + +/** + * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * + * Used from application interrupt service routines to defer the execution of a + * function to the RTOS daemon task (the timer service task, hence this function + * is implemented in timers.c and is prefixed with 'Timer'). + * + * Ideally an interrupt service routine (ISR) is kept as short as possible, but + * sometimes an ISR either has a lot of processing to do, or needs to perform + * processing that is not deterministic. In these cases + * xTimerPendFunctionCallFromISR() can be used to defer processing of a function + * to the RTOS daemon task. + * + * A mechanism is provided that allows the interrupt to return directly to the + * task that will subsequently execute the pended callback function. This + * allows the callback function to execute contiguously in time with the + * interrupt - just as if the callback had executed in the interrupt itself. + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task (which is set using + * configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of + * the currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE within + * xTimerPendFunctionCallFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + * Example usage: + * @verbatim + * + * // The callback function that will execute in the context of the daemon task. + * // Note callback functions must all use this same prototype. + * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) + * { + * BaseType_t xInterfaceToService; + * + * // The interface that requires servicing is passed in the second + * // parameter. The first parameter is not used in this case. + * xInterfaceToService = ( BaseType_t ) ulParameter2; + * + * // ...Perform the processing here... + * } + * + * // An ISR that receives data packets from multiple interfaces + * void vAnISR( void ) + * { + * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; + * + * // Query the hardware to determine which interface needs processing. + * xInterfaceToService = prvCheckInterfaces(); + * + * // The actual processing is to be deferred to a task. Request the + * // vProcessInterface() callback function is executed, passing in the + * // number of the interface that needs processing. The interface to + * // service is passed in the second parameter. The first parameter is + * // not used in this case. + * xHigherPriorityTaskWoken = pdFALSE; + * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); + * + * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context + * // switch should be requested. The macro used is port specific and will + * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to + * // the documentation page for the port being used. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * + * } + * @endverbatim + */ +BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + + /** + * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * TickType_t xTicksToWait ); + * + * + * Used to defer the execution of a function to the RTOS daemon task (the timer + * service task, hence this function is implemented in timers.c and is prefixed + * with 'Timer'). + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param xTicksToWait Calling this function will result in a message being + * sent to the timer daemon task on a queue. xTicksToWait is the amount of + * time the calling task should remain in the Blocked state (so not using any + * processing time) for space to become available on the timer queue if the + * queue is found to be full. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + */ +BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * const char * const pcTimerGetName( TimerHandle_t xTimer ); + * + * Returns the name that was assigned to a timer when the timer was created. + * + * @param xTimer The handle of the timer being queried. + * + * @return The name assigned to the timer specified by the xTimer parameter. + */ +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 * for use by the kernel only. */ -portBASE_TYPE xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; -portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) PRIVILEGED_FUNCTION; +BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } diff --git a/FreeRTOS/Source/list.c b/FreeRTOS/Source/list.c index f7e4a41..5e207c1 100644 --- a/FreeRTOS/Source/list.c +++ b/FreeRTOS/Source/list.c @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -71,12 +76,12 @@ * PUBLIC LIST API documented in list.h *----------------------------------------------------------*/ -void vListInitialise( xList * const pxList ) +void vListInitialise( List_t * const pxList ) { /* The list structure contains a list item which is used to mark the end of the list. To initialise the list the list end is inserted as the only list entry. */ - pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ /* The list end value is the highest possible value in the list to ensure it remains at the end of the list. */ @@ -84,31 +89,49 @@ void vListInitialise( xList * const pxList ) /* The list end next and previous pointers point to itself so we know when the list is empty. */ - pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U; + pxList->uxNumberOfItems = ( UBaseType_t ) 0U; + + /* Write known values into the list if + configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); + listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); } /*-----------------------------------------------------------*/ -void vListInitialiseItem( xListItem * const pxItem ) +void vListInitialiseItem( ListItem_t * const pxItem ) { /* Make sure the list item is not recorded as being on a list. */ pxItem->pvContainer = NULL; + + /* Write known values into the list item if + configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); + listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); } /*-----------------------------------------------------------*/ -void IRAM vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ) +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) { -xListItem * pxIndex; +ListItem_t * const pxIndex = pxList->pxIndex; + + /* Only effective when configASSERT() is also defined, these tests may catch + the list data structures being overwritten in memory. They will not catch + data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); /* Insert a new list item into pxList, but rather than sort the list, makes the new list item the last item to be removed by a call to - pvListGetOwnerOfNextEntry. */ - pxIndex = pxList->pxIndex; - + listGET_OWNER_OF_NEXT_ENTRY(). */ pxNewListItem->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious; + + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); + pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious = pxNewListItem; @@ -119,21 +142,25 @@ xListItem * pxIndex; } /*-----------------------------------------------------------*/ -void IRAM vListInsert( xList * const pxList, xListItem * const pxNewListItem ) +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) { -xListItem *pxIterator; -portTickType xValueOfInsertion; +ListItem_t *pxIterator; +const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; - /* Insert the new list item into the list, sorted in ulListItem order. */ - xValueOfInsertion = pxNewListItem->xItemValue; + /* Only effective when configASSERT() is also defined, these tests may catch + the list data structures being overwritten in memory. They will not catch + data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); - /* If the list already contains a list item with the same item value then - the new list item should be placed after it. This ensures that TCB's which - are stored in ready lists (all of which have the same ulListItem value) - get an equal share of the CPU. However, if the xItemValue is the same as - the back marker the iteration loop below will not end. This means we need - to guard against this by checking the value first and modifying the - algorithm slightly if necessary. */ + /* Insert the new list item into the list, sorted in xItemValue order. + + If the list already contains a list item with the same item value then the + new list item should be placed after it. This ensures that TCB's which are + stored in ready lists (all of which have the same xItemValue value) get a + share of the CPU. However, if the xItemValue is the same as the back marker + the iteration loop below will not end. Therefore the value is checked + first, and the algorithm slightly modified if necessary. */ if( xValueOfInsertion == portMAX_DELAY ) { pxIterator = pxList->xListEnd.pxPrevious; @@ -141,26 +168,31 @@ portTickType xValueOfInsertion; else { /* *** NOTE *********************************************************** - If you find your application is crashing here then likely causes are: + If you find your application is crashing here then likely causes are + listed below. In addition see http://www.freertos.org/FAQHelp.html for + more tips, and ensure configASSERT() is defined! + http://www.freertos.org/a00110.html#configASSERT + 1) Stack overflow - see http://www.freertos.org/Stacks-and-stack-overflow-checking.html - 2) Incorrect interrupt priority assignment, especially on Cortex-M3 + 2) Incorrect interrupt priority assignment, especially on Cortex-M parts where numerically high priority values denote low actual - interrupt priories, which can seem counter intuitive. See - configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html + interrupt priorities, which can seem counter intuitive. See + http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition + of configMAX_SYSCALL_INTERRUPT_PRIORITY on + http://www.freertos.org/a00110.html 3) Calling an API function from within a critical section or when the scheduler is suspended, or calling an API function that does not end in "FromISR" from an interrupt. 4) Using a queue or semaphore before it has been initialised or before the scheduler has been started (are interrupts firing before vTaskStartScheduler() has been called?). - See http://www.freertos.org/FAQHelp.html for more tips. **********************************************************************/ - for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ { - /* There is nothing to do here, we are just iterating to the - wanted insertion position. */ + /* There is nothing to do here, just iterating to the wanted + insertion position. */ } } @@ -177,22 +209,27 @@ portTickType xValueOfInsertion; } /*-----------------------------------------------------------*/ -unsigned portBASE_TYPE IRAM uxListRemove( xListItem * const pxItemToRemove ) +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { -xList * pxList; +/* The list item knows which list it is in. Obtain the list from the list +item. */ +List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; - /* The list item knows which list it is in. Obtain the list from the list - item. */ - pxList = ( xList * ) pxItemToRemove->pvContainer; + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); /* Make sure the index is left pointing to a valid item. */ if( pxList->pxIndex == pxItemToRemove ) { pxList->pxIndex = pxItemToRemove->pxPrevious; } + else + { + mtCOVERAGE_TEST_MARKER(); + } pxItemToRemove->pvContainer = NULL; ( pxList->uxNumberOfItems )--; diff --git a/FreeRTOS/Source/portable/esp8266/port.c b/FreeRTOS/Source/portable/esp8266/port.c index 1167aaf..a1e21f5 100644 --- a/FreeRTOS/Source/portable/esp8266/port.c +++ b/FreeRTOS/Source/portable/esp8266/port.c @@ -258,3 +258,11 @@ void IRAM vPortExitCritical( void ) portENABLE_INTERRUPTS(); } +/* back compatibility */ +signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) +{ + (void)puxStackBuffer; (void)xRegions; + return xTaskCreate( pxTaskCode, (const char * const)pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); +} + + diff --git a/FreeRTOS/Source/portable/esp8266/portmacro.h b/FreeRTOS/Source/portable/esp8266/portmacro.h index 3345ab5..645f5c4 100644 --- a/FreeRTOS/Source/portable/esp8266/portmacro.h +++ b/FreeRTOS/Source/portable/esp8266/portmacro.h @@ -94,13 +94,19 @@ extern "C" { #define portSHORT short #define portSTACK_TYPE unsigned portLONG #define portBASE_TYPE long +#define portPOINTER_SIZE_TYPE unsigned portLONG + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; typedef uint32_t portTickType; +typedef uint32_t TickType_t; #define portMAX_DELAY ( portTickType ) 0xffffffff /* Architecture specifics. */ #define portSTACK_GROWTH ( -1 ) -#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portTICK_PERIOD_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portBYTE_ALIGNMENT 8 /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c index 57fcf96..ce623be 100644 --- a/FreeRTOS/Source/queue.c +++ b/FreeRTOS/Source/queue.c @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -85,13 +90,13 @@ privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ -/* Constants used with the cRxLock and xTxLock structure members. */ -#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 ) -#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 ) +/* Constants used with the cRxLock and cTxLock structure members. */ +#define queueUNLOCKED ( ( int8_t ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) -/* When the xQUEUE structure is used to represent a base queue its pcHead and +/* 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 -xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are +Queue_t structure is used to represent a mutex pcHead and pcTail pointers are not necessary, and the pcHead pointer is set to NULL to indicate that the pcTail pointer actually points to the mutex holder (if any). Map alternative names to the pcHead and pcTail structure members to ensure the readability of @@ -106,47 +111,63 @@ structure member). */ /* Semaphores do not actually store or copy data, so have an item size of zero. */ -#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 ) -#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U ) +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) +#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. */ + #define queueYIELD_IF_USING_PREEMPTION() +#else + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() +#endif /* * Definition of the queue used by the scheduler. - * Items are queued by copy, not reference. + * Items are queued by copy, not reference. See the following link for the + * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html */ typedef struct QueueDefinition { - signed char *pcHead; /*< Points to the beginning of the queue storage area. */ - signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ + int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ - signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ - - union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ + union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ { - signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ - unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ } u; - xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ - xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ - volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ - unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ - unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ + volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ + 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 signed portBASE_TYPE 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 signed portBASE_TYPE 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 ) - unsigned char ucQueueNumber; - unsigned char 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 +name below to enable the use of older kernel aware debuggers. */ +typedef xQUEUE Queue_t; + /*-----------------------------------------------------------*/ /* @@ -160,14 +181,19 @@ typedef struct QueueDefinition more user friendly. */ typedef struct QUEUE_REGISTRY_ITEM { - signed char *pcQueueName; - xQueueHandle xHandle; + const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + QueueHandle_t xHandle; } xQueueRegistryItem; - /* The queue registry is simply an array of xQueueRegistryItem structures. + /* The old xQueueRegistryItem name is maintained above then typedefed to the + new xQueueRegistryItem name below to enable the use of older kernel aware + debuggers. */ + typedef xQueueRegistryItem QueueRegistryItem_t; + + /* The queue registry is simply an array of QueueRegistryItem_t structures. The pcQueueName member of a structure being NULL is indicative of the array position being vacant. */ - xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; #endif /* configQUEUE_REGISTRY_SIZE */ @@ -179,39 +205,54 @@ typedef struct QueueDefinition * to indicate that a task may require unblocking. When the queue in unlocked * these lock counts are inspected, and the appropriate action taken. */ -static void IRAM prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; +static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; /* * Uses a critical section to determine if there is any data in a queue. * * @return pdTRUE if the queue contains no items, otherwise pdFALSE. */ -static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; /* * Uses a critical section to determine if there is any space in a queue. * * @return pdTRUE if there is no space, otherwise pdFALSE; */ -static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; /* * Copies an item into the queue, either at the front of the queue or the * back of the queue. */ -static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION; +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; /* * Copies an item out of a queue. */ -static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION; +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; #if ( configUSE_QUEUE_SETS == 1 ) /* * Checks to see if a queue is a member of a queue set, and if so, notifies * the queue set that the queue contains data. */ - static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; + 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 /*-----------------------------------------------------------*/ @@ -223,45 +264,54 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvB #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() /*-----------------------------------------------------------*/ -portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) + +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) { -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); taskENTER_CRITICAL(); { pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); - pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; pxQueue->pcWriteTo = pxQueue->pcHead; - pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize ); - pxQueue->xRxLock = queueUNLOCKED; - pxQueue->xTxLock = queueUNLOCKED; + pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize ); + pxQueue->cRxLock = queueUNLOCKED; + pxQueue->cTxLock = queueUNLOCKED; if( xNewQueue == pdFALSE ) { /* If there are tasks blocked waiting to read from the queue, then the tasks will remain blocked as after this function exits the queue - will still be empty. If there are tasks blocked waiting to write to + will still be empty. If there are tasks blocked waiting to write to the queue, then one should be unblocked as after this function exits 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 ) { - portYIELD_WITHIN_API(); + queueYIELD_IF_USING_PREEMPTION(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else @@ -279,122 +329,208 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } /*-----------------------------------------------------------*/ -xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) -{ -xQUEUE *pxNewQueue; -size_t xQueueSizeInBytes; -xQueueHandle 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; - /* Allocate the new queue structure. */ - if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) + if( uxItemSize == ( UBaseType_t ) 0 ) { - pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); - if( pxNewQueue != NULL ) - { - /* Create the list of pointers to queue items. 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. */ - - pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes ); - if( pxNewQueue->pcHead != NULL ) - { - /* 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; - } - else - { - traceQUEUE_CREATE_FAILED( ucQueueType ); - vPortFree( pxNewQueue ); - } - } + /* 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 + { + /* Set the head to the start of the queue storage area. */ + pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; } - configASSERT( xReturn ); + /* Initialise the queue members as described where the queue type is + defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); - return xReturn; + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ + + #if( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ + + traceQUEUE_CREATE( pxNewQueue ); } /*-----------------------------------------------------------*/ -#if ( configUSE_MUTEXES == 1 ) - xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) +#if( configUSE_MUTEXES == 1 ) + + static void prvInitialiseMutex( Queue_t *pxNewQueue ) { - xQUEUE *pxNewQueue; - - /* Prevent compiler warnings about unused parameters if - configUSE_TRACE_FACILITY does not equal 1. */ - ( void ) ucQueueType; - - /* Allocate the new queue structure. */ - pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); 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 = ( unsigned portBASE_TYPE ) 0U; - pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U; - pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 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 ); /* Start with the semaphore in the expected state. */ - ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK ); + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); } else { 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 ); - configASSERT( pxNewQueue ); return pxNewQueue; } @@ -402,20 +538,21 @@ xQueueHandle xReturn = NULL; /*-----------------------------------------------------------*/ #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) - void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) + + void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) { void *pxReturn; /* This function is called by xSemaphoreGetMutexHolder(), and should not - be called directly. Note: This is is a good way of determining if the + be called directly. Note: This is a good way of determining if the calling task is the mutex holder, but not a good way of determining the identity of the mutex holder, as the holder may change between the following critical section exiting and the function returning. */ taskENTER_CRITICAL(); { - if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) { - pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder; + pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder; } else { @@ -425,16 +562,17 @@ xQueueHandle xReturn = NULL; taskEXIT_CRITICAL(); return pxReturn; - } + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ #endif /*-----------------------------------------------------------*/ #if ( configUSE_RECURSIVE_MUTEXES == 1 ) - portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) + + BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) { - portBASE_TYPE xReturn; - xQUEUE * const pxMutex = ( xQUEUE * ) xMutex; + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; configASSERT( pxMutex ); @@ -444,7 +582,7 @@ xQueueHandle xReturn = NULL; this is the only condition we are interested in it does not matter if pxMutexHolder is accessed simultaneously by another task. Therefore no mutual exclusion is required to test the pxMutexHolder variable. */ - if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */ + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */ { traceGIVE_MUTEX_RECURSIVE( pxMutex ); @@ -455,19 +593,24 @@ xQueueHandle xReturn = NULL; uxRecursiveCallCount member. */ ( pxMutex->u.uxRecursiveCallCount )--; - /* Have we unwound the call count? */ - if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 ) + /* Has the recursive call count unwound to 0? */ + if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 ) { /* Return the mutex. This will automatically unblock any other task that might be waiting to access the mutex. */ ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } xReturn = pdPASS; } else { - /* We cannot give the mutex because we are not the holder. */ + /* The mutex cannot be given because the calling task is not the + holder. */ xReturn = pdFAIL; traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); @@ -480,10 +623,11 @@ xQueueHandle xReturn = NULL; /*-----------------------------------------------------------*/ #if ( configUSE_RECURSIVE_MUTEXES == 1 ) - portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) + + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) { - portBASE_TYPE xReturn; - xQUEUE * const pxMutex = ( xQUEUE * ) xMutex; + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; configASSERT( pxMutex ); @@ -492,18 +636,19 @@ xQueueHandle xReturn = NULL; traceTAKE_MUTEX_RECURSIVE( pxMutex ); - if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */ + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ { ( pxMutex->u.uxRecursiveCallCount )++; xReturn = pdPASS; } else { - xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); + xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); - /* pdPASS will only be returned if we successfully obtained the mutex, - we may have blocked to reach here. */ - if( xReturn == pdPASS ) + /* 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 != pdFAIL ) { ( pxMutex->u.uxRecursiveCallCount )++; } @@ -519,16 +664,20 @@ xQueueHandle xReturn = NULL; #endif /* configUSE_RECURSIVE_MUTEXES */ /*-----------------------------------------------------------*/ -#if ( configUSE_COUNTING_SEMAPHORES == 1 ) - xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) - { - xQueueHandle xHandle; +#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - xHandle = xQueueGenericCreate( uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + 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 ) { - ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount; + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; traceCREATE_COUNTING_SEMAPHORE(); } @@ -537,21 +686,55 @@ xQueueHandle xReturn = NULL; traceCREATE_COUNTING_SEMAPHORE_FAILED(); } - configASSERT( xHandle ); return xHandle; } -#endif /* configUSE_COUNTING_SEMAPHORES */ +#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ /*-----------------------------------------------------------*/ -signed portBASE_TYPE IRAM xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) + +#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, 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 ) ) */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) { -signed portBASE_TYPE xEntryTimeSet = pdFALSE; -xTimeOutType xTimeOut; -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + /* This function relaxes the coding standard somewhat to allow return statements within the function itself. This is done in the interest @@ -560,25 +743,29 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { taskENTER_CRITICAL(); { - /* Is there room on the queue now? The running task must be - the highest priority task wanting to access the queue. If - the head item in the queue is to be overwritten then it does - not matter if the queue is full. */ + /* Is there room on the queue now? The running task must be the + highest priority task wanting to access the queue. If the head item + in the queue is to be overwritten then it does not matter if the + queue is full. */ if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { traceQUEUE_SEND( pxQueue ); - prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); #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 unblock. A context switch is required. */ - portYIELD_WITHIN_API(); + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else @@ -587,14 +774,30 @@ xQUEUE * const pxQueue = ( xQUEUE * ) 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 this from within the critical section - the kernel takes care of that. */ - portYIELD_WITHIN_API(); + queueYIELD_IF_USING_PREEMPTION(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes + and the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } } } @@ -604,27 +807,40 @@ xQUEUE * const pxQueue = ( xQUEUE * ) 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 this from within the critical section - the kernel takes care of that. */ - portYIELD_WITHIN_API(); + queueYIELD_IF_USING_PREEMPTION(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes and + the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_QUEUE_SETS */ taskEXIT_CRITICAL(); - - /* Return to the original privilege level before exiting the - function. */ return pdPASS; } else { - if( xTicksToWait == ( portTickType ) 0 ) + if( xTicksToWait == ( TickType_t ) 0 ) { /* The queue was full and no block time is specified (or the block time has expired) so leave now. */ @@ -644,7 +860,8 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } else { - /* Entry time was already set. */ + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); } } } @@ -694,8 +911,6 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; prvUnlockQueue( pxQueue ); ( void ) xTaskResumeAll(); - /* Return to the original privilege level before exiting the - function. */ traceQUEUE_SEND_FAILED( pxQueue ); return errQUEUE_FULL; } @@ -703,226 +918,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } /*-----------------------------------------------------------*/ -#if ( configUSE_ALTERNATIVE_API == 1 ) - signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) - { - signed portBASE_TYPE xEntryTimeSet = pdFALSE; - xTimeOutType xTimeOut; - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; - - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 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(); - } - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( portTickType ) 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 - { - taskEXIT_CRITICAL(); - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - } - taskEXIT_CRITICAL(); - } - } - -#endif /* configUSE_ALTERNATIVE_API */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_ALTERNATIVE_API == 1 ) - signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) - { - signed portBASE_TYPE xEntryTimeSet = pdFALSE; - xTimeOutType xTimeOut; - signed char *pcOriginalReadPosition; - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; - - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - for( ;; ) - { - taskENTER_CRITICAL(); - { - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 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 = ( signed char * ) xTaskGetCurrentTaskHandle(); - } - } - #endif - - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) - { - portYIELD_WITHIN_API(); - } - } - } - else - { - traceQUEUE_PEEK( pxQueue ); - - /* We are not removing the data, 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(); - } - } - - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( portTickType ) 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 ) - { - portENTER_CRITICAL(); - { - vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); - } - portEXIT_CRITICAL(); - } - } - #endif - - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - portYIELD_WITHIN_API(); - } - } - else - { - taskEXIT_CRITICAL(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - } - taskEXIT_CRITICAL(); - } - } - - -#endif /* configUSE_ALTERNATIVE_API */ -/*-----------------------------------------------------------*/ -signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) { -signed portBASE_TYPE xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are keep permanently enabled, even + above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion @@ -936,28 +944,35 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - /* Similar to xQueueGenericSend, except we don't block if there is no room - in the queue. Also we don't directly wake a task that was blocked on a - queue read, instead we return a flag to say whether a context switch is - required or not (i.e. has a task with a higher priority than us been woken - by this post). */ + /* Similar to xQueueGenericSend, except without blocking if there is no room + in the queue. Also don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { + const int8_t cTxLock = pxQueue->cTxLock; + traceQUEUE_SEND_FROM_ISR( pxQueue ); - prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a + semaphore or mutex. That means prvCopyDataToQueue() cannot result + in a task disinheriting a priority and prvCopyDataToQueue() can be + called here even though the disinherit function does not check if + the scheduler is suspended before accessing the ready lists. */ + ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - /* If the queue is locked we do not alter the event list. This will + /* 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 @@ -966,6 +981,14 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { *pxHigherPriorityTaskWoken = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else @@ -974,13 +997,25 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { 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. */ if( pxHigherPriorityTaskWoken != NULL ) { *pxHigherPriorityTaskWoken = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } } @@ -996,7 +1031,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { *pxHigherPriorityTaskWoken = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } #endif /* configUSE_QUEUE_SETS */ @@ -1005,7 +1052,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) 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; @@ -1021,15 +1068,186 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; return xReturn; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) + +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) { -signed portBASE_TYPE xEntryTimeSet = pdFALSE; -xTimeOutType xTimeOut; -signed char *pcOriginalReadPosition; -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* Similar to xQueueGenericSendFromISR() but used with semaphores where the + item size is 0. Don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() + if the item size is not 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); + + /* Normally a mutex would not be given from an interrupt, especially if + there is a mutex holder, as priority inheritance makes no sense for an + interrupts, only tasks. */ + configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + 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( 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 + holder - and if there is a mutex holder then the mutex cannot be + given from an ISR. As this is the ISR version of the function it + 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 = uxMessagesWaiting + 1; + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + 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 + task to unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const 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 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif /* This function relaxes the coding standard somewhat to allow return statements within the function itself. This is done in the interest @@ -1039,9 +1257,11 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { taskENTER_CRITICAL(); { - /* Is there data in the queue now? To be running we must be - the highest priority task wanting to access the queue. */ - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + 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( uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* Remember the read position in case the queue is only being peeked. */ @@ -1054,7 +1274,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; traceQUEUE_RECEIVE( pxQueue ); /* Actually removing data, not just peeking. */ - --( pxQueue->uxMessagesWaiting ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1; #if ( configUSE_MUTEXES == 1 ) { @@ -1062,17 +1282,29 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { /* Record the information required to implement priority inheritance should it become necessary. */ - pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */ + pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); } } - #endif + #endif /* configUSE_MUTEXES */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) { - portYIELD_WITHIN_API(); + queueYIELD_IF_USING_PREEMPTION(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else @@ -1087,13 +1319,19 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; 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(); + queueYIELD_IF_USING_PREEMPTION(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } @@ -1102,7 +1340,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } else { - if( xTicksToWait == ( portTickType ) 0 ) + if( xTicksToWait == ( TickType_t ) 0 ) { /* The queue was empty and no block time is specified (or the block time has expired) so leave now. */ @@ -1120,6 +1358,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; else { /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); } } } @@ -1142,11 +1381,15 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { - portENTER_CRITICAL(); + taskENTER_CRITICAL(); { vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); } - portEXIT_CRITICAL(); + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } } #endif @@ -1157,6 +1400,10 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { portYIELD_WITHIN_API(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -1169,52 +1416,65 @@ xQUEUE * const pxQueue = ( xQUEUE * ) 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(); + } } } } /*-----------------------------------------------------------*/ -signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) + +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) { -signed portBASE_TYPE xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are keep permanently enabled, even + above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); 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 > ( unsigned portBASE_TYPE ) 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 ) { @@ -1226,14 +1486,26 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; { *pxHigherPriorityTaskWoken = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else { /* 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; @@ -1249,36 +1521,38 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; return xReturn; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) + +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) { -signed portBASE_TYPE xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; -signed char *pcOriginalReadPosition; -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are keep permanently enabled, even + above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion failure if a FreeRTOS API function is called from an interrupt that has been assigned a priority above the configured maximum system call priority. Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { /* Cannot block in an ISR, so check there is data available. */ - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) { traceQUEUE_PEEK_FROM_ISR( pxQueue ); @@ -1302,54 +1576,99 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } /*-----------------------------------------------------------*/ -unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) { -unsigned portBASE_TYPE uxReturn; +UBaseType_t uxReturn; configASSERT( xQueue ); taskENTER_CRITICAL(); - uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting; + { + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + } taskEXIT_CRITICAL(); return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ -unsigned portBASE_TYPE IRAM uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) { -unsigned portBASE_TYPE uxReturn; +UBaseType_t uxReturn; +Queue_t *pxQueue; - configASSERT( xQueue ); + pxQueue = ( Queue_t * ) xQueue; + configASSERT( pxQueue ); - uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting; + taskENTER_CRITICAL(); + { + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ -void vQueueDelete( xQueueHandle xQueue ) +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) { -xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; +UBaseType_t uxReturn; + + configASSERT( xQueue ); + + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +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->pcHead ); - 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 */ } /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) { - return ( ( xQUEUE * ) xQueue )->ucQueueNumber; + return ( ( Queue_t * ) xQueue )->uxQueueNumber; } #endif /* configUSE_TRACE_FACILITY */ @@ -1357,9 +1676,9 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; #if ( configUSE_TRACE_FACILITY == 1 ) - void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) + void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) { - ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber; + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; } #endif /* configUSE_TRACE_FACILITY */ @@ -1367,25 +1686,37 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) { - return ( ( xQUEUE * ) xQueue )->ucQueueType; + return ( ( Queue_t * ) xQueue )->ucQueueType; } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ -static void IRAM prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) + +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) { - if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) +BaseType_t xReturn = pdFALSE; +UBaseType_t uxMessagesWaiting; + + /* This function is called from a critical section. */ + + uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) { #if ( configUSE_MUTEXES == 1 ) { if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) { /* The mutex is no longer being held. */ - vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); pxQueue->pxMutexHolder = NULL; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* configUSE_MUTEXES */ } @@ -1397,6 +1728,10 @@ static void IRAM prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, { pxQueue->pcWriteTo = pxQueue->pcHead; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -1406,37 +1741,57 @@ static void IRAM prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, { pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } if( xPosition == queueOVERWRITE ) { - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 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 + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } - ++( pxQueue->uxMessagesWaiting ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1; + + return xReturn; } /*-----------------------------------------------------------*/ -static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) + +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) { - if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) + if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) { pxQueue->u.pcReadFrom += pxQueue->uxItemSize; if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ { pxQueue->u.pcReadFrom = pxQueue->pcHead; } + else + { + mtCOVERAGE_TEST_MARKER(); + } ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ } } /*-----------------------------------------------------------*/ -static void IRAM prvUnlockQueue( xQUEUE *pxQueue ) + +static void prvUnlockQueue( Queue_t * const pxQueue ) { /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ @@ -1446,8 +1801,10 @@ static void IRAM prvUnlockQueue( xQUEUE *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? */ @@ -1455,18 +1812,23 @@ static void IRAM prvUnlockQueue( xQUEUE *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. A context switch is required. */ vTaskMissedYield(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } 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 ) @@ -1475,6 +1837,10 @@ static void IRAM prvUnlockQueue( xQUEUE *pxQueue ) context switch is required. */ vTaskMissedYield(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -1490,10 +1856,14 @@ static void IRAM prvUnlockQueue( xQUEUE *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 + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -1502,17 +1872,19 @@ static void IRAM prvUnlockQueue( xQUEUE *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 ) { @@ -1520,8 +1892,12 @@ static void IRAM prvUnlockQueue( xQUEUE *pxQueue ) { vTaskMissedYield(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } - --( pxQueue->xRxLock ); + --cRxLock; } else { @@ -1529,18 +1905,19 @@ static void IRAM prvUnlockQueue( xQUEUE *pxQueue ) } } - pxQueue->xRxLock = queueUNLOCKED; + pxQueue->cRxLock = queueUNLOCKED; } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ -static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) + +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) { -signed portBASE_TYPE xReturn; +BaseType_t xReturn; taskENTER_CRITICAL(); { - if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) { xReturn = pdTRUE; } @@ -1554,12 +1931,13 @@ signed portBASE_TYPE xReturn; return xReturn; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) + +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) { -signed portBASE_TYPE xReturn; +BaseType_t xReturn; configASSERT( xQueue ); - if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 ) { xReturn = pdTRUE; } @@ -1571,9 +1949,10 @@ signed portBASE_TYPE xReturn; return xReturn; } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ /*-----------------------------------------------------------*/ -static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) + +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) { -signed portBASE_TYPE xReturn; +BaseType_t xReturn; taskENTER_CRITICAL(); { @@ -1591,12 +1970,13 @@ signed portBASE_TYPE xReturn; return xReturn; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) + +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { -signed portBASE_TYPE xReturn; +BaseType_t xReturn; configASSERT( xQueue ); - if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength ) + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength ) { xReturn = pdTRUE; } @@ -1610,10 +1990,11 @@ signed portBASE_TYPE xReturn; /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ) + + BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) { - signed portBASE_TYPE xReturn; - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* If the queue is already full we may have to block. A critical section is required to prevent an interrupt removing something from the queue @@ -1624,7 +2005,7 @@ signed portBASE_TYPE xReturn; { /* The queue is full - do we want to block or just leave without posting? */ - if( xTicksToWait > ( portTickType ) 0 ) + if( xTicksToWait > ( TickType_t ) 0 ) { /* As this is called from a coroutine we cannot block directly, but return indicating that we need to block. */ @@ -1662,6 +2043,14 @@ signed portBASE_TYPE xReturn; that a yield might be appropriate. */ xReturn = errQUEUE_YIELD; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else @@ -1678,21 +2067,22 @@ signed portBASE_TYPE xReturn; /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait ) + + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) { - signed portBASE_TYPE xReturn; - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* If the queue is already empty we may have to block. A critical section is required to prevent an interrupt adding something to the queue between the check to see if the queue is empty and blocking on the queue. */ portDISABLE_INTERRUPTS(); { - if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) { /* There are no messages in the queue, do we want to block or just leave with nothing? */ - if( xTicksToWait > ( portTickType ) 0 ) + if( xTicksToWait > ( TickType_t ) 0 ) { /* As this is a co-routine we cannot block directly, but return indicating that we need to block. */ @@ -1706,12 +2096,16 @@ signed portBASE_TYPE xReturn; return errQUEUE_FULL; } } + else + { + mtCOVERAGE_TEST_MARKER(); + } } portENABLE_INTERRUPTS(); portDISABLE_INTERRUPTS(); { - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* Data is available from the queue. */ pxQueue->u.pcReadFrom += pxQueue->uxItemSize; @@ -1719,6 +2113,10 @@ signed portBASE_TYPE xReturn; { pxQueue->u.pcReadFrom = pxQueue->pcHead; } + else + { + mtCOVERAGE_TEST_MARKER(); + } --( pxQueue->uxMessagesWaiting ); ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); @@ -1735,6 +2133,14 @@ signed portBASE_TYPE xReturn; { xReturn = errQUEUE_YIELD; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } else @@ -1751,9 +2157,10 @@ signed portBASE_TYPE xReturn; /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) + + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) { - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* Cannot block within an ISR so if there is no space on the queue then exit without doing anything. */ @@ -1771,8 +2178,24 @@ signed portBASE_TYPE xReturn; { return pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } return xCoRoutinePreviouslyWoken; @@ -1783,14 +2206,14 @@ signed portBASE_TYPE xReturn; #if ( configUSE_CO_ROUTINES == 1 ) - signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) { - signed portBASE_TYPE xReturn; - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* We cannot block from an ISR, so check there is data available. If not then just leave without doing anything. */ - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) { /* Copy the data from the queue. */ pxQueue->u.pcReadFrom += pxQueue->uxItemSize; @@ -1798,6 +2221,10 @@ signed portBASE_TYPE xReturn; { pxQueue->u.pcReadFrom = pxQueue->pcHead; } + else + { + mtCOVERAGE_TEST_MARKER(); + } --( pxQueue->uxMessagesWaiting ); ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); @@ -1809,7 +2236,19 @@ signed portBASE_TYPE xReturn; { *pxCoRoutineWoken = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } xReturn = pdPASS; @@ -1827,21 +2266,27 @@ signed portBASE_TYPE xReturn; #if ( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { - unsigned portBASE_TYPE ux; + UBaseType_t ux; /* See if there is an empty space in the registry. A NULL name denotes a free slot. */ - for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) { if( xQueueRegistry[ ux ].pcQueueName == NULL ) { /* Store the information on this queue. */ xQueueRegistry[ ux ].pcQueueName = pcQueueName; xQueueRegistry[ ux ].xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); break; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } } @@ -1850,20 +2295,57 @@ signed portBASE_TYPE xReturn; #if ( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueUnregisterQueue( xQueueHandle xQueue ) + const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { - unsigned portBASE_TYPE ux; + UBaseType_t ux; + const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + + /* Note there is nothing here to protect against another task adding or + removing entries from the registry while it is being searched. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + pcReturn = xQueueRegistry[ ux ].pcQueueName; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return pcReturn; + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueUnregisterQueue( QueueHandle_t xQueue ) + { + UBaseType_t ux; /* See if the handle of the queue being unregistered in actually in the registry. */ - for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) { if( xQueueRegistry[ ux ].xHandle == xQueue ) { /* 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 + { + mtCOVERAGE_TEST_MARKER(); + } } } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ @@ -1873,9 +2355,9 @@ signed portBASE_TYPE xReturn; #if ( configUSE_TIMERS == 1 ) - void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) + void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { - xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* This function should not be called by application code hence the 'Restricted' in its name. It is not part of the public API. It is @@ -1892,10 +2374,14 @@ signed portBASE_TYPE xReturn; the queue is locked, and the calling task blocks on the queue, then the calling task will be immediately unblocked when the queue is unlocked. */ prvLockQueue( pxQueue ); - if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U ) + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) { /* There is nothing in the queue, block for the specified period. */ - vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); + } + else + { + mtCOVERAGE_TEST_MARKER(); } prvUnlockQueue( pxQueue ); } @@ -1903,13 +2389,13 @@ signed portBASE_TYPE xReturn; #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ -#if ( configUSE_QUEUE_SETS == 1 ) +#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) { - xQueueSetHandle pxQueue; + QueueSetHandle_t pxQueue; - pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET ); + pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); return pxQueue; } @@ -1919,30 +2405,30 @@ signed portBASE_TYPE xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) { - portBASE_TYPE xReturn; + BaseType_t xReturn; - if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + taskENTER_CRITICAL(); { - /* Cannot add a queue/semaphore to more than one queue set. */ - xReturn = pdFAIL; - } - else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 ) - { - /* Cannot add a queue/semaphore to a queue set if there are already - items in the queue/semaphore. */ - xReturn = pdFAIL; - } - else - { - taskENTER_CRITICAL(); + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) { - ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; } - taskEXIT_CRITICAL(); - xReturn = pdPASS; } + taskEXIT_CRITICAL(); return xReturn; } @@ -1952,17 +2438,17 @@ signed portBASE_TYPE xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) { - portBASE_TYPE xReturn; - xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore; + BaseType_t xReturn; + Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) { /* The queue was not a member of the set. */ xReturn = pdFAIL; } - else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 ) + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) { /* It is dangerous to remove a queue from a set when the queue is not empty because the queue set will still hold pending events for @@ -1988,11 +2474,11 @@ signed portBASE_TYPE xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) { - xQueueSetMemberHandle xReturn = NULL; + QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ + ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ return xReturn; } @@ -2001,11 +2487,11 @@ signed portBASE_TYPE xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) { - xQueueSetMemberHandle xReturn = NULL; + QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ return xReturn; } @@ -2014,27 +2500,52 @@ signed portBASE_TYPE xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) { - xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer; - portBASE_TYPE xReturn = pdFALSE; + Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; + BaseType_t xReturn = pdFALSE; + + /* This function must be called form a critical section. */ configASSERT( pxQueueSetContainer ); configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) { + const int8_t cTxLock = pxQueueSetContainer->cTxLock; + traceQUEUE_SEND( pxQueueSetContainer ); - /* The data copies is the handle of the queue that contains data. */ - prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); - if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + + /* The data copied is the handle of the queue that contains data. */ + xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + + if( cTxLock == queueUNLOCKED ) { - if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) { - /* The task waiting has a higher priority */ - xReturn = pdTRUE; + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } + else + { + pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } return xReturn; @@ -2042,3 +2553,14 @@ signed portBASE_TYPE xReturn; #endif /* configUSE_QUEUE_SETS */ + + + + + + + + + + + diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index e8b24d2..6c261a6 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -83,146 +88,28 @@ header files above, but not in this file, in order to generate the correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ +/* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting +functions but without including stdio.h here. */ #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) /* At the bottom of this file are two optional functions that can be used to generate human readable text from the raw data generated by the uxTaskGetSystemState() function. Note the formatting functions are provided for convenience only, and are NOT considered part of the kernel. */ #include -#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */ +#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 - -/* - * 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 portSTACK_TYPE *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 - - xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ - xListItem xEventListItem; /*< Used to reference a task from an event list. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - - #if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *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 ) - unsigned portBASE_TYPE 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 ) - unsigned portBASE_TYPE 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. */ - unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ - #endif - - #if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long 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 - -} tskTCB; - - -/* - * 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 +#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. */ + #define taskYIELD_IF_USING_PREEMPTION() +#else + #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #endif -/*lint -e956 A manual analysis and inspection has been used to determine which -static variables must be declared volatile. */ - -PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; - -/* Lists for ready and blocked tasks. --------------------*/ -PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ -PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList 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 xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ - PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U; - -#endif - -#if ( INCLUDE_vTaskSuspend == 1 ) - - PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ - -#endif - -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - - PRIVILEGED_DATA static xTaskHandle 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 unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U; -PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U; -PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = pdFALSE; -PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; -PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_DELAY; - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - PRIVILEGED_DATA static unsigned long 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 @@ -230,15 +117,41 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D */ #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. */ -#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) -#define tskREADY_CHAR ( ( signed char ) 'R' ) -#define tskDELETED_CHAR ( ( signed char ) 'D' ) -#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) +#define tskBLOCKED_CHAR ( 'B' ) +#define tskREADY_CHAR ( 'R' ) +#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 ) @@ -248,28 +161,31 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D /* uxTopReadyPriority holds the priority of the highest priority ready state task. */ - #define taskRECORD_READY_PRIORITY( uxPriority ) \ - { \ - if( ( uxPriority ) > uxTopReadyPriority ) \ - { \ - uxTopReadyPriority = ( uxPriority ); \ - } \ + #define taskRECORD_READY_PRIORITY( uxPriority ) \ + { \ + if( ( uxPriority ) > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( uxPriority ); \ + } \ } /* taskRECORD_READY_PRIORITY */ /*-----------------------------------------------------------*/ - #define taskSELECT_HIGHEST_PRIORITY_TASK() \ - { \ - /* Find the highest priority queue that contains ready tasks. */ \ - while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \ - { \ - configASSERT( uxTopReadyPriority ); \ - --uxTopReadyPriority; \ - } \ - \ - /* 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 ] ) ); \ + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority = uxTopReadyPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \ + { \ + 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[ uxTopPriority ] ) ); \ + uxTopReadyPriority = uxTopPriority; \ } /* taskSELECT_HIGHEST_PRIORITY_TASK */ /*-----------------------------------------------------------*/ @@ -293,9 +209,9 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D #define taskSELECT_HIGHEST_PRIORITY_TASK() \ { \ - unsigned portBASE_TYPE uxTopPriority; \ + 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 ] ) ); \ @@ -306,12 +222,12 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D /* A port optimised version is provided, call it only if the TCB being reset is being referenced from a ready list. If it is referenced from a delayed or suspended list then it won't be in a ready list. */ - #define taskRESET_READY_PRIORITY( uxPriority ) \ - { \ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \ - { \ - portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ - } \ + #define taskRESET_READY_PRIORITY( uxPriority ) \ + { \ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ + { \ + portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ + } \ } #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ @@ -322,7 +238,7 @@ PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_D count overflows. */ #define taskSWITCH_DELAYED_LISTS() \ { \ - xList *pxTemp; \ + List_t *pxTemp; \ \ /* The delayed tasks list should be empty when the lists are switched. */ \ configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ @@ -331,25 +247,7 @@ count overflows. */ pxDelayedTaskList = pxOverflowDelayedTaskList; \ pxOverflowDelayedTaskList = pxTemp; \ xNumOfOverflows++; \ - \ - if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \ - { \ - /* The new current delayed list is empty. Set \ - xNextTaskUnblockTime to the maximum possible value so it is \ - extremely unlikely that the \ - if( xTickCount >= xNextTaskUnblockTime ) test will pass until \ - there is an item in the delayed list. */ \ - xNextTaskUnblockTime = portMAX_DELAY; \ - } \ - else \ - { \ - /* The new current 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 should be removed \ - from the Blocked state. */ \ - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \ - xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \ - } \ + prvResetNextTaskUnblockTime(); \ } /*-----------------------------------------------------------*/ @@ -358,31 +256,198 @@ count overflows. */ * Place the task represented by pxTCB into the appropriate ready list for * the task. It is inserted at the end of the list. */ -#define prvAddTaskToReadyList( pxTCB ) \ - traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ - taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ - vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) +#define prvAddTaskToReadyList( pxTCB ) \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ + tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) /*-----------------------------------------------------------*/ /* - * Several functions take an xTaskHandle parameter that can optionally be NULL, + * Several functions take an TaskHandle_t parameter that can optionally be NULL, * where NULL is used to indicate that the handle of the currently executing * task should be used in place of the parameter. This macro simply checks to * see if the parameter is NULL and returns a pointer to the appropriate TCB. */ -#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) ) +#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) ) + +/* The item value of the event list item is normally used to hold the priority +of the task to which it belongs (coded to allow it to be held in reverse +priority order). However, it is occasionally borrowed for other purposes. It +is important its value is not updated due to a task priority change while it is +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 ) + #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. --------------------------*/ -extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName ); -extern void vApplicationTickHook( void ); +#if( configCHECK_FOR_STACK_OVERFLOW > 0 ) + extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); +#endif + +#if( configUSE_TICK_HOOK > 0 ) + extern void vApplicationTickHook( void ); +#endif + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); +#endif /* File private functions. --------------------------------*/ -/* - * Utility to ready a TCB for a given task. Mainly just copies the parameters - * into the TCB structure. +/** + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. */ -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; +#if ( INCLUDE_vTaskSuspend == 1 ) + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#endif /* INCLUDE_vTaskSuspend */ /* * Utility to ready all the lists used by the scheduler. This is called @@ -412,7 +477,7 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); */ #if ( INCLUDE_vTaskDelete == 1 ) - static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; + static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION; #endif @@ -427,16 +492,10 @@ 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 IRAM prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION; +static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION; /* - * Allocates memory from the heap for a TCB and associated stack. Checks the - * allocation was successful. - */ -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; - -/* - * Fills an xTaskStatusType structure with information on each task that is + * Fills an TaskStatus_t structure with information on each task that is * referenced from the pxList list (which may be a ready list, a delayed list, * a suspended list, etc.). * @@ -445,7 +504,17 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY */ #if ( configUSE_TRACE_FACILITY == 1 ) - static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *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 @@ -456,7 +525,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY */ #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; #endif @@ -471,212 +540,595 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY */ #if ( configUSE_TICKLESS_IDLE != 0 ) - static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; + static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; #endif -signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) -{ -signed portBASE_TYPE xReturn; -tskTCB * pxNewTCB; +/* + * Set xNextTaskUnblockTime to the time at which the next Blocked state task + * will exit the Blocked state. + */ +static void prvResetNextTaskUnblockTime( void ); - configASSERT( pxTaskCode ); - configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) ); +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - /* Allocate the memory required by the TCB and stack for the new task, - checking that the allocation was successful. */ - pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); + /* + * 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 ) PRIVILEGED_FUNCTION; - if( pxNewTCB != NULL ) +#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; + +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { - portSTACK_TYPE *pxTopOfStack; + TCB_t *pxNewTCB; + TaskHandle_t xReturn; - #if( portUSING_MPU_WRAPPERS == 1 ) - /* Should the task be created in privileged mode? */ - portBASE_TYPE xRunPrivileged; - if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) - { - xRunPrivileged = pdTRUE; - } - else - { - xRunPrivileged = pdFALSE; - } - uxPriority &= ~portPRIVILEGE_BIT; - #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 visa 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 - ( unsigned short ) 1 ); - pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( 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( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) 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( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) 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 ); - } - #endif /* portSTACK_GROWTH */ - - /* Setup the newly allocated TCB with the initial state of the task. */ - prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); - - /* 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 TCB out - in an anonymous way. The calling function/ - task can use this as a handle to delete the task later if - required.*/ - *pxCreatedTask = ( xTaskHandle ) pxNewTCB; - } - - /* Ensure interrupts don't access the task lists while they are being - updated. */ - taskENTER_CRITICAL(); - { - uxCurrentNumberOfTasks++; - if( pxCurrentTCB == NULL ) + if( pxStack != NULL ) { - /* There are no other tasks, or all the other tasks are in - the suspended state - make this the current task. */ - pxCurrentTCB = pxNewTCB; + /* 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( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) + if( pxNewTCB != NULL ) { - /* 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(); + /* 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 { - /* 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; - } - } + pxNewTCB = NULL; } - - 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(); + #endif /* portSTACK_GROWTH */ + + 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 */ + + prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); + prvAddNewTaskToReadyList( pxNewTCB ); + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + 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 ) + { + 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 the name string is terminated in the case that the string length + was greater or equal to configMAX_TASK_NAME_LEN. */ + pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + + /* This is used as an array index so must ensure it's not too large. First + remove the privilege bit if one is present. */ + if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; } else { - 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 ) - { - portYIELD_WITHIN_API(); - } + pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL; } } + #endif - return xReturn; + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + pxNewTCB->ulNotifiedValue = 0; + pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + } + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Initialise this task's Newlib reent structure. */ + _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); + } + #endif + + #if( INCLUDE_xTaskAbortDelay == 1 ) + { + pxNewTCB->ucDelayAborted = pdFALSE; + } + #endif + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + #if( portUSING_MPU_WRAPPERS == 1 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portUSING_MPU_WRAPPERS */ + + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the handle out in an anonymous way. The handle can be used to + change the created task's priority, delete the created task, etc.*/ + *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} +/*-----------------------------------------------------------*/ + +static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) +{ + /* Ensure interrupts don't access the task lists while the lists are being + updated. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + if( pxCurrentTCB == NULL ) + { + /* There are no other tasks, or all the other tasks are in + the suspended state - make this the current task. */ + pxCurrentTCB = pxNewTCB; + + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If the scheduler is not already running, make this task the + current task if it is the highest priority task to be created + so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ) + { + 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(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelete == 1 ) - void vTaskDelete( xTaskHandle xTaskToDelete ) + void vTaskDelete( TaskHandle_t xTaskToDelete ) { - tskTCB *pxTCB; + TCB_t *pxTCB; taskENTER_CRITICAL(); { - /* If null is passed in here then we are deleting ourselves. */ + /* If null is passed in here then it is the calling task that is + 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 ) ) == ( unsigned portBASE_TYPE ) 0 ) + /* Remove task from the ready list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } /* Is the task waiting on an event also? */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } + else + { + 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(); - /* Force a reschedule if we have just deleted the current task. */ + /* Force a reschedule if it is the currently running task that has just + been deleted. */ if( xSchedulerRunning != pdFALSE ) { if( pxTCB == pxCurrentTCB ) { + configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } } @@ -685,19 +1137,20 @@ tskTCB * pxNewTCB; #if ( INCLUDE_vTaskDelayUntil == 1 ) - void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) + void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) { - portTickType xTimeToWake; - portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; + TickType_t xTimeToWake; + BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); + configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { /* Minor optimisation. The tick count cannot change in this block. */ - const portTickType xConstTickCount = xTickCount; + const TickType_t xConstTickCount = xTickCount; /* Generate the tick time at which the task wants to wake. */ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; @@ -713,6 +1166,10 @@ tskTCB * pxNewTCB; { xShouldDelay = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -723,6 +1180,10 @@ tskTCB * pxNewTCB; { xShouldDelay = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } /* Update the wake time ready for the next call. */ @@ -730,20 +1191,15 @@ tskTCB * pxNewTCB; if( xShouldDelay != pdFALSE ) { - traceTASK_DELAY_UNTIL(); + traceTASK_DELAY_UNTIL( xTimeToWake ); - /* 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 ) ) == ( unsigned portBASE_TYPE ) 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 ); - } - - prvAddCurrentTaskToDelayedList( xTimeToWake ); + /* prvAddCurrentTaskToDelayedList() needs the block time, not + the time to wake, so subtract the current tick count. */ + prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); + } + else + { + mtCOVERAGE_TEST_MARKER(); } } xAlreadyYielded = xTaskResumeAll(); @@ -754,6 +1210,10 @@ tskTCB * pxNewTCB; { portYIELD_WITHIN_API(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* INCLUDE_vTaskDelayUntil */ @@ -761,14 +1221,14 @@ tskTCB * pxNewTCB; #if ( INCLUDE_vTaskDelay == 1 ) - void vTaskDelay( portTickType xTicksToDelay ) + void vTaskDelay( const TickType_t xTicksToDelay ) { - portTickType xTimeToWake; - signed portBASE_TYPE xAlreadyYielded = pdFALSE; + BaseType_t xAlreadyYielded = pdFALSE; /* A delay time of zero just forces a reschedule. */ - if( xTicksToDelay > ( portTickType ) 0U ) + if( xTicksToDelay > ( TickType_t ) 0U ) { + configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { traceTASK_DELAY(); @@ -780,25 +1240,14 @@ tskTCB * pxNewTCB; 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 ) ) == ( unsigned portBASE_TYPE ) 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 ); - } - prvAddCurrentTaskToDelayedList( xTimeToWake ); + prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); } xAlreadyYielded = xTaskResumeAll(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } /* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */ @@ -806,18 +1255,24 @@ tskTCB * pxNewTCB; { portYIELD_WITHIN_API(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* INCLUDE_vTaskDelay */ /*-----------------------------------------------------------*/ -#if ( INCLUDE_eTaskGetState == 1 ) +#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) ) - eTaskState eTaskGetState( xTaskHandle xTask ) + eTaskState eTaskGetState( TaskHandle_t xTask ) { eTaskState eReturn; - xList *pxStateList; - const tskTCB * const pxTCB = ( tskTCB * ) xTask; + List_t *pxStateList; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + configASSERT( pxTCB ); if( pxTCB == pxCurrentTCB ) { @@ -828,7 +1283,7 @@ tskTCB * pxNewTCB; { taskENTER_CRITICAL(); { - pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) ); + pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); } taskEXIT_CRITICAL(); @@ -843,21 +1298,30 @@ tskTCB * pxNewTCB; else if( pxStateList == &xSuspendedTaskList ) { /* The task being queried is referenced from the suspended - list. */ - eReturn = eSuspended; + list. Is it genuinely suspended or is it block + indefinitely? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + { + eReturn = eSuspended; + } + else + { + eReturn = eBlocked; + } } #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 - else + else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ { /* If the task is not in any other state, it must be in the Ready (including pending ready) state. */ @@ -866,22 +1330,22 @@ tskTCB * pxNewTCB; } return eReturn; - } + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ #endif /* INCLUDE_eTaskGetState */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskPriorityGet == 1 ) - unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) + UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxReturn; + TCB_t *pxTCB; + UBaseType_t uxReturn; taskENTER_CRITICAL(); { - /* If null is passed in here then we are changing the - priority of the calling function. */ + /* If null is passed in here then it is the priority of the that + called uxTaskPriorityGet() that is being queried. */ pxTCB = prvGetTCBFromHandle( xTask ); uxReturn = pxTCB->uxPriority; } @@ -893,20 +1357,64 @@ tskTCB * pxNewTCB; #endif /* INCLUDE_uxTaskPriorityGet */ /*-----------------------------------------------------------*/ +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + UBaseType_t uxReturn, uxSavedInterruptState; + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* If null is passed in here then it is the priority of the calling + task that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + #if ( INCLUDE_vTaskPrioritySet == 1 ) - void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority ) + void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxCurrentBasePriority, uxPriorityUsedOnEntry; - portBASE_TYPE xYieldRequired = pdFALSE; + TCB_t *pxTCB; + UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; + BaseType_t xYieldRequired = pdFALSE; configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); /* Ensure the new priority is valid. */ - if( uxNewPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES ) + if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) { - uxNewPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; + uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); } taskENTER_CRITICAL(); @@ -939,9 +1447,13 @@ tskTCB * pxNewTCB; running task is being raised. Is the priority being raised above that of the running task? */ if( uxNewPriority >= pxCurrentTCB->uxPriority ) - { + { xYieldRequired = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -952,8 +1464,8 @@ tskTCB * pxNewTCB; } else if( pxTCB == pxCurrentTCB ) { - /* Setting the priority of the running task down means - there may now be another task of higher priority that + /* Setting the priority of the running task down means + there may now be another task of higher priority that is ready to execute. */ xYieldRequired = pdTRUE; } @@ -977,6 +1489,10 @@ tskTCB * pxNewTCB; { pxTCB->uxPriority = uxNewPriority; } + else + { + mtCOVERAGE_TEST_MARKER(); + } /* The base priority gets set whatever. */ pxTCB->uxBasePriority = uxNewPriority; @@ -987,30 +1503,51 @@ tskTCB * pxNewTCB; } #endif - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + /* Only reset the event list item value if the value is not + being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } /* If the task is in the blocked or suspended list we need do 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 ) ) == ( unsigned portBASE_TYPE ) 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 reset macro can be called directly. */ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } prvAddTaskToReadyList( pxTCB ); } - - if( xYieldRequired == pdTRUE ) + else { - portYIELD_WITHIN_API(); + mtCOVERAGE_TEST_MARKER(); + } + + if( xYieldRequired != pdFALSE ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } /* Remove compiler warning about unused variables when the port @@ -1026,9 +1563,9 @@ tskTCB * pxNewTCB; #if ( INCLUDE_vTaskSuspend == 1 ) - void vTaskSuspend( xTaskHandle xTaskToSuspend ) + void vTaskSuspend( TaskHandle_t xTaskToSuspend ) { - tskTCB *pxTCB; + TCB_t *pxTCB; taskENTER_CRITICAL(); { @@ -1038,27 +1575,52 @@ tskTCB * pxNewTCB; traceTASK_SUSPEND( pxTCB ); - /* Remove task from the ready/delayed list and place in the suspended list. */ - if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + /* Remove task from the ready/delayed list and place in the + suspended list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } /* Is the task waiting on an event also? */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } + else + { + 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 ) { /* The current task has just been suspended. */ + configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } else @@ -1080,6 +1642,10 @@ tskTCB * pxNewTCB; } } } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* INCLUDE_vTaskSuspend */ @@ -1087,30 +1653,42 @@ tskTCB * pxNewTCB; #if ( INCLUDE_vTaskSuspend == 1 ) - signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) { - portBASE_TYPE xReturn = pdFALSE; - const tskTCB * const pxTCB = ( tskTCB * ) xTask; + BaseType_t xReturn = pdFALSE; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + /* Accesses xPendingReadyList so must be called from a critical + section. */ /* It does not make sense to check if the calling task is suspended. */ configASSERT( xTask ); - /* Is the task we are attempting to resume actually in the - suspended list? */ - if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) + /* Is the task being resumed actually in the suspended list? */ + 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 ) { - /* Is it in the suspended list because it is in the - Suspended state? It is possible to be in the suspended - list because it is blocked on a task with no timeout - specified. */ + /* Is it in the suspended list because it is in the Suspended + state, or because is is blocked with no timeout? */ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) { xReturn = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } return xReturn; @@ -1121,9 +1699,9 @@ tskTCB * pxNewTCB; #if ( INCLUDE_vTaskSuspend == 1 ) - void vTaskResume( xTaskHandle xTaskToResume ) + void vTaskResume( TaskHandle_t xTaskToResume ) { - tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume; + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; /* It does not make sense to resume the calling task. */ configASSERT( xTaskToResume ); @@ -1134,26 +1712,39 @@ tskTCB * pxNewTCB; { taskENTER_CRITICAL(); { - if( xTaskIsTaskSuspended( 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. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) { - /* This yield may not cause the task just resumed to run, but - will leave the lists in the correct state for the next yield. */ - portYIELD_WITHIN_API(); + /* This yield may not cause the task just resumed to run, + but will leave the lists in the correct state for the + next yield. */ + taskYIELD_IF_USING_PREEMPTION(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* INCLUDE_vTaskSuspend */ @@ -1162,11 +1753,11 @@ tskTCB * pxNewTCB; #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) + BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) { - portBASE_TYPE xYieldRequired = pdFALSE; - tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume; - unsigned portBASE_TYPE uxSavedInterruptStatus; + BaseType_t xYieldRequired = pdFALSE; + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + UBaseType_t uxSavedInterruptStatus; configASSERT( xTaskToResume ); @@ -1190,24 +1781,39 @@ tskTCB * pxNewTCB; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) { traceTASK_RESUME_FROM_ISR( pxTCB ); - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + /* Check the ready lists can be accessed. */ + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { - xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); - ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + /* Ready lists can be accessed so move the task from the + suspended list to the ready list directly. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); } else { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed, at which point a - yield will be performed if necessary. */ + /* The delayed or ready lists cannot be accessed so the task + is held in the pending ready list until the scheduler is + unsuspended. */ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); } } + else + { + mtCOVERAGE_TEST_MARKER(); + } } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); @@ -1219,21 +1825,45 @@ tskTCB * pxNewTCB; void vTaskStartScheduler( void ) { -portBASE_TYPE xReturn; +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, ( signed char * ) "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, ( signed char * ) "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 ) { @@ -1241,6 +1871,10 @@ portBASE_TYPE xReturn; { xReturn = xTimerCreateTimerTask(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* configUSE_TIMERS */ @@ -1250,14 +1884,20 @@ portBASE_TYPE xReturn; before or during the call to xPortStartScheduler(). The stacks of the created tasks contain a status word with interrupts switched on so interrupts will automatically get re-enabled when the first task - starts to run. - - STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE - DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ + starts to run. */ portDISABLE_INTERRUPTS(); + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to the task that will run first. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; - xTickCount = ( portTickType ) 0U; + xTickCount = ( TickType_t ) 0U; /* If configGENERATE_RUN_TIME_STATS is defined then the following macro must be defined to configure the timer/counter used to generate @@ -1281,8 +1921,12 @@ portBASE_TYPE 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; } /*-----------------------------------------------------------*/ @@ -1297,19 +1941,49 @@ void vTaskEndScheduler( void ) } /*----------------------------------------------------------*/ -void IRAM vTaskSuspendAll( void ) +void vTaskSuspendAll( void ) { /* A critical section is not required as the variable is of type - portBASE_TYPE. */ + BaseType_t. Please read Richard Barry's reply in the following link to a + post in the FreeRTOS support forum before reporting this as a bug! - + http://goo.gl/wu4acr */ ++uxSchedulerSuspended; } /*----------------------------------------------------------*/ #if ( configUSE_TICKLESS_IDLE != 0 ) - static portTickType prvGetExpectedIdleTime( void ) + static TickType_t prvGetExpectedIdleTime( void ) { - portTickType xReturn; + 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 ) { @@ -1322,6 +1996,13 @@ void IRAM 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; @@ -1333,11 +2014,10 @@ void IRAM vTaskSuspendAll( void ) #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ -signed portBASE_TYPE IRAM xTaskResumeAll( void ) +BaseType_t xTaskResumeAll( void ) { -tskTCB *pxTCB; -portBASE_TYPE xAlreadyYielded = pdFALSE; -portBASE_TYPE xYieldRequired = pdFALSE; +TCB_t *pxTCB = NULL; +BaseType_t xAlreadyYielded = pdFALSE; /* If uxSchedulerSuspended is zero then this function does not match a previous call to vTaskSuspendAll(). */ @@ -1352,50 +2032,91 @@ portBASE_TYPE xYieldRequired = pdFALSE; { --uxSchedulerSuspended; - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { - if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U ) + if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) { /* Move any readied tasks from the pending list into the appropriate ready list. */ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) { - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); - /* If we have moved a task that has a priority higher than - the current task then we should yield. */ + /* If the moved task has a priority higher than the current + task then a yield must be performed. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) { - xYieldRequired = pdTRUE; + xYieldPending = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + 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 > ( unsigned portBASE_TYPE ) 0U ) + they should be processed now. This ensures the tick count does + not slip, and that any delayed tasks are resumed at the correct + time. */ { - while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U ) + UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */ + + if( uxPendedCounts > ( UBaseType_t ) 0U ) { - if( xTaskIncrementTick() != pdFALSE ) + do { - xYieldRequired = pdTRUE; - } - --uxPendedTicks; + if( xTaskIncrementTick() != pdFALSE ) + { + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --uxPendedCounts; + } while( uxPendedCounts > ( UBaseType_t ) 0U ); + + uxPendedTicks = 0; + } + else + { + mtCOVERAGE_TEST_MARKER(); } } - if( ( xYieldRequired == pdTRUE ) || ( xYieldPending == pdTRUE ) ) + if( xYieldPending != pdFALSE ) { - xAlreadyYielded = pdTRUE; - xYieldPending = pdFALSE; - portYIELD_WITHIN_API(); + #if( configUSE_PREEMPTION != 0 ) + { + xAlreadyYielded = pdTRUE; + } + #endif + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); } } } + else + { + mtCOVERAGE_TEST_MARKER(); + } } taskEXIT_CRITICAL(); @@ -1403,29 +2124,29 @@ portBASE_TYPE xYieldRequired = pdFALSE; } /*-----------------------------------------------------------*/ -portTickType xTaskGetTickCount( void ) +TickType_t xTaskGetTickCount( void ) { -portTickType xTicks; +TickType_t xTicks; /* Critical section required if running on a 16 bit processor. */ - taskENTER_CRITICAL(); + portTICK_TYPE_ENTER_CRITICAL(); { xTicks = xTickCount; } - taskEXIT_CRITICAL(); + portTICK_TYPE_EXIT_CRITICAL(); return xTicks; } /*-----------------------------------------------------------*/ -portTickType xTaskGetTickCountFromISR( void ) +TickType_t xTaskGetTickCountFromISR( void ) { -portTickType xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; +TickType_t xReturn; +UBaseType_t uxSavedInterruptStatus; /* RTOS ports that support interrupt nesting have the concept of a maximum system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are keep permanently enabled, even + above the maximum system call priority are kept permanently enabled, even when the RTOS kernel is in a critical section, but cannot make any calls to FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion @@ -1439,75 +2160,200 @@ unsigned portBASE_TYPE uxSavedInterruptStatus; link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - xReturn = xTickCount; - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR(); + { + xReturn = xTickCount; + } + portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xReturn; } /*-----------------------------------------------------------*/ -unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) +UBaseType_t uxTaskGetNumberOfTasks( void ) { /* A critical section is not required because the variables are of type - portBASE_TYPE. */ + BaseType_t. */ return uxCurrentNumberOfTasks; } /*-----------------------------------------------------------*/ -#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; - signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ) + /* 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[] ) { - tskTCB *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 ) - unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime ) + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) { - unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES; + UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; vTaskSuspendAll(); { /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { - /* Fill in an xTaskStatusType structure with information on each + /* Fill in an TaskStatus_t structure with information on each task in the Ready state. */ do { uxQueue--; - uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); - } while( uxQueue > ( unsigned portBASE_TYPE ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - /* Fill in an xTaskStatusType structure with information on each + /* Fill in an TaskStatus_t structure with information on each task in the Blocked state. */ - uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked ); - uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) 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 xTaskStatusType structure with information on + /* 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 #if ( INCLUDE_vTaskSuspend == 1 ) { - /* Fill in an xTaskStatusType structure with information on + /* 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 @@ -1515,7 +2361,11 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) { if( pulTotalRunTime != NULL ) { - *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif } } #else @@ -1527,6 +2377,10 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) } #endif } + else + { + mtCOVERAGE_TEST_MARKER(); + } } ( void ) xTaskResumeAll(); @@ -1538,7 +2392,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - xTaskHandle xTaskGetIdleTaskHandle( void ) + TaskHandle_t xTaskGetIdleTaskHandle( void ) { /* If xTaskGetIdleTaskHandle() is called before the scheduler has been started, then xIdleTaskHandle will be NULL. */ @@ -1555,7 +2409,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) - void vTaskStepTick( portTickType xTicksToJump ) + void vTaskStepTick( const TickType_t xTicksToJump ) { /* Correct the tick count value after a period during which the tick was suppressed. Note this does *not* call the tick hook function for @@ -1568,97 +2422,187 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ -portBASE_TYPE IRAM xTaskIncrementTick( void ) +#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 ) { -tskTCB * pxTCB; -portTickType xItemValue; -portBASE_TYPE xSwitchRequired = pdFALSE; +TCB_t * pxTCB; +TickType_t xItemValue; +BaseType_t xSwitchRequired = pdFALSE; /* Called by the portable layer each time a tick interrupt occurs. Increments the tick then checks to see if the new tick value will cause any tasks to be unblocked. */ traceTASK_INCREMENT_TICK( xTickCount ); - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + 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 portTickType xConstTickCount = xTickCount; + taskSWITCH_DELAYED_LISTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xConstTickCount == ( portTickType ) 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(); - } - - /* 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 tasks has been - found whose block time has not expired there is no need not 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 = ( tskTCB * ) 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; - } - - /* 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 ) ); - } - - /* 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; - } - } - #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 */ } } } @@ -1668,12 +2612,31 @@ portBASE_TYPE xSwitchRequired = pdFALSE; writer has not explicitly turned time slicing off. */ #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) { - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 ) + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ) { xSwitchRequired = pdTRUE; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ + + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the pended tick + count is being unwound (when the scheduler is being unlocked). */ + if( uxPendedTicks == ( UBaseType_t ) 0U ) + { + vApplicationTickHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICK_HOOK */ } else { @@ -1688,16 +2651,18 @@ portBASE_TYPE xSwitchRequired = pdFALSE; #endif } - #if ( configUSE_TICK_HOOK == 1 ) + #if ( configUSE_PREEMPTION == 1 ) { - /* Guard against the tick hook being called when the missed tick - count is being unwound (when the scheduler is being unlocked). */ - if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U ) + if( xYieldPending != pdFALSE ) { - vApplicationTickHook(); + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); } } - #endif /* configUSE_TICK_HOOK */ + #endif /* configUSE_PREEMPTION */ return xSwitchRequired; } @@ -1705,18 +2670,19 @@ portBASE_TYPE xSwitchRequired = pdFALSE; #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) { - tskTCB *xTCB; + TCB_t *xTCB; - /* If xTask is NULL then we are setting our own task hook. */ + /* If xTask is NULL then it is the task hook of the calling task that is + getting set. */ if( xTask == NULL ) { - xTCB = ( tskTCB * ) pxCurrentTCB; + xTCB = ( TCB_t * ) pxCurrentTCB; } else { - xTCB = ( tskTCB * ) xTask; + xTCB = ( TCB_t * ) xTask; } /* Save the hook function in the TCB. A critical section is required as @@ -1731,25 +2697,27 @@ portBASE_TYPE xSwitchRequired = pdFALSE; #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) { - tskTCB *xTCB; - pdTASK_HOOK_CODE xReturn; + TCB_t *xTCB; + TaskHookFunction_t xReturn; /* If xTask is NULL then we are setting our own task hook. */ if( xTask == NULL ) { - xTCB = ( tskTCB * ) pxCurrentTCB; + xTCB = ( TCB_t * ) pxCurrentTCB; } else { - xTCB = ( tskTCB * ) xTask; + xTCB = ( TCB_t * ) xTask; } /* Save the hook function in the TCB. A critical section is required as the value can be accessed from an interrupt. */ taskENTER_CRITICAL(); + { xReturn = xTCB->pxTaskTag; + } taskEXIT_CRITICAL(); return xReturn; @@ -1760,19 +2728,19 @@ portBASE_TYPE xSwitchRequired = pdFALSE; #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) + BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) { - tskTCB *xTCB; - portBASE_TYPE xReturn; + TCB_t *xTCB; + BaseType_t xReturn; /* If xTask is NULL then we are calling our own task hook. */ if( xTask == NULL ) { - xTCB = ( tskTCB * ) pxCurrentTCB; + xTCB = ( TCB_t * ) pxCurrentTCB; } else { - xTCB = ( tskTCB * ) xTask; + xTCB = ( TCB_t * ) xTask; } if( xTCB->pxTaskTag != NULL ) @@ -1792,7 +2760,7 @@ portBASE_TYPE xSwitchRequired = pdFALSE; void vTaskSwitchContext( void ) { - if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) + if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context switch. */ @@ -1800,6 +2768,7 @@ void vTaskSwitchContext( void ) } else { + xYieldPending = pdFALSE; traceTASK_SWITCHED_OUT(); #if ( configGENERATE_RUN_TIME_STATS == 1 ) @@ -1811,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. */ @@ -1821,15 +2790,20 @@ void vTaskSwitchContext( void ) { pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } ulTaskSwitchedInTime = ulTotalRunTime; } #endif /* configGENERATE_RUN_TIME_STATS */ - taskFIRST_CHECK_FOR_STACK_OVERFLOW(); - taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + /* Check for stack overflow, if configured. */ + taskCHECK_FOR_STACK_OVERFLOW(); + /* Select a new task to run using either the generic C or port + optimised asm code. */ taskSELECT_HIGHEST_PRIORITY_TASK(); - traceTASK_SWITCHED_IN(); #if ( configUSE_NEWLIB_REENTRANT == 1 ) @@ -1843,70 +2817,57 @@ void vTaskSwitchContext( void ) } /*-----------------------------------------------------------*/ -void IRAM vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { -portTickType xTimeToWake; - configASSERT( pxEventList ); - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. */ + /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ /* Place the event list item of the TCB in the appropriate event list. This is placed in the list in priority order so the highest priority task - is the first to be woken by the event. */ + is the first to be woken by the event. The queue that contains the event + list is locked, preventing simultaneous access from interrupts. */ vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); - /* 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. We have - exclusive access to the ready lists as the scheduler is locked. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 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 ); - } - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add ourselves to the suspended task list instead of a delayed task - list to ensure we are not woken by a timing event. We 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; - 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. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - #endif /* INCLUDE_vTaskSuspend */ + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); } /*-----------------------------------------------------------*/ -#if configUSE_TIMERS == 1 +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) +{ + configASSERT( pxEventList ); - void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event groups implementation. */ + configASSERT( uxSchedulerSuspended != 0 ); + + /* Store the item value in the event list item. It is safe to access the + event list item here as interrupts won't access the event list item of a + task that is not in the Blocked state. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Place the event list item of the TCB at the end of the appropriate event + list. It is safe to access the event list here because it is part of an + event group implementation - and interrupts don't access event groups + directly (instead they access them indirectly by pending function calls to + the task level). */ + vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); +} +/*-----------------------------------------------------------*/ + +#if( configUSE_TIMERS == 1 ) + + void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { - portTickType xTimeToWake; - configASSERT( pxEventList ); /* This function should not be called by application code hence the 'Restricted' in its name. It is not part of the public API. It is designed for use by kernel code, and has special calling requirements - - it should be called from a critical section. */ + it should be called with the scheduler suspended. */ /* Place the event list item of the TCB in the appropriate event list. @@ -1915,68 +2876,124 @@ portTickType 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 form a critical section. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 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 ); + xTicksToWait = portMAX_DELAY; } - /* 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 ); + traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) ); + prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely ); } #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ -signed portBASE_TYPE IRAM xTaskRemoveFromEventList( const xList * const pxEventList ) +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) { -tskTCB *pxUnblockedTCB; -portBASE_TYPE xReturn; +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. It can also be called from within an ISR. */ + /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be + called from a critical section within an ISR. */ - /* The event list is sorted in priority order, so we can remove the - first in the list, remove the TCB from the delayed list, and add - it to the ready list. + /* The event list is sorted in priority order, so the first in the list can + be removed as it is known to be the highest priority. Remove the TCB from + the delayed list, and add it to the ready list. If an event is for a queue that is locked then this function will never get called - the lock count on the queue will get modified instead. This - means we can always expect exclusive access to the event list here. + means exclusive access to the event list is guaranteed here. This function assumes that a check has already been made to ensure that pxEventList is not empty. */ - pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); configASSERT( pxUnblockedTCB ); ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { - ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); } else { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed. */ + /* The delayed and ready lists cannot be accessed, so hold this task + pending until the scheduler is resumed. */ vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); } - if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has a higher + priority than the calling task. This allows the calling task to know if + it should force a context switch now. */ + xReturn = pdTRUE; + + /* 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 + { + xReturn = pdFALSE; + } + + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event flags implementation. */ + configASSERT( uxSchedulerSuspended != pdFALSE ); + + /* Store the new item value in the event list. */ + listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Remove the event list form the event flag. Interrupts do not access + event flags. */ + pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( pxEventListItem ); + + /* 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->xStateListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) { /* Return true if the task removed from the event list has a higher priority than the calling task. This allows the calling task to know if it should force a context switch now. */ xReturn = pdTRUE; + + /* 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 { @@ -1987,7 +3004,7 @@ portBASE_TYPE xReturn; } /*-----------------------------------------------------------*/ -void IRAM vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) { configASSERT( pxTimeOut ); pxTimeOut->xOverflowCount = xNumOfOverflows; @@ -1995,9 +3012,9 @@ void IRAM vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) } /*-----------------------------------------------------------*/ -portBASE_TYPE IRAM xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) { -portBASE_TYPE xReturn; +BaseType_t xReturn; configASSERT( pxTimeOut ); configASSERT( pxTicksToWait ); @@ -2005,31 +3022,43 @@ portBASE_TYPE xReturn; taskENTER_CRITICAL(); { /* Minor optimisation. The tick count cannot change in this block. */ - const portTickType xConstTickCount = xTickCount; + 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; } @@ -2044,7 +3073,7 @@ portBASE_TYPE xReturn; } /*-----------------------------------------------------------*/ -void IRAM vTaskMissedYield( void ) +void vTaskMissedYield( void ) { xYieldPending = pdTRUE; } @@ -2052,14 +3081,14 @@ void IRAM vTaskMissedYield( void ) #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ) + UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) { - unsigned portBASE_TYPE uxReturn; - tskTCB *pxTCB; + UBaseType_t uxReturn; + TCB_t *pxTCB; if( xTask != NULL ) { - pxTCB = ( tskTCB * ) xTask; + pxTCB = ( TCB_t * ) xTask; uxReturn = pxTCB->uxTaskNumber; } else @@ -2075,13 +3104,13 @@ void IRAM vTaskMissedYield( void ) #if ( configUSE_TRACE_FACILITY == 1 ) - void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ) + void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) { - tskTCB *pxTCB; + TCB_t *pxTCB; if( xTask != NULL ) { - pxTCB = ( tskTCB * ) xTask; + pxTCB = ( TCB_t * ) xTask; pxTCB->uxTaskNumber = uxHandle; } } @@ -2104,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 ) @@ -2130,10 +3163,14 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) the list, and an occasional incorrect value will not matter. If the ready list at the idle priority contains more than one task then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) { taskYIELD(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ @@ -2156,7 +3193,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) configUSE_TICKLESS_IDLE to be set to a value other than 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) { - portTickType xExpectedIdleTime; + TickType_t xExpectedIdleTime; /* It is not desirable to suspend then resume the scheduler on each iteration of the idle task. Therefore, a preliminary @@ -2181,19 +3218,29 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); traceLOW_POWER_IDLE_END(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } ( void ) xTaskResumeAll(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif /* configUSE_TICKLESS_IDLE */ } } /*-----------------------------------------------------------*/ -#if configUSE_TICKLESS_IDLE != 0 +#if( configUSE_TICKLESS_IDLE != 0 ) eSleepModeStatus eTaskConfirmSleepModeStatus( void ) { + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = 1; eSleepModeStatus eReturn = eStandardSleep; if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) @@ -2208,123 +3255,76 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } else { - #if configUSE_TIMERS == 0 + /* If all the tasks are in the suspended list (which might mean they + have an infinite block time rather than actually being suspended) + then it is safe to turn all clocks off and just wait for external + interrupts. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) { - /* The idle task exists in addition to the application tasks. */ - const unsigned portBASE_TYPE uxNonApplicationTasks = 1; - - /* If timers are not being used and all the tasks are in the - suspended list (which might mean they have an infinite block - time rather than actually being suspended) then it is safe to - turn all clocks off and just wait for external interrupts. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) - { - eReturn = eNoTasksWaitingTimeout; - } + eReturn = eNoTasksWaitingTimeout; + } + else + { + mtCOVERAGE_TEST_MARKER(); } - #endif /* configUSE_TIMERS */ } return eReturn; } + #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) -{ -unsigned portBASE_TYPE x; +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) - /* Store the task name in the TCB. */ - for( x = ( unsigned portBASE_TYPE ) 0; x < ( unsigned portBASE_TYPE ) configMAX_TASK_NAME_LEN; x++ ) + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) { - pxTCB->pcTaskName[ x ] = pcName[ x ]; + TCB_t *pxTCB; - /* 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 ) + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { - break; + pxTCB = prvGetTCBFromHandle( xTaskToSet ); + pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; } } - /* 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 ] = ( signed char ) '\0'; +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ +/*-----------------------------------------------------------*/ - /* 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 >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES ) +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + + void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) { - uxPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; + void *pvReturn = NULL; + TCB_t *pxTCB; + + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + } + else + { + pvReturn = NULL; + } + + return pvReturn; } - pxTCB->uxPriority = uxPriority; - #if ( configUSE_MUTEXES == 1 ) - { - pxTCB->uxBasePriority = uxPriority; - } - #endif /* configUSE_MUTEXES */ - - vListInitialiseItem( &( pxTCB->xGenericListItem ) ); - vListInitialiseItem( &( pxTCB->xEventListItem ) ); - - /* Set the pxTCB as a link back from the xListItem. 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 ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) 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 = ( unsigned portBASE_TYPE ) 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 ( configUSE_NEWLIB_REENTRANT == 1 ) - { - /* Initialise this task's Newlib reent structure. */ - _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); - } - #endif /* configUSE_NEWLIB_REENTRANT */ -} +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ /*-----------------------------------------------------------*/ #if ( portUSING_MPU_WRAPPERS == 1 ) - void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) + void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) { - tskTCB *pxTCB; + TCB_t *pxTCB; - /* If null is passed in here then we are deleting ourselves. */ + /* If null is passed in here then we are modifying the MPU settings of + the calling task. */ pxTCB = prvGetTCBFromHandle( xTaskToModify ); - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); } #endif /* portUSING_MPU_WRAPPERS */ @@ -2332,9 +3332,9 @@ unsigned portBASE_TYPE x; static void prvInitialiseTaskLists( void ) { -unsigned portBASE_TYPE uxPriority; +UBaseType_t uxPriority; - for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < ( unsigned portBASE_TYPE ) configMAX_PRIORITIES; uxPriority++ ) + for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) { vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); } @@ -2364,156 +3364,163 @@ unsigned portBASE_TYPE uxPriority; static void prvCheckTasksWaitingTermination( void ) { + + /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ + #if ( INCLUDE_vTaskDelete == 1 ) { - portBASE_TYPE xListIsEmpty; + BaseType_t xListIsEmpty; /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called too often in the idle task. */ - while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) + while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) { vTaskSuspendAll(); + { xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + } ( void ) xTaskResumeAll(); if( xListIsEmpty == pdFALSE ) { - tskTCB *pxTCB; + TCB_t *pxTCB; taskENTER_CRITICAL(); { - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); - ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); --uxCurrentNumberOfTasks; - --uxTasksDeleted; + --uxDeletedTasksWaitingCleanUp; } taskEXIT_CRITICAL(); prvDeleteTCB( pxTCB ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } } - #endif /* vTaskDelete */ + #endif /* INCLUDE_vTaskDelete */ } /*-----------------------------------------------------------*/ -static void IRAM prvAddCurrentTaskToDelayedList( portTickType 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 we can use the current block list. */ - 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 */ -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) -{ -tskTCB *pxNewTCB; - - /* Allocate space for the TCB. Where the memory comes from depends on - the implementation of the port malloc function. */ - pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); - - 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 = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - if( pxNewTCB->pxStack == NULL ) + #if ( configUSE_MUTEXES == 1 ) { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; + 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 { - /* Just to help debugging. */ - ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) ); + pxTaskStatus->eCurrentState = eTaskGetState( xTask ); + } + + /* Obtaining the stack space takes some time, so the xGetFreeStackSpace + parameter is provided to allow it to be skipped. */ + if( xGetFreeStackSpace != pdFALSE ) + { + #if ( portSTACK_GROWTH > 0 ) + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); + } + #else + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); + } + #endif + } + else + { + pxTaskStatus->usStackHighWaterMark = 0; } } - return pxNewTCB; -} +#endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) + static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned portBASE_TYPE uxTask = 0; + volatile TCB_t *pxNextTCB, *pxFirstTCB; + UBaseType_t uxTask = 0; - if( listCURRENT_LIST_LENGTH( pxList ) > ( unsigned portBASE_TYPE ) 0 ) + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - /* Populate an xTaskStatusType structure within the + /* Populate an TaskStatus_t structure within the pxTaskStatusArray array for each task that is referenced from - pxList. See the definition of xTaskStatusType in task.h for the - meaning of each xTaskStatusType structure member. */ + pxList. See the definition of TaskStatus_t in task.h for the + meaning of each TaskStatus_t structure member. */ do { listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - - pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB; - pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] ); - pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber; - pxTaskStatusArray[ uxTask ].eCurrentState = eState; - pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority; - - #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 ) - { - ppxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); - } - #else - { - pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); - } - #endif - + vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); uxTask++; - } while( pxNextTCB != pxFirstTCB ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } return uxTask; } @@ -2523,19 +3530,19 @@ tskTCB *pxNewTCB; #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) { - register unsigned short usCount = 0U; + uint32_t ulCount = 0U; - while( *pucStackByte == tskSTACK_FILL_BYTE ) + while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) { pucStackByte -= portSTACK_GROWTH; - usCount++; + ulCount++; } - usCount /= sizeof( portSTACK_TYPE ); + ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ - return usCount; + return ( uint16_t ) ulCount; } #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ @@ -2543,25 +3550,25 @@ tskTCB *pxNewTCB; #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) + UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) { - tskTCB *pxTCB; - unsigned char *pcEndOfStack; - unsigned portBASE_TYPE uxReturn; + TCB_t *pxTCB; + uint8_t *pucEndOfStack; + UBaseType_t uxReturn; pxTCB = prvGetTCBFromHandle( xTask ); #if portSTACK_GROWTH < 0 { - pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; } #else { - pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; } #endif - uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack ); + uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); return uxReturn; } @@ -2571,27 +3578,89 @@ tskTCB *pxNewTCB; #if ( INCLUDE_vTaskDelete == 1 ) - static void prvDeleteTCB( tskTCB *pxTCB ) + static void prvDeleteTCB( TCB_t *pxTCB ) { /* This call is required specifically for the TriCore port. It must be above the vPortFree() calls. The call is also used by ports/demos that want to allocate and clean RAM statically. */ portCLEAN_UP_TCB( pxTCB ); - /* Free up the memory allocated by the scheduler for the task. It is up to - the task to free any memory allocated at the application level. */ - vPortFreeAligned( pxTCB->pxStack ); - vPortFree( pxTCB ); + /* Free up the memory allocated by the scheduler for the task. It is up + to the task to free any memory allocated at the application level. */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) + { + /* 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 ) + { + /* Both the stack and TCB were allocated dynamically, so both + must be freed. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + { + /* Only the stack was statically allocated, so the TCB is the + only memory that must be freed. */ + vPortFree( pxTCB ); + } + else + { + /* Neither the stack nor the TCB were allocated dynamically, so + nothing needs to be freed. */ + configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ +static void prvResetNextTaskUnblockTime( void ) +{ +TCB_t *pxTCB; + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The new current delayed list is empty. Set xNextTaskUnblockTime to + the maximum possible value so it is extremely unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass until + there is an item in the delayed list. */ + xNextTaskUnblockTime = portMAX_DELAY; + } + else + { + /* The new current 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 should be removed + from the Blocked state. */ + ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) ); + } +} +/*-----------------------------------------------------------*/ + #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) - xTaskHandle xTaskGetCurrentTaskHandle( void ) + TaskHandle_t xTaskGetCurrentTaskHandle( void ) { - xTaskHandle xReturn; + TaskHandle_t xReturn; /* A critical section is not required as this is not called from an interrupt and the current TCB will always be the same for any @@ -2606,9 +3675,9 @@ tskTCB *pxNewTCB; #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - portBASE_TYPE xTaskGetSchedulerState( void ) + BaseType_t xTaskGetSchedulerState( void ) { - portBASE_TYPE xReturn; + BaseType_t xReturn; if( xSchedulerRunning == pdFALSE ) { @@ -2616,7 +3685,7 @@ tskTCB *pxNewTCB; } else { - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) { xReturn = taskSCHEDULER_RUNNING; } @@ -2634,27 +3703,43 @@ tskTCB *pxNewTCB; #if ( configUSE_MUTEXES == 1 ) - void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) + void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; /* If the mutex was given back by an interrupt while the queue was locked then the mutex holder might now be NULL. */ if( pxMutexHolder != NULL ) { + /* If the holder of the mutex has a priority below the priority of + the task attempting to obtain the mutex then it will temporarily + inherit the priority of the task attempting to obtain the mutex. */ if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) { - /* Adjust the mutex holder state to account for its new priority. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - /* 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 ) + /* Adjust the mutex holder state to account for its new + priority. Only reset the event list item value if the value is + not being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) { - if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* 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->xStateListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) { taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } /* Inherit the priority before being moved into the new list. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; @@ -2668,6 +3753,14 @@ tskTCB *pxNewTCB; traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } @@ -2676,29 +3769,80 @@ tskTCB *pxNewTCB; #if ( configUSE_MUTEXES == 1 ) - void IRAM vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) + BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + BaseType_t xReturn = pdFALSE; if( pxMutexHolder != NULL ) { + /* A task can only have an inherited priority if it holds the mutex. + If the mutex is held by a task then it cannot be given from an + interrupt, and if a mutex is given by the holding task then it must + be the running state task. */ + configASSERT( pxTCB == pxCurrentTCB ); + + configASSERT( pxTCB->uxMutexesHeld ); + ( pxTCB->uxMutexesHeld )--; + + /* Has the holder of the mutex inherited the priority of another + task? */ if( pxTCB->uxPriority != pxTCB->uxBasePriority ) { - /* We must be the running task to be able to give the mutex back. - Remove ourselves from the ready list we currently appear in. */ - if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + /* Only disinherit if no other mutexes are held. */ + if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) { - taskRESET_READY_PRIORITY( pxTCB->uxPriority ); - } + /* A task can only have an inherited priority if it holds + the mutex. If the mutex is held by a task then it cannot be + 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->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Disinherit the priority before adding the task into the new - ready list. */ - traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); - pxTCB->uxPriority = pxTCB->uxBasePriority; - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - prvAddTaskToReadyList( pxTCB ); + /* Disinherit the priority before adding the task into the + new ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; + + /* Reset the event list item value. It cannot be in use for + any other purpose if this task is running, and it must be + running to give back the mutex. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + prvAddTaskToReadyList( pxTCB ); + + /* Return true to indicate that a context switch is required. + This is only actually required in the corner case whereby + multiple mutexes were held and the mutexes were given back + in an order different to that in which they were taken. + If a context switch did not occur when the first mutex was + returned, even if a task was waiting on it, then a context + switch should occur when the last mutex is returned whether + a task is waiting on it or not. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; } #endif /* configUSE_MUTEXES */ @@ -2713,6 +3857,21 @@ tskTCB *pxNewTCB; if( xSchedulerRunning != pdFALSE ) { ( pxCurrentTCB->uxCriticalNesting )++; + + /* This is not the interrupt safe version of the enter critical + function so assert() if it is being called from an interrupt + context. Only API functions that end in "FromISR" can be used in an + interrupt. Only assert if the critical nesting count is 1 to + protect against recursive calls if the assert function also uses a + critical section. */ + if( pxCurrentTCB->uxCriticalNesting == 1 ) + { + portASSERT_IF_IN_ISR(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } @@ -2733,19 +3892,57 @@ tskTCB *pxNewTCB; { portENABLE_INTERRUPTS(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } #endif /* portCRITICAL_NESTING_IN_TCB */ /*-----------------------------------------------------------*/ -#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - void vTaskList( signed char *pcWriteBuffer ) + static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) { - xTaskStatusType *pxTaskStatusArray; - volatile unsigned portBASE_TYPE uxArraySize, x; + size_t x; + + /* Start by copying the entire string. */ + strcpy( pcBuffer, pcTaskName ); + + /* Pad the end of the string with spaces to ensure columns line up when + printed out. */ + for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) + { + pcBuffer[ x ] = ' '; + } + + /* Terminate. */ + pcBuffer[ x ] = 0x00; + + /* Return the new end of string. */ + return &( pcBuffer[ x ] ); + } + +#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + void vTaskList( char * pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; char cStatus; /* @@ -2780,8 +3977,10 @@ tskTCB *pxNewTCB; function is executing. */ uxArraySize = uxCurrentNumberOfTasks; - /* Allocate an array index for each task. */ - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); + /* 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 ) { @@ -2793,43 +3992,59 @@ tskTCB *pxNewTCB; { switch( pxTaskStatusArray[ x ].eCurrentState ) { - case eReady: cStatus = tskREADY_CHAR; - break; + case eReady: cStatus = tskREADY_CHAR; + break; - case eBlocked: cStatus = tskBLOCKED_CHAR; - break; + case eBlocked: cStatus = tskBLOCKED_CHAR; + break; - case eSuspended: cStatus = tskSUSPENDED_CHAR; - break; + case eSuspended: cStatus = tskSUSPENDED_CHAR; + break; - case eDeleted: cStatus = tskDELETED_CHAR; - break; + case eDeleted: cStatus = tskDELETED_CHAR; + break; - default: /* Should not get here, but it is included - to prevent static checking errors. */ - cStatus = 0x00; - break; + default: /* Should not get here, but it is included + to prevent static checking errors. */ + cStatus = 0x00; + break; } - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); - pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); + /* Write the task name to the string, padding with spaces so it + can be printed in tabular form more easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + + /* Write the rest of the string. */ + sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); + 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 + { + mtCOVERAGE_TEST_MARKER(); + } } -#endif /* configUSE_TRACE_FACILITY */ +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ /*----------------------------------------------------------*/ -#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) + void vTaskGetRunTimeStats( char *pcWriteBuffer ) { - xTaskStatusType *pxTaskStatusArray; - volatile unsigned portBASE_TYPE uxArraySize, x; - unsigned long ulTotalTime, ulStatsAsPercentage; + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + uint32_t ulTotalTime, ulStatsAsPercentage; + + #if( configUSE_TRACE_FACILITY != 1 ) + { + #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). + } + #endif /* * PLEASE NOTE: @@ -2863,8 +4078,10 @@ tskTCB *pxNewTCB; function is executing. */ uxArraySize = uxCurrentNumberOfTasks; - /* Allocate an array index for each task. */ - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); + /* 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 ) { @@ -2885,17 +4102,22 @@ tskTCB *pxNewTCB; ulTotalRunTimeDiv100 has already been divided by 100. */ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; + /* Write the task name to the string, padding with + spaces so it can be printed in tabular form more + easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + if( ulStatsAsPercentage > 0UL ) { #ifdef portLU_PRINTF_SPECIFIER_REQUIRED { - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); } #else { /* sizeof( int ) == sizeof( long ) so a smaller printf() library can be used. */ - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); + sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); } #endif } @@ -2905,27 +4127,681 @@ tskTCB *pxNewTCB; consumed less than 1% of the total run time. */ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED { - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); + sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); } #else { /* sizeof( int ) == sizeof( long ) so a smaller printf() library can be used. */ - sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); + sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); } #endif } - pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); + pcWriteBuffer += strlen( pcWriteBuffer ); } } + else + { + 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 + { + mtCOVERAGE_TEST_MARKER(); + } } -#endif /* configGENERATE_RUN_TIME_STATS */ +#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ +/*-----------------------------------------------------------*/ + +TickType_t uxTaskResetEventItemValue( void ) +{ +TickType_t uxReturn; + + uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) ); + + /* Reset the event list item to its normal value - so it can be used with + queues and semaphores. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void *pvTaskIncrementMutexHeldCount( void ) + { + /* If xSemaphoreCreateMutex() is called before any tasks have been created + then pxCurrentTCB will be NULL. */ + if( pxCurrentTCB != NULL ) + { + ( pxCurrentTCB->uxMutexesHeld )++; + } + + return pxCurrentTCB; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) + { + uint32_t ulReturn; + + taskENTER_CRITICAL(); + { + /* Only block if the notification count is not already non-zero. */ + if( pxCurrentTCB->ulNotifiedValue == 0UL ) + { + /* Mark this task as waiting for a notification. */ + pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; + + if( xTicksToWait > ( TickType_t ) 0 ) + { + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + traceTASK_NOTIFY_TAKE_BLOCK(); + + /* All ports are written to allow a yield in a critical + section (some will yield immediately, others wait until the + critical section exits) - but it is not something that + application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + traceTASK_NOTIFY_TAKE(); + ulReturn = pxCurrentTCB->ulNotifiedValue; + + if( ulReturn != 0UL ) + { + if( xClearCountOnExit != pdFALSE ) + { + pxCurrentTCB->ulNotifiedValue = 0UL; + } + else + { + pxCurrentTCB->ulNotifiedValue = ulReturn - 1; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + } + taskEXIT_CRITICAL(); + + return ulReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + /* Only block if a notification is not already pending. */ + 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 + clear the value to zero. */ + pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry; + + /* Mark this task as waiting for a notification. */ + pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; + + if( xTicksToWait > ( TickType_t ) 0 ) + { + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + traceTASK_NOTIFY_WAIT_BLOCK(); + + /* All ports are written to allow a yield in a critical + section (some will yield immediately, others wait until the + critical section exits) - but it is not something that + application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + traceTASK_NOTIFY_WAIT(); + + if( pulNotificationValue != NULL ) + { + /* Output the current notification value, which may or may not + have changed. */ + *pulNotificationValue = pxCurrentTCB->ulNotifiedValue; + } + + /* 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->ucNotifyState == taskWAITING_NOTIFICATION ) + { + /* A notification was not received. */ + xReturn = pdFALSE; + } + else + { + /* A notification was already pending or a notification was + received while the task was waiting. */ + pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit; + xReturn = pdTRUE; + } + + pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) + { + TCB_t * pxTCB; + BaseType_t xReturn = pdPASS; + uint8_t ucOriginalNotifyState; + + configASSERT( xTaskToNotify ); + pxTCB = ( TCB_t * ) xTaskToNotify; + + taskENTER_CRITICAL(); + { + if( pulPreviousNotificationValue != NULL ) + { + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + } + + ucOriginalNotifyState = pxTCB->ucNotifyState; + + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + + switch( eAction ) + { + case eSetBits : + pxTCB->ulNotifiedValue |= ulValue; + break; + + case eIncrement : + ( pxTCB->ulNotifiedValue )++; + break; + + case eSetValueWithOverwrite : + pxTCB->ulNotifiedValue = ulValue; + break; + + case eSetValueWithoutOverwrite : + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) + { + pxTCB->ulNotifiedValue = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } + break; + + case eNoAction: + /* The task is being notified without its notify value being + updated. */ + break; + } + + traceTASK_NOTIFY(); + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked waiting for a notification then + xNextTaskUnblockTime might be set to the blocked task's time + out time. If the task is unblocked for a reason other than + a timeout xNextTaskUnblockTime is normally left unchanged, + because it will automatically get reset to a new value when + the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter + sleep mode at the earliest possible time - so reset + xNextTaskUnblockTime here to ensure it is updated at the + earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + BaseType_t xReturn = pdPASS; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( xTaskToNotify ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + pxTCB = ( TCB_t * ) xTaskToNotify; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( pulPreviousNotificationValue != NULL ) + { + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + } + + ucOriginalNotifyState = pxTCB->ucNotifyState; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + + switch( eAction ) + { + case eSetBits : + pxTCB->ulNotifiedValue |= ulValue; + break; + + case eIncrement : + ( pxTCB->ulNotifiedValue )++; + break; + + case eSetValueWithOverwrite : + pxTCB->ulNotifiedValue = ulValue; + break; + + case eSetValueWithoutOverwrite : + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) + { + pxTCB->ulNotifiedValue = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } + break; + + case eNoAction : + /* The task is being notified without its notify value being + updated. */ + break; + } + + traceTASK_NOTIFY_FROM_ISR(); + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + 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->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *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 + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( xTaskToNotify ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + pxTCB = ( TCB_t * ) xTaskToNotify; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + ucOriginalNotifyState = pxTCB->ucNotifyState; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + + /* 'Giving' is equivalent to incrementing a count in a counting + semaphore. */ + ( pxTCB->ulNotifiedValue )++; + + traceTASK_NOTIFY_GIVE_FROM_ISR(); + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + 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->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *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 + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ + +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + BaseType_t xReturn; + + /* If null is passed in here then it is the calling task that is having + its notification state cleared. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + taskENTER_CRITICAL(); + { + if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) + { + pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ +static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) +{ +TickType_t xTimeToWake; +const TickType_t xConstTickCount = xTickCount; + + #if( INCLUDE_xTaskAbortDelay == 1 ) + { + /* About to enter a delayed list, so ensure the ucDelayAborted flag is + reset to pdFALSE so it can be detected as having been set to pdTRUE + when the task leaves the Blocked state. */ + pxCurrentTCB->ucDelayAborted = pdFALSE; + } + #endif + + /* Remove the task from the ready list before adding it to the blocked list + as the same list item is used for both lists. */ + if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure it is not woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + kernel will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); + + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow + list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list + is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + + /* If the task entering the blocked state was placed at the + head of the list of blocked tasks then xNextTaskUnblockTime + needs to be updated too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the kernel + will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); + + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */ + ( void ) xCanBlockIndefinitely; + } + #endif /* INCLUDE_vTaskSuspend */ +} + + +#ifdef FREERTOS_MODULE_TEST + #include "tasks_test_access_functions.h" +#endif diff --git a/FreeRTOS/Source/timers.c b/FreeRTOS/Source/timers.c index 783a461..d4a821a 100644 --- a/FreeRTOS/Source/timers.c +++ b/FreeRTOS/Source/timers.c @@ -1,59 +1,64 @@ /* - FreeRTOS V7.5.2 - Copyright (C) 2013 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. - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - 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. + 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. + *************************************************************************** + >>! 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 from the following + FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html - 1 tab == 4 spaces! - *************************************************************************** * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * + * 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. * * * - * http://www.FreeRTOS.org/FAQHelp.html * + * 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 - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. + 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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. + 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 @@ -75,6 +80,10 @@ task.h is included from an application file. */ #include "queue.h" #include "timers.h" +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. +#endif + /* Lint e961 and e750 are suppressed as a MISRA exception justified because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the header files above, but not in this file, in order to generate the correct @@ -89,52 +98,95 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ #if ( configUSE_TIMERS == 1 ) /* Misc definitions. */ -#define tmrNO_DELAY ( portTickType ) 0U +#define tmrNO_DELAY ( TickType_t ) 0U /* The definition of the timers themselves. */ typedef struct tmrTimerControl { - const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ - xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ - portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ - unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ + const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ + UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */ void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ - tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + #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 definition of messages that can be sent and received on the timer -queue. */ +/* The old xTIMER name is maintained above then typedefed to the new Timer_t +name below to enable the use of older kernel aware debuggers. */ +typedef xTIMER Timer_t; + +/* The definition of messages that can be sent and received on the timer queue. +Two types of message can be queued - messages that manipulate a software timer, +and messages that request the execution of a non-timer related callback. The +two message types are defined in two separate structures, xTimerParametersType +and xCallbackParametersType respectively. */ +typedef struct tmrTimerParameters +{ + TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ +} TimerParameter_t; + + +typedef struct tmrCallbackParameters +{ + PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ + void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */ + uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ +} CallbackParameters_t; + +/* The structure that contains the two message types, along with an identifier +that is used to determine which message type is valid. */ typedef struct tmrTimerQueueMessage { - portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */ - portTickType xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ - xTIMER * pxTimer; /*<< The timer to which the command will be applied. */ -} xTIMER_MESSAGE; + BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ + union + { + TimerParameter_t xTimerParameters; + + /* Don't include xCallbackParameters if it is not going to be used as + it makes the structure (and therefore the timer queue) larger. */ + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + CallbackParameters_t xCallbackParameters; + #endif /* INCLUDE_xTimerPendFunctionCall */ + } u; +} DaemonTaskMessage_t; /*lint -e956 A manual analysis and inspection has been used to determine which static variables must be declared volatile. */ /* The list in which active timers are stored. Timers are referenced in expire time order, with the nearest expiry time at the front of the list. Only the -timer service task is allowed to access xActiveTimerList. */ -PRIVILEGED_DATA static xList xActiveTimerList1; -PRIVILEGED_DATA static xList xActiveTimerList2; -PRIVILEGED_DATA static xList *pxCurrentTimerList; -PRIVILEGED_DATA static xList *pxOverflowTimerList; +timer service task is allowed to access these lists. */ +PRIVILEGED_DATA static List_t xActiveTimerList1; +PRIVILEGED_DATA static List_t xActiveTimerList2; +PRIVILEGED_DATA static List_t *pxCurrentTimerList; +PRIVILEGED_DATA static List_t *pxOverflowTimerList; /* A queue that is used to send commands to the timer service task. */ -PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL; - -#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) - - PRIVILEGED_DATA static xTaskHandle xTimerTaskHandle = NULL; - -#endif +PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; +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. @@ -152,31 +204,31 @@ static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; * Called by the timer service task to interpret and process a command it * received on the timer queue. */ -static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; +static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; /* * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, * depending on if the expire time causes a timer counter overflow. */ -static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION; +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; /* * An active timer has reached its expire time. Reload the timer if it is an * auto reload timer, then call its callback. */ -static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION; +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; /* * The tick count has overflowed. Switch the timer lists after ensuring the * current timer list does not still reference some timers. */ -static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION; +static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; /* * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE * if a tick count overflow occurred since prvSampleTimeNow() was last called. */ -static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; /* * If the timer list contains any active timers then return the expire time of @@ -184,19 +236,29 @@ static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) * timer list does not contain any timers then return 0 and set *pxListWasEmpty * to pdTRUE. */ -static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVILEGED_FUNCTION; +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; /* * If a timer has expired, process it. Otherwise, block the timer service task * until either a timer does expire or a command is received. */ -static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION; +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. */ /*-----------------------------------------------------------*/ -portBASE_TYPE xTimerCreateTimerTask( void ) +BaseType_t xTimerCreateTimerTask( void ) { -portBASE_TYPE xReturn = pdFAIL; +BaseType_t xReturn = pdFAIL; /* This function is called when the scheduler is started if configUSE_TIMERS is set to 1. Check that the infrastructure used by the @@ -206,18 +268,40 @@ portBASE_TYPE 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, ( const signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) 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, ( const signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) 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 + { + mtCOVERAGE_TEST_MARKER(); } configASSERT( xReturn ); @@ -225,49 +309,117 @@ portBASE_TYPE xReturn = pdFAIL; } /*-----------------------------------------------------------*/ -xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) -{ -xTIMER *pxNewTimer; +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - /* Allocate the timer structure. */ - if( xTimerPeriodInTicks == ( portTickType ) 0U ) + 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. */ { - pxNewTimer = NULL; - configASSERT( ( xTimerPeriodInTicks > 0 ) ); - } - else - { - pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); + 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; } - return ( xTimerHandle ) 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 ) ); + + 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 ); + } } /*-----------------------------------------------------------*/ -portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) { -portBASE_TYPE xReturn = pdFAIL; -xTIMER_MESSAGE xMessage; +BaseType_t xReturn = pdFAIL; +DaemonTaskMessage_t xMessage; + + configASSERT( xTimer ); /* Send a message to the timer service task to perform a particular action on a particular timer definition. */ @@ -275,14 +427,14 @@ xTIMER_MESSAGE xMessage; { /* Send a command to the timer service task to start the xTimer timer. */ xMessage.xMessageID = xCommandID; - xMessage.xMessageValue = xOptionalValue; - xMessage.pxTimer = ( xTIMER * ) xTimer; + xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; + xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer; - if( pxHigherPriorityTaskWoken == NULL ) + if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) { if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) { - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime ); + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); } else { @@ -296,68 +448,113 @@ xTIMER_MESSAGE xMessage; traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } return xReturn; } /*-----------------------------------------------------------*/ -#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) - - xTaskHandle 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; +} /*-----------------------------------------------------------*/ -static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) +TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) { -xTIMER *pxTimer; -portBASE_TYPE xResult; +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; + + configASSERT( xTimer ); + return pxTimer->pcTimerName; +} +/*-----------------------------------------------------------*/ + +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) +{ +BaseType_t xResult; +Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /* Remove the timer from the list of active timers. A check has already been performed to ensure the list is not empty. */ - pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); traceTIMER_EXPIRED( pxTimer ); /* If the timer is an auto reload timer then calculate the next expiry time and re-insert the timer in the list of active timers. */ - if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) { - /* This is the only time a 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, even if a command to - switch lists due to a tick count overflow is already waiting in - the timer queue. */ - if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) + /* 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 ) != pdFALSE ) { /* The timer expired before it was added to the active timer list. Reload it now. */ - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); configASSERT( xResult ); ( void ) xResult; } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } /* Call the timer callback. */ - pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); } /*-----------------------------------------------------------*/ static void prvTimerTask( void *pvParameters ) { -portTickType xNextExpireTime; -portBASE_TYPE xListWasEmpty; +TickType_t xNextExpireTime; +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, @@ -374,10 +571,10 @@ portBASE_TYPE xListWasEmpty; } /*-----------------------------------------------------------*/ -static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) { -portTickType xTimeNow; -portBASE_TYPE xTimerListsWereSwitched; +TickType_t xTimeNow; +BaseType_t xTimerListsWereSwitched; vTaskSuspendAll(); { @@ -385,7 +582,7 @@ portBASE_TYPE xTimerListsWereSwitched; has expired or not. If obtaining the time causes the lists to switch then don't process this timer as any timers that remained in the list when the lists were switched will have been processed within the - prvSampelTimeNow() function. */ + prvSampleTimeNow() function. */ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); if( xTimerListsWereSwitched == pdFALSE ) { @@ -403,16 +600,27 @@ portBASE_TYPE xTimerListsWereSwitched; received - whichever comes first. The following line cannot be reached unless xNextExpireTime > xTimeNow, except in the case when the current timer list is empty. */ - vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) ); + if( xListWasEmpty != pdFALSE ) + { + /* The current timer list is empty - is the overflow list + also empty? */ + xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); + } + + vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); if( xTaskResumeAll() == pdFALSE ) { - /* Yield to wait for either a command to arrive, or the block time - to expire. If a command arrived between the critical section being - exited and this yield then the yield will not cause the task - to block. */ + /* Yield to wait for either a command to arrive, or the + block time to expire. If a command arrived between the + critical section being exited and this yield then the yield + will not cause the task to block. */ portYIELD_WITHIN_API(); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } } else @@ -423,9 +631,9 @@ portBASE_TYPE xTimerListsWereSwitched; } /*-----------------------------------------------------------*/ -static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) { -portTickType xNextExpireTime; +TickType_t xNextExpireTime; /* Timers are listed in expiry time order, with the head of the list referencing the task that will expire first. Obtain the time at which @@ -442,23 +650,23 @@ portTickType xNextExpireTime; else { /* Ensure the task unblocks when the tick count rolls over. */ - xNextExpireTime = ( portTickType ) 0U; + xNextExpireTime = ( TickType_t ) 0U; } return xNextExpireTime; } /*-----------------------------------------------------------*/ -static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) { -portTickType xTimeNow; -PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e956 Variable is only accessible to one task. */ +TickType_t xTimeNow; +PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ xTimeNow = xTaskGetTickCount(); if( xTimeNow < xLastTime ) { - prvSwitchTimerLists( xLastTime ); + prvSwitchTimerLists(); *pxTimerListsWereSwitched = pdTRUE; } else @@ -472,9 +680,9 @@ PRIVILEGED_DATA static portTickType xLastTime = ( portTickType ) 0U; /*lint !e95 } /*-----------------------------------------------------------*/ -static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) { -portBASE_TYPE xProcessTimerNow = pdFALSE; +BaseType_t xProcessTimerNow = pdFALSE; listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); @@ -483,7 +691,7 @@ portBASE_TYPE 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. */ @@ -515,84 +723,157 @@ portBASE_TYPE xProcessTimerNow = pdFALSE; static void prvProcessReceivedCommands( void ) { -xTIMER_MESSAGE xMessage; -xTIMER *pxTimer; -portBASE_TYPE xTimerListsWereSwitched, xResult; -portTickType xTimeNow; +DaemonTaskMessage_t xMessage; +Timer_t *pxTimer; +BaseType_t xTimerListsWereSwitched, xResult; +TickType_t xTimeNow; while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ { - pxTimer = xMessage.pxTimer; - - if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) { - /* The timer is in a list, remove it. */ - ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + /* Negative commands are pended function calls rather than timer + commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) + { + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + + /* The timer uses the xCallbackParameters member to request a + callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); + + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + #endif /* INCLUDE_xTimerPendFunctionCall */ - traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue ); - - /* In this case the xTimerListsWereSwitched parameter is not used, but - it must be present in the function call. prvSampleTimeNow() must be - called after the message is received from xTimerQueue so there is no - possibility of a higher priority task adding a message to the message - queue with a time that is ahead of the timer daemon task (because it - pre-empted the timer daemon task after the xTimeNow value was set). */ - xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - - switch( xMessage.xMessageID ) + /* Commands that are positive are timer commands rather than pended + function calls. */ + if( xMessage.xMessageID >= ( BaseType_t ) 0 ) { - case tmrCOMMAND_START : - /* Start or restart a timer. */ - if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE ) - { - /* The timer expired before it was added to the active timer - list. Process it now. */ - pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); + /* The messages uses the xTimerParameters member to work on a + software timer. */ + pxTimer = xMessage.u.xTimerParameters.pxTimer; - if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) + { + /* The timer is in a list, remove it. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); + + /* In this case the xTimerListsWereSwitched parameter is not used, but + it must be present in the function call. prvSampleTimeNow() must be + called after the message is received from xTimerQueue so there is no + possibility of a higher priority task adding a message to the message + queue with a time that is ahead of the timer daemon task (because it + pre-empted the timer daemon task after the xTimeNow value was set). */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + + switch( xMessage.xMessageID ) + { + case tmrCOMMAND_START : + case tmrCOMMAND_START_FROM_ISR : + case tmrCOMMAND_RESET : + 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 ) != pdFALSE ) { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; + /* The timer expired before it was added to the active + timer list. Process it now. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + traceTIMER_EXPIRED( pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } - } - break; + else + { + mtCOVERAGE_TEST_MARKER(); + } + break; - case tmrCOMMAND_STOP : - /* The timer has already been removed from the active list. - There is nothing to do here. */ - break; + case tmrCOMMAND_STOP : + case tmrCOMMAND_STOP_FROM_ISR : + /* The timer has already been removed from the active list. + There is nothing to do here. */ + break; - case tmrCOMMAND_CHANGE_PERIOD : - pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue; - configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); - ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); - break; + case tmrCOMMAND_CHANGE_PERIOD : + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR : + pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; + configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); - case tmrCOMMAND_DELETE : - /* The timer has already been removed from the active list, - just free up the memory. */ - vPortFree( pxTimer ); - break; + /* 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; - default : - /* Don't expect to get here. */ - break; + case tmrCOMMAND_DELETE : + /* The timer has already been removed from the active list, + 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 : + /* Don't expect to get here. */ + break; + } } } } /*-----------------------------------------------------------*/ -static void prvSwitchTimerLists( portTickType xLastTime ) +static void prvSwitchTimerLists( void ) { -portTickType xNextExpireTime, xReloadTime; -xList *pxTemp; -xTIMER *pxTimer; -portBASE_TYPE xResult; - - /* Remove compiler warnings if configASSERT() is not defined. */ - ( void ) xLastTime; +TickType_t xNextExpireTime, xReloadTime; +List_t *pxTemp; +Timer_t *pxTimer; +BaseType_t xResult; /* The tick count has overflowed. The timer lists must be switched. If there are any timers still referenced from the current timer list @@ -603,15 +884,16 @@ portBASE_TYPE xResult; xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); /* Remove the timer from the list. */ - pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); /* Execute its callback, then send a command to restart the timer if it is an auto-reload timer. It cannot be restarted here as the lists have not yet been switched. */ - pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); - if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) { /* Calculate the reload value, and if the reload value results in the timer going into the same timer list then it has already expired @@ -628,11 +910,15 @@ portBASE_TYPE xResult; } else { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); configASSERT( xResult ); ( void ) xResult; } } + else + { + mtCOVERAGE_TEST_MARKER(); + } } pxTemp = pxCurrentTimerList; @@ -654,17 +940,50 @@ static void prvCheckForValidListAndQueue( void ) vListInitialise( &xActiveTimerList2 ); pxCurrentTimerList = &xActiveTimerList1; pxOverflowTimerList = &xActiveTimerList2; - xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) ); + + #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 ) + { + if( xTimerQueue != NULL ) + { + vQueueAddToRegistry( xTimerQueue, "TmrQ" ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configQUEUE_REGISTRY_SIZE */ + } + else + { + mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ -portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) { -portBASE_TYPE xTimerIsInActiveList; -xTIMER *pxTimer = ( xTIMER * ) xTimer; +BaseType_t xTimerIsInActiveList; +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + configASSERT( xTimer ); /* Is the timer in the list of active timers? */ taskENTER_CRITICAL(); @@ -672,22 +991,98 @@ xTIMER *pxTimer = ( xTIMER * ) xTimer; /* Checking to see if it is in the NULL list in effect checks to see if it is referenced from either the current or the overflow timer lists in one go, but the logic has to be reversed, hence the '!'. */ - xTimerIsInActiveList = !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); + xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); } taskEXIT_CRITICAL(); return xTimerIsInActiveList; +} /*lint !e818 Can't be pointer to const due to the typedef. */ +/*-----------------------------------------------------------*/ + +void *pvTimerGetTimerID( const TimerHandle_t xTimer ) +{ +Timer_t * const pxTimer = ( Timer_t * ) xTimer; +void *pvReturn; + + configASSERT( xTimer ); + + taskENTER_CRITICAL(); + { + pvReturn = pxTimer->pvTimerID; + } + taskEXIT_CRITICAL(); + + return pvReturn; } /*-----------------------------------------------------------*/ -void *pvTimerGetTimerID( xTimerHandle xTimer ) +void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) { -xTIMER *pxTimer = ( xTIMER * ) xTimer; +Timer_t * const pxTimer = ( Timer_t * ) xTimer; - return pxTimer->pvTimerID; + configASSERT( xTimer ); + + taskENTER_CRITICAL(); + { + pxTimer->pvTimerID = pvNewID; + } + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + + tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* This function can only be called after a timer has been created or + after the scheduler has been started because, until then, the timer + queue does not exist. */ + configASSERT( xTimerQueue ); + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + + tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + /* This entire source file will be skipped if the application is not configured to include software timer functionality. If you want to include software timer functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ diff --git a/README.md b/README.md index 50edf61..1fa76bc 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Current status is alpha quality, actively developed. AP STATION mode (ie wifi cl ## Open Source Components -* [FreeRTOS](http://www.freertos.org/) V7.5.2 +* [FreeRTOS](http://www.freertos.org/) V9.0.0 * [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v1.4.1, modified via the [esp-lwip project](https://github.com/kadamski/esp-lwip) by @kadamski. * [newlib](https://github.com/projectgus/newlib-xtensa) v2.2.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS. diff --git a/core/app_main.c b/core/app_main.c index ed78025..6662301 100644 --- a/core/app_main.c +++ b/core/app_main.c @@ -411,7 +411,7 @@ static __attribute__((noinline)) void user_start_phase2(void) { tcpip_init(NULL, NULL); sdk_wdt_init(); - xTaskCreate(sdk_user_init_task, (signed char *)"uiT", 1024, 0, 14, &sdk_xUserTaskHandle); + xTaskCreate(sdk_user_init_task, "uiT", 1024, 0, 14, &sdk_xUserTaskHandle); vTaskStartScheduler(); } diff --git a/examples/access_point/access_point.c b/examples/access_point/access_point.c index 5a41156..05e344a 100644 --- a/examples/access_point/access_point.c +++ b/examples/access_point/access_point.c @@ -52,7 +52,7 @@ void user_init(void) IP4_ADDR(&first_client_ip, 172, 16, 0, 2); dhcpserver_start(&first_client_ip, 4); - xTaskCreate(telnetTask, (signed char *)"telnetTask", 512, NULL, 2, NULL); + xTaskCreate(telnetTask, "telnetTask", 512, NULL, 2, NULL); } /* Telnet task listens on port 23, returns some status information and then closes diff --git a/examples/aws_iot/aws_iot.c b/examples/aws_iot/aws_iot.c index e6b0f35..8b26b99 100644 --- a/examples/aws_iot/aws_iot.c +++ b/examples/aws_iot/aws_iot.c @@ -274,7 +274,7 @@ void user_init(void) { gpio_write(GPIO_LED, 1); publish_queue = xQueueCreate(3, 16); - xTaskCreate(&wifi_task, (int8_t *) "wifi_task", 256, NULL, 2, NULL); - xTaskCreate(&beat_task, (int8_t *) "beat_task", 256, NULL, 2, NULL); - xTaskCreate(&mqtt_task, (int8_t *) "mqtt_task", 2048, NULL, 2, NULL); + xTaskCreate(&wifi_task, "wifi_task", 256, NULL, 2, NULL); + xTaskCreate(&beat_task, "beat_task", 256, NULL, 2, NULL); + xTaskCreate(&mqtt_task, "mqtt_task", 2048, NULL, 2, NULL); } diff --git a/examples/blink/blink.c b/examples/blink/blink.c index 1539b67..341ac08 100644 --- a/examples/blink/blink.c +++ b/examples/blink/blink.c @@ -54,6 +54,6 @@ void blinkenRegisterTask(void *pvParameters) void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(blinkenTask, (signed char *)"blinkenTask", 256, NULL, 2, NULL); - //xTaskCreate(blinkenRegisterTask, (signed char *)"blinkenRegisterTask", 256, NULL, 2, NULL); + xTaskCreate(blinkenTask, "blinkenTask", 256, NULL, 2, NULL); + //xTaskCreate(blinkenRegisterTask, "blinkenRegisterTask", 256, NULL, 2, NULL); } diff --git a/examples/bmp180_i2c/bmp180_i2c.c b/examples/bmp180_i2c/bmp180_i2c.c index 5aa63f7..d05aca8 100644 --- a/examples/bmp180_i2c/bmp180_i2c.c +++ b/examples/bmp180_i2c/bmp180_i2c.c @@ -113,10 +113,10 @@ void user_init(void) mainqueue = xQueueCreate(10, sizeof(my_event_t)); // Create user interface task - xTaskCreate(bmp180_task, (signed char *)"bmp180_task", 256, &mainqueue, 2, NULL); + xTaskCreate(bmp180_task, "bmp180_task", 256, &mainqueue, 2, NULL); // Create Timer (Trigger a measurement every second) - timerHandle = xTimerCreate((signed char *)"BMP180 Trigger", 1000/portTICK_RATE_MS, pdTRUE, NULL, bmp180_i2c_timer_cb); + timerHandle = xTimerCreate("BMP180 Trigger", 1000/portTICK_RATE_MS, pdTRUE, NULL, bmp180_i2c_timer_cb); if (timerHandle != NULL) { diff --git a/examples/bmp280/bmp280_example.c b/examples/bmp280/bmp280_example.c index 6621158..e80d6b0 100644 --- a/examples/bmp280/bmp280_example.c +++ b/examples/bmp280/bmp280_example.c @@ -106,8 +106,8 @@ void user_init(void) i2c_init(scl_pin, sda_pin); #ifdef MODE_FORCED - xTaskCreate(bmp280_task_forced, (signed char *)"bmp280_task", 256, NULL, 2, NULL); + xTaskCreate(bmp280_task_forced, "bmp280_task", 256, NULL, 2, NULL); #else - xTaskCreate(bmp280_task_normal, (signed char *)"bmp280_task", 256, NULL, 2, NULL); + xTaskCreate(bmp280_task_normal, "bmp280_task", 256, NULL, 2, NULL); #endif } diff --git a/examples/button/button.c b/examples/button/button.c index 0b0784d..7bebf81 100644 --- a/examples/button/button.c +++ b/examples/button/button.c @@ -79,6 +79,6 @@ void user_init(void) gpio_enable(gpio, GPIO_INPUT); tsqueue = xQueueCreate(2, sizeof(uint32_t)); - xTaskCreate(buttonIntTask, (signed char *)"buttonIntTask", 256, &tsqueue, 2, NULL); - xTaskCreate(buttonPollTask, (signed char*)"buttonPollTask", 256, NULL, 1, NULL); + xTaskCreate(buttonIntTask, "buttonIntTask", 256, &tsqueue, 2, NULL); + xTaskCreate(buttonPollTask, "buttonPollTask", 256, NULL, 1, NULL); } diff --git a/examples/dht_sensor/dht_sensor.c b/examples/dht_sensor/dht_sensor.c index 425d5c0..b031672 100644 --- a/examples/dht_sensor/dht_sensor.c +++ b/examples/dht_sensor/dht_sensor.c @@ -44,6 +44,6 @@ void dhtMeasurementTask(void *pvParameters) void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(dhtMeasurementTask, (signed char *)"dhtMeasurementTask", 256, NULL, 2, NULL); + xTaskCreate(dhtMeasurementTask, "dhtMeasurementTask", 256, NULL, 2, NULL); } diff --git a/examples/ds18b20_broadcaster/ds18b20_broadcaster.c b/examples/ds18b20_broadcaster/ds18b20_broadcaster.c index def94fd..e5bcfea 100644 --- a/examples/ds18b20_broadcaster/ds18b20_broadcaster.c +++ b/examples/ds18b20_broadcaster/ds18b20_broadcaster.c @@ -119,6 +119,6 @@ void user_init(void) sdk_wifi_set_opmode(STATION_MODE); sdk_wifi_station_set_config(&config); - xTaskCreate(&broadcast_temperature, (signed char *)"broadcast_temperature", 256, NULL, 2, NULL); + xTaskCreate(&broadcast_temperature, "broadcast_temperature", 256, NULL, 2, NULL); } diff --git a/examples/ds18b20_onewire/ds18b20_onewire.c b/examples/ds18b20_onewire/ds18b20_onewire.c index b9b7655..098f59f 100644 --- a/examples/ds18b20_onewire/ds18b20_onewire.c +++ b/examples/ds18b20_onewire/ds18b20_onewire.c @@ -73,6 +73,6 @@ void print_temperature(void *pvParameters) { void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(&print_temperature, (signed char *)"print_temperature", 256, NULL, 2, NULL); + xTaskCreate(&print_temperature, "print_temperature", 256, NULL, 2, NULL); } diff --git a/examples/ds3231_test/ds3231_test.c b/examples/ds3231_test/ds3231_test.c index 77fc167..858b0a0 100644 --- a/examples/ds3231_test/ds3231_test.c +++ b/examples/ds3231_test/ds3231_test.c @@ -37,5 +37,5 @@ void user_init(void) ds3231_Init(scl, sda); - xTaskCreate(task1, (signed char *)"tsk1", 256, NULL, 2, NULL); + xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL); } diff --git a/examples/experiments/timers/timers.c b/examples/experiments/timers/timers.c index d5a2f50..bc3aa2b 100644 --- a/examples/experiments/timers/timers.c +++ b/examples/experiments/timers/timers.c @@ -119,7 +119,7 @@ void frc2_handler(void) void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(timerRegTask, (signed char *)"timerRegTask", 1024, NULL, 2, NULL); + xTaskCreate(timerRegTask, "timerRegTask", 1024, NULL, 2, NULL); TIMER(0).CTRL = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256) | TIMER_CTRL_RELOAD; TIMER(0).LOAD = 0x200000; diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index ff6cab7..984a566 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -230,7 +230,7 @@ void user_init(void) test_sign_extension(); xTaskHandle taskHandle; - xTaskCreate(test_system_interaction, (signed char *)"interactionTask", 256, &taskHandle, 2, NULL); + xTaskCreate(test_system_interaction, "interactionTask", 256, &taskHandle, 2, NULL); } static volatile bool frc1_ran; diff --git a/examples/http_get/http_get.c b/examples/http_get/http_get.c index b90abdf..408d5b1 100644 --- a/examples/http_get/http_get.c +++ b/examples/http_get/http_get.c @@ -126,6 +126,6 @@ void user_init(void) sdk_wifi_set_opmode(STATION_MODE); sdk_wifi_station_set_config(&config); - xTaskCreate(&http_get_task, (signed char *)"get_task", 256, NULL, 2, NULL); + xTaskCreate(&http_get_task, "get_task", 256, NULL, 2, NULL); } diff --git a/examples/http_get_mbedtls/http_get_mbedtls.c b/examples/http_get_mbedtls/http_get_mbedtls.c index 7aad0e3..fa7c114 100644 --- a/examples/http_get_mbedtls/http_get_mbedtls.c +++ b/examples/http_get_mbedtls/http_get_mbedtls.c @@ -333,5 +333,5 @@ void user_init(void) sdk_wifi_set_opmode(STATION_MODE); sdk_wifi_station_set_config(&config); - xTaskCreate(&http_get_task, (signed char *)"get_task", 2048, NULL, 2, NULL); + xTaskCreate(&http_get_task, "get_task", 2048, NULL, 2, NULL); } diff --git a/examples/i2s_audio/i2s_audio_example.c b/examples/i2s_audio/i2s_audio_example.c index 78df426..ddb1387 100644 --- a/examples/i2s_audio/i2s_audio_example.c +++ b/examples/i2s_audio/i2s_audio_example.c @@ -193,5 +193,5 @@ void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(play_task, (signed char *)"test_task", 1024, NULL, 2, NULL); + xTaskCreate(play_task, "test_task", 1024, NULL, 2, NULL); } diff --git a/examples/json_jsmn_simple/json_jsmn_simple.c b/examples/json_jsmn_simple/json_jsmn_simple.c index 3a65ddf..4a01741 100644 --- a/examples/json_jsmn_simple/json_jsmn_simple.c +++ b/examples/json_jsmn_simple/json_jsmn_simple.c @@ -108,5 +108,5 @@ void user_init(void) { uart_set_baud(0, 115200); printf("SDK version:%s\n", sdk_system_get_sdk_version()); - xTaskCreate(json_test, (signed char *)"jsont", 1024, NULL, 2, NULL); + xTaskCreate(json_test, "jsont", 1024, NULL, 2, NULL); } diff --git a/examples/mqtt_client/mqtt_client.c b/examples/mqtt_client/mqtt_client.c index fe129fd..2b9e764 100644 --- a/examples/mqtt_client/mqtt_client.c +++ b/examples/mqtt_client/mqtt_client.c @@ -216,7 +216,7 @@ void user_init(void) vSemaphoreCreateBinary(wifi_alive); publish_queue = xQueueCreate(3, PUB_MSG_LEN); - xTaskCreate(&wifi_task, (int8_t *)"wifi_task", 256, NULL, 2, NULL); - xTaskCreate(&beat_task, (int8_t *)"beat_task", 256, NULL, 3, NULL); - xTaskCreate(&mqtt_task, (int8_t *)"mqtt_task", 1024, NULL, 4, NULL); + xTaskCreate(&wifi_task, "wifi_task", 256, NULL, 2, NULL); + xTaskCreate(&beat_task, "beat_task", 256, NULL, 3, NULL); + xTaskCreate(&mqtt_task, "mqtt_task", 1024, NULL, 4, NULL); } diff --git a/examples/ota_basic/ota_basic.c b/examples/ota_basic/ota_basic.c index c2050d5..5083539 100644 --- a/examples/ota_basic/ota_basic.c +++ b/examples/ota_basic/ota_basic.c @@ -138,5 +138,5 @@ void user_init(void) printf("Starting TFTP server..."); ota_tftp_init_server(TFTP_PORT); - xTaskCreate(&tftp_client_task, (signed char *)"tftp_client", 2048, NULL, 2, NULL); + xTaskCreate(&tftp_client_task, "tftp_client", 2048, NULL, 2, NULL); } diff --git a/examples/posix_fs/posix_fs_example.c b/examples/posix_fs/posix_fs_example.c index 2f5ad14..22877c4 100644 --- a/examples/posix_fs/posix_fs_example.c +++ b/examples/posix_fs/posix_fs_example.c @@ -51,5 +51,5 @@ void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(test_task, (signed char *)"test_task", 1024, NULL, 2, NULL); + xTaskCreate(test_task, "test_task", 1024, NULL, 2, NULL); } diff --git a/examples/pwm_test/pwm_test.c b/examples/pwm_test/pwm_test.c index d0372ac..1cd2bc5 100644 --- a/examples/pwm_test/pwm_test.c +++ b/examples/pwm_test/pwm_test.c @@ -46,5 +46,5 @@ void user_init(void) printf("pwm_start()\n"); pwm_start(); - xTaskCreate(task1, (signed char *)"tsk1", 256, NULL, 2, NULL); + xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL); } diff --git a/examples/simple/simple.c b/examples/simple/simple.c index d95a040..8134bb9 100644 --- a/examples/simple/simple.c +++ b/examples/simple/simple.c @@ -39,6 +39,6 @@ void user_init(void) uart_set_baud(0, 115200); printf("SDK version:%s\n", sdk_system_get_sdk_version()); mainqueue = xQueueCreate(10, sizeof(uint32_t)); - xTaskCreate(task1, (signed char *)"tsk1", 256, &mainqueue, 2, NULL); - xTaskCreate(task2, (signed char *)"tsk2", 256, &mainqueue, 2, NULL); + xTaskCreate(task1, "tsk1", 256, &mainqueue, 2, NULL); + xTaskCreate(task2, "tsk2", 256, &mainqueue, 2, NULL); } diff --git a/examples/simple_cplusplus/simple.cpp b/examples/simple_cplusplus/simple.cpp index dec286d..c74d54b 100644 --- a/examples/simple_cplusplus/simple.cpp +++ b/examples/simple_cplusplus/simple.cpp @@ -61,5 +61,5 @@ extern "C" void user_init(void) { uart_set_baud(0, 115200); printf("SDK version:%s\n", sdk_system_get_sdk_version()); - xTaskCreate(task1, (signed char *)"tsk1", 256, NULL, 2, NULL); + xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL); } diff --git a/examples/sntp/sntp_example.c b/examples/sntp/sntp_example.c index 242489b..a68365a 100644 --- a/examples/sntp/sntp_example.c +++ b/examples/sntp/sntp_example.c @@ -74,6 +74,6 @@ void user_init(void) sdk_wifi_set_opmode(STATION_MODE); sdk_wifi_station_set_config(&config); - xTaskCreate(sntp_tsk, (signed char *)"SNTP", 1024, NULL, 1, NULL); + xTaskCreate(sntp_tsk, "SNTP", 1024, NULL, 1, NULL); } diff --git a/examples/spiffs/spiffs_example.c b/examples/spiffs/spiffs_example.c index 4a907df..5252a92 100644 --- a/examples/spiffs/spiffs_example.c +++ b/examples/spiffs/spiffs_example.c @@ -114,5 +114,5 @@ void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(test_task, (signed char *)"test_task", 1024, NULL, 2, NULL); + xTaskCreate(test_task, "test_task", 1024, NULL, 2, NULL); } diff --git a/examples/sysparam_editor/sysparam_editor.c b/examples/sysparam_editor/sysparam_editor.c index f2244e1..a959348 100644 --- a/examples/sysparam_editor/sysparam_editor.c +++ b/examples/sysparam_editor/sysparam_editor.c @@ -242,5 +242,5 @@ void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(sysparam_editor_task, (signed char *)"sysparam_editor_task", 512, NULL, 2, NULL); + xTaskCreate(sysparam_editor_task, "sysparam_editor_task", 512, NULL, 2, NULL); } diff --git a/examples/tls_server/tls_server.c b/examples/tls_server/tls_server.c index 9030dc0..7959609 100644 --- a/examples/tls_server/tls_server.c +++ b/examples/tls_server/tls_server.c @@ -254,5 +254,5 @@ void user_init(void) sdk_wifi_set_opmode(STATION_MODE); sdk_wifi_station_set_config(&config); - xTaskCreate(&tls_server_task, (signed char *)"server_task", 2048, NULL, 2, NULL); + xTaskCreate(&tls_server_task, "server_task", 2048, NULL, 2, NULL); } diff --git a/examples/tsl2561/tsl2561_example.c b/examples/tsl2561/tsl2561_example.c index b6081b8..447f669 100644 --- a/examples/tsl2561/tsl2561_example.c +++ b/examples/tsl2561/tsl2561_example.c @@ -65,5 +65,5 @@ void user_init(void) uart_set_baud(0, 115200); i2c_init(SCL_PIN, SDA_PIN); - xTaskCreate(tsl2561MeasurementTask, (signed char *)"tsl2561MeasurementTask", 256, NULL, 2, NULL); + xTaskCreate(tsl2561MeasurementTask, "tsl2561MeasurementTask", 256, NULL, 2, NULL); } diff --git a/examples/ws2812_i2s/ws2812_i2s_colour_loop.c b/examples/ws2812_i2s/ws2812_i2s_colour_loop.c index 022f010..7644494 100644 --- a/examples/ws2812_i2s/ws2812_i2s_colour_loop.c +++ b/examples/ws2812_i2s/ws2812_i2s_colour_loop.c @@ -79,5 +79,5 @@ void user_init(void) { uart_set_baud(0, 115200); - xTaskCreate(&demo, (signed char *)"ws2812_i2s", 256, NULL, 10, NULL); + xTaskCreate(&demo, "ws2812_i2s", 256, NULL, 10, NULL); } diff --git a/examples/ws2812_rainbow/ws2812_rainbow.c b/examples/ws2812_rainbow/ws2812_rainbow.c index 4d37acc..034b099 100644 --- a/examples/ws2812_rainbow/ws2812_rainbow.c +++ b/examples/ws2812_rainbow/ws2812_rainbow.c @@ -148,6 +148,6 @@ void user_init(void) // notice the glitches due to NMI. printf("Starting a task. There may be glitches!\r\n"); - xTaskCreate(&demo, (signed char *)"strip demo", 256, NULL, 10, NULL); + xTaskCreate(&demo, "strip demo", 256, NULL, 10, NULL); #endif } diff --git a/extras/bmp180/bmp180.c b/extras/bmp180/bmp180.c index bcd447c..805a620 100644 --- a/extras/bmp180/bmp180.c +++ b/extras/bmp180/bmp180.c @@ -289,7 +289,7 @@ static bool bmp180_createTask() portBASE_TYPE x = pdPASS; if (bmp180_task_handle == NULL) { - x = xTaskCreate(bmp180_driver_task, (signed char *)"bmp180_driver_task", 256, NULL, BMP180_TASK_PRIORITY, &bmp180_task_handle); + x = xTaskCreate(bmp180_driver_task, "bmp180_driver_task", 256, NULL, BMP180_TASK_PRIORITY, &bmp180_task_handle); } return x == pdPASS; } diff --git a/extras/cpp_support/include/task.hpp b/extras/cpp_support/include/task.hpp index cb1cb45..e87e32a 100644 --- a/extras/cpp_support/include/task.hpp +++ b/extras/cpp_support/include/task.hpp @@ -56,7 +56,7 @@ public: */ int task_create(const char* const pcName, unsigned short usStackDepth = 256, unsigned portBASE_TYPE uxPriority = 2) { - return xTaskCreate(task_t::_task, (signed char *)pcName, usStackDepth, this, uxPriority, NULL); + return xTaskCreate(task_t::_task, pcName, usStackDepth, this, uxPriority, NULL); } protected: diff --git a/extras/dhcpserver/dhcpserver.c b/extras/dhcpserver/dhcpserver.c index 269b297..82ccfd1 100644 --- a/extras/dhcpserver/dhcpserver.c +++ b/extras/dhcpserver/dhcpserver.c @@ -89,7 +89,7 @@ void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases) // state->server_if is assigned once the task is running - see comment in dhcpserver_task() ip_addr_copy(state->first_client_addr, *first_client_addr); - xTaskCreate(dhcpserver_task, (signed char *)"DHCPServer", 768, NULL, 8, &dhcpserver_task_handle); + xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle); } void dhcpserver_stop(void) diff --git a/extras/rboot-ota/ota-tftp.c b/extras/rboot-ota/ota-tftp.c index 99ebdf7..c53b771 100644 --- a/extras/rboot-ota/ota-tftp.c +++ b/extras/rboot-ota/ota-tftp.c @@ -50,7 +50,7 @@ static void tftp_send_error(struct netconn *nc, int err_code, const char *err_ms void ota_tftp_init_server(int listen_port) { - xTaskCreate(tftp_task, (signed char *)"tftpOTATask", 512, (void *)listen_port, 2, NULL); + xTaskCreate(tftp_task, "tftpOTATask", 512, (void *)listen_port, 2, NULL); } err_t ota_tftp_download(const char *server, int port, const char *filename, diff --git a/lwip/lwip b/lwip/lwip index 3cf8d51..aa3eb9a 160000 --- a/lwip/lwip +++ b/lwip/lwip @@ -1 +1 @@ -Subproject commit 3cf8d514bd76e6ef77e6fa514d0ec6d96da7fd9a +Subproject commit aa3eb9ac978d52abca53561ebaf119a673a2aac0 diff --git a/lwip/sys_arch.c b/lwip/sys_arch.c index dc26dfd..51c29e0 100644 --- a/lwip/sys_arch.c +++ b/lwip/sys_arch.c @@ -514,7 +514,7 @@ xTaskHandle xCreatedTask; portBASE_TYPE xResult; sys_thread_t xReturn; - xResult = xTaskCreate( pxThread, ( signed char * ) pcName, iStackSize, pvArg, iPriority, &xCreatedTask ); + xResult = xTaskCreate( pxThread, pcName, iStackSize, pvArg, iPriority, &xCreatedTask ); if( xResult == pdPASS ) {