Merge branch 'zims-freertos-sync-1' into 'master'

freertos: Sync safe changes from Amazon SMP branch

See merge request espressif/esp-idf!14699
This commit is contained in:
Zim Kalinowski
2021-08-09 21:13:51 +00:00
7 changed files with 9689 additions and 9538 deletions

View File

@@ -1,6 +1,6 @@
/* /*
* FreeRTOS Kernel V10.2.1 * FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@@ -19,10 +19,9 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* http://www.FreeRTOS.org * https://www.FreeRTOS.org
* http://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
* 1 tab == 4 spaces!
*/ */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@@ -30,32 +29,32 @@
#include "croutine.h" #include "croutine.h"
/* Remove the whole file is co-routines are not being used. */ /* Remove the whole file is co-routines are not being used. */
#if( configUSE_CO_ROUTINES != 0 ) #if ( configUSE_CO_ROUTINES != 0 )
/* /*
* Some kernel aware debuggers require data to be viewed to be global, rather * Some kernel aware debuggers require data to be viewed to be global, rather
* than file scope. * than file scope.
*/ */
#ifdef portREMOVE_STATIC_QUALIFIER #ifdef portREMOVE_STATIC_QUALIFIER
#define static #define static
#endif #endif
/* Lists for ready and blocked co-routines. --------------------*/ /* Lists for ready and blocked co-routines. --------------------*/
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static List_t xDelayedCoRoutineList1; /*< Delayed 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 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 * pxDelayedCoRoutineList = NULL; /*< 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 * pxOverflowDelayedCoRoutineList = NULL; /*< 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. */ 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. --------------------------------*/ /* Other file private variables. --------------------------------*/
CRCB_t * pxCurrentCoRoutine = NULL; CRCB_t * pxCurrentCoRoutine = NULL;
static UBaseType_t uxTopCoRoutineReadyPriority = 0; static UBaseType_t uxTopCoRoutineReadyPriority = 0;
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
/* The initial state of the co-routine when it is created. */ /* The initial state of the co-routine when it is created. */
#define corINITIAL_STATE ( 0 ) #define corINITIAL_STATE ( 0 )
/* /*
* Place the co-routine represented by pxCRCB into the appropriate ready queue * Place the co-routine represented by pxCRCB into the appropriate ready queue
@@ -64,20 +63,20 @@ static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
* This macro accesses the co-routine ready lists and therefore must not be * This macro accesses the co-routine ready lists and therefore must not be
* used from within an ISR. * used from within an ISR.
*/ */
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ #define prvAddCoRoutineToReadyQueue( pxCRCB ) \
{ \ { \
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
{ \ { \
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
} \ } \
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
} }
/* /*
* Utility to ready all the lists used by the scheduler. This is called * Utility to ready all the lists used by the scheduler. This is called
* automatically upon the creation of the first co-routine. * automatically upon the creation of the first co-routine.
*/ */
static void prvInitialiseCoRoutineLists( void ); static void prvInitialiseCoRoutineLists( void );
/* /*
* Co-routines that are readied by an interrupt cannot be placed directly into * Co-routines that are readied by an interrupt cannot be placed directly into
@@ -85,7 +84,7 @@ static void prvInitialiseCoRoutineLists( void );
* in the pending ready list in order that they can later be moved to the ready * in the pending ready list in order that they can later be moved to the ready
* list by the co-routine scheduler. * list by the co-routine scheduler.
*/ */
static void prvCheckPendingReadyList( void ); static void prvCheckPendingReadyList( void );
/* /*
* Macro that looks at the list of co-routines that are currently delayed to * Macro that looks at the list of co-routines that are currently delayed to
@@ -95,21 +94,24 @@ static void prvCheckPendingReadyList( void );
* meaning once one co-routine has been found whose timer has not expired * meaning once one co-routine has been found whose timer has not expired
* we need not look any further down the list. * we need not look any further down the list.
*/ */
static void prvCheckDelayedList( void ); static void prvCheckDelayedList( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
{ UBaseType_t uxPriority,
BaseType_t xReturn; UBaseType_t uxIndex )
CRCB_t *pxCoRoutine; {
BaseType_t xReturn;
CRCB_t * pxCoRoutine;
/* Allocate the memory that will store the co-routine control block. */ /* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine ) if( pxCoRoutine )
{ {
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to /* If pxCurrentCoRoutine is NULL then this is the first co-routine to
be created and the co-routine data structures need initialising. */ * be created and the co-routine data structures need initialising. */
if( pxCurrentCoRoutine == NULL ) if( pxCurrentCoRoutine == NULL )
{ {
pxCurrentCoRoutine = pxCoRoutine; pxCurrentCoRoutine = pxCoRoutine;
@@ -133,8 +135,8 @@ CRCB_t *pxCoRoutine;
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the ListItem_t. /* 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 * This is so we can get back to the containing CRCB from a generic item
in a list. */ * in a list. */
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
@@ -142,7 +144,7 @@ CRCB_t *pxCoRoutine;
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) 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 /* Now the co-routine has been initialised it can be added to the ready
list at the correct priority. */ * list at the correct priority. */
prvAddCoRoutineToReadyQueue( pxCoRoutine ); prvAddCoRoutineToReadyQueue( pxCoRoutine );
xReturn = pdPASS; xReturn = pdPASS;
@@ -153,20 +155,21 @@ CRCB_t *pxCoRoutine;
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
{ List_t * pxEventList )
TickType_t xTimeToWake; {
TickType_t xTimeToWake;
/* Calculate the time to wake - this may overflow but this is /* Calculate the time to wake - this may overflow but this is
not a problem. */ * not a problem. */
xTimeToWake = xCoRoutineTickCount + xTicksToDelay; xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding /* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for * ourselves to the blocked list as the same list item is used for
both lists. */ * both lists. */
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
/* The list item will be inserted in wake time order. */ /* The list item will be inserted in wake time order. */
@@ -175,38 +178,38 @@ TickType_t xTimeToWake;
if( xTimeToWake < xCoRoutineTickCount ) if( xTimeToWake < xCoRoutineTickCount )
{ {
/* Wake time has overflowed. Place this item in the /* Wake time has overflowed. Place this item in the
overflow list. */ * overflow list. */
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
} }
else else
{ {
/* The wake time has not overflowed, so we can use the /* The wake time has not overflowed, so we can use the
current block list. */ * current block list. */
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
} }
if( pxEventList ) if( pxEventList )
{ {
/* Also add the co-routine to an event list. If this is done then the /* Also add the co-routine to an event list. If this is done then the
function must be called with interrupts disabled. */ * function must be called with interrupts disabled. */
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCheckPendingReadyList( void ) static void prvCheckPendingReadyList( void )
{ {
/* Are there any co-routines waiting to get moved to the ready list? These /* Are there any co-routines waiting to get moved to the ready list? These
are co-routines that have been readied by an ISR. The ISR cannot access * are co-routines that have been readied by an ISR. The ISR cannot access
the ready lists itself. */ * the ready lists itself. */
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{ {
CRCB_t *pxUnblockedCRCB; CRCB_t * pxUnblockedCRCB;
/* The pending ready list can be accessed by an ISR. */ /* The pending ready list can be accessed by an ISR. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@@ -214,14 +217,15 @@ static void prvCheckPendingReadyList( void )
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCheckDelayedList( void ) static void prvCheckDelayedList( void )
{ {
CRCB_t *pxCRCB; CRCB_t * pxCRCB;
xPassedTicks = xTaskGetTickCount() - xLastTickCount; xPassedTicks = xTaskGetTickCount() - xLastTickCount;
while( xPassedTicks ) while( xPassedTicks )
{ {
xCoRoutineTickCount++; xCoRoutineTickCount++;
@@ -233,7 +237,7 @@ CRCB_t *pxCRCB;
List_t * pxTemp; List_t * pxTemp;
/* Tick count has overflowed so we need to swap the delay lists. If there are /* 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! */ * any items in pxDelayedCoRoutineList here then there is an error! */
pxTemp = pxDelayedCoRoutineList; pxTemp = pxDelayedCoRoutineList;
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
pxOverflowDelayedCoRoutineList = pxTemp; pxOverflowDelayedCoRoutineList = pxTemp;
@@ -253,10 +257,10 @@ CRCB_t *pxCRCB;
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
{ {
/* The event could have occurred just before this critical /* The event could have occurred just before this critical
section. If this is the case then the generic list item will * section. If this is the case then the generic list item will
have been moved to the pending ready list and the following * have been moved to the pending ready list and the following
line is still valid. Also the pvContainer parameter will have * line is still valid. Also the pvContainer parameter will have
been set to NULL so the following lines are also valid. */ * been set to NULL so the following lines are also valid. */
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
/* Is the co-routine waiting on an event also? */ /* Is the co-routine waiting on an event also? */
@@ -272,11 +276,11 @@ CRCB_t *pxCRCB;
} }
xLastTickCount = xCoRoutineTickCount; xLastTickCount = xCoRoutineTickCount;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vCoRoutineSchedule( void ) void vCoRoutineSchedule( void )
{ {
/* See if any co-routines readied by events need moving to the ready lists. */ /* See if any co-routines readied by events need moving to the ready lists. */
prvCheckPendingReadyList(); prvCheckPendingReadyList();
@@ -295,19 +299,19 @@ void vCoRoutineSchedule( void )
} }
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
of the same priority get an equal share of the processor time. */ * of the same priority get an equal share of the processor time. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
/* Call the co-routine. */ /* Call the co-routine. */
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
return; return;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInitialiseCoRoutineLists( void ) static void prvInitialiseCoRoutineLists( void )
{ {
UBaseType_t uxPriority; UBaseType_t uxPriority;
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
{ {
@@ -319,20 +323,20 @@ UBaseType_t uxPriority;
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
/* Start with pxDelayedCoRoutineList using list1 and the /* Start with pxDelayedCoRoutineList using list1 and the
pxOverflowDelayedCoRoutineList using list2. */ * pxOverflowDelayedCoRoutineList using list2. */
pxDelayedCoRoutineList = &xDelayedCoRoutineList1; pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
{ {
CRCB_t *pxUnblockedCRCB; CRCB_t * pxUnblockedCRCB;
BaseType_t xReturn; BaseType_t xReturn;
/* This function is called from within an interrupt. It can only access /* This function is called from within an interrupt. It can only access
event lists and the pending ready list. This function assumes that a * event lists and the pending ready list. This function assumes that a
check has already been made to ensure pxEventList is not empty. */ * check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
@@ -347,6 +351,6 @@ BaseType_t xReturn;
} }
return xReturn; return xReturn;
} }
#endif /* configUSE_CO_ROUTINES == 0 */ #endif /* configUSE_CO_ROUTINES == 0 */

View File

@@ -1,6 +1,6 @@
/* /*
* FreeRTOS Kernel V10.2.1 * FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@@ -19,18 +19,17 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* http://www.FreeRTOS.org * https://www.FreeRTOS.org
* http://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
* 1 tab == 4 spaces!
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdlib.h> #include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining /* 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 * all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */ * task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */ /* FreeRTOS includes. */
@@ -40,14 +39,14 @@ task.h is included from an application file. */
#include "event_groups.h" #include "event_groups.h"
/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * 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 * for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */ * correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
/* The following bit fields convey control information in a task's event list /* The following bit fields convey control information in a task's event list
item value. It is important they don't clash with the * item value. It is important they don't clash with the
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#if configUSE_16_BIT_TICKS == 1 #if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
@@ -65,11 +64,11 @@ typedef struct EventGroupDef_t
EventBits_t uxEventBits; EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber; UBaseType_t uxEventGroupNumber;
#endif #endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) #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. */ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
#endif #endif
@@ -86,24 +85,26 @@ typedef struct EventGroupDef_t
* wait condition is met if any of the bits set in uxBitsToWait for are also set * wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits. * in uxCurrentEventBits.
*/ */
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
{ {
EventGroup_t *pxEventBits; EventGroup_t * pxEventBits;
/* A StaticEventGroup_t object must be provided. */ /* A StaticEventGroup_t object must be provided. */
configASSERT( pxEventGroupBuffer ); configASSERT( pxEventGroupBuffer );
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
/* Sanity check that the size of the structure used to declare a /* Sanity check that the size of the structure used to declare a
variable of type StaticEventGroup_t equals the size of the real * variable of type StaticEventGroup_t equals the size of the real
event group structure. */ * event group structure. */
volatile size_t xSize = sizeof( StaticEventGroup_t ); volatile size_t xSize = sizeof( StaticEventGroup_t );
configASSERT( xSize == sizeof( EventGroup_t ) ); configASSERT( xSize == sizeof( EventGroup_t ) );
} /*lint !e529 xSize is referenced if configASSERT() is defined. */ } /*lint !e529 xSize is referenced if configASSERT() is defined. */
@@ -117,11 +118,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
pxEventBits->uxEventBits = 0; pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{ {
/* Both static and dynamic allocation can be used, so note that /* Both static and dynamic allocation can be used, so note that
this event group was created statically in case the event group * this event group was created statically in case the event group
is later deleted. */ * is later deleted. */
pxEventBits->ucStaticallyAllocated = pdTRUE; pxEventBits->ucStaticallyAllocated = pdTRUE;
} }
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
@@ -133,8 +134,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
else else
{ {
/* xEventGroupCreateStatic should only ever be called with /* xEventGroupCreateStatic should only ever be called with
pxEventGroupBuffer pointing to a pre-allocated (compile time * pxEventGroupBuffer pointing to a pre-allocated (compile time
allocated) StaticEventGroup_t variable. */ * allocated) StaticEventGroup_t variable. */
traceEVENT_GROUP_CREATE_FAILED(); traceEVENT_GROUP_CREATE_FAILED();
} }
@@ -144,25 +145,25 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void ) EventGroupHandle_t xEventGroupCreate( void )
{ {
EventGroup_t *pxEventBits; EventGroup_t * pxEventBits;
/* Allocate the event group. Justification for MISRA deviation as /* Allocate the event group. Justification for MISRA deviation as
follows: pvPortMalloc() always ensures returned memory blocks are * follows: pvPortMalloc() always ensures returned memory blocks are
aligned per the requirements of the MCU stack. In this case * aligned per the requirements of the MCU stack. In this case
pvPortMalloc() must return a pointer that is guaranteed to meet the * pvPortMalloc() must return a pointer that is guaranteed to meet the
alignment requirements of the EventGroup_t structure - which (if you * alignment requirements of the EventGroup_t structure - which (if you
follow it through) is the alignment requirements of the TickType_t type * follow it through) is the alignment requirements of the TickType_t type
(EventBits_t being of TickType_t itself). Therefore, whenever the * (EventBits_t being of TickType_t itself). Therefore, whenever the
stack alignment requirements are greater than or equal to the * stack alignment requirements are greater than or equal to the
TickType_t alignment requirements the cast is safe. In other cases, * TickType_t alignment requirements the cast is safe. In other cases,
where the natural word size of the architecture is less than * where the natural word size of the architecture is less than
sizeof( TickType_t ), the TickType_t variables will be accessed in two * sizeof( TickType_t ), the TickType_t variables will be accessed in two
or more reads operations, and the alignment requirements is only that * or more reads operations, and the alignment requirements is only that
of each individual read. */ * of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */ pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
if( pxEventBits != NULL ) if( pxEventBits != NULL )
@@ -170,11 +171,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
pxEventBits->uxEventBits = 0; pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
{ {
/* Both static and dynamic allocation can be used, so note this /* Both static and dynamic allocation can be used, so note this
event group was allocated statically in case the event group is * event group was allocated statically in case the event group is
later deleted. */ * later deleted. */
pxEventBits->ucStaticallyAllocated = pdFALSE; pxEventBits->ucStaticallyAllocated = pdFALSE;
} }
#endif /* configSUPPORT_STATIC_ALLOCATION */ #endif /* configSUPPORT_STATIC_ALLOCATION */
@@ -194,11 +195,14 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait )
{ {
EventBits_t uxOriginalBitValue, uxReturn; EventBits_t uxOriginalBitValue, uxReturn;
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
BaseType_t xTimeoutOccurred = pdFALSE; BaseType_t xTimeoutOccurred = pdFALSE;
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 ); configASSERT( uxBitsToWaitFor != 0 );
@@ -220,7 +224,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = ( uxOriginalBitValue | uxBitsToSet ); uxReturn = ( uxOriginalBitValue | uxBitsToSet );
/* Rendezvous always clear the bits. They will have been cleared /* Rendezvous always clear the bits. They will have been cleared
already unless this is the only task in the rendezvous. */ * already unless this is the only task in the rendezvous. */
pxEventBits->uxEventBits &= ~uxBitsToWaitFor; pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
xTicksToWait = 0; xTicksToWait = 0;
@@ -232,20 +236,20 @@ BaseType_t xTimeoutOccurred = pdFALSE;
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
/* Store the bits that the calling task is waiting for in the /* 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 * task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */ * found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
/* This assignment is obsolete as uxReturn will get set after /* This assignment is obsolete as uxReturn will get set after
the task unblocks, but some compilers mistakenly generate a * the task unblocks, but some compilers mistakenly generate a
warning about uxReturn being returned without being set if the * warning about uxReturn being returned without being set if the
assignment is omitted. */ * assignment is omitted. */
uxReturn = 0; uxReturn = 0;
} }
else else
{ {
/* The rendezvous bits were not set, but no block time was /* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */ * specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
xTimeoutOccurred = pdTRUE; xTimeoutOccurred = pdTRUE;
} }
@@ -259,9 +263,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
/* The task blocked to wait for its required bits to be set - at this /* 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 * 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 * 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. */ * event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue(); uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
@@ -272,9 +276,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
/* Although the task got here because it timed out before the /* Although the task got here because it timed out before the
bits it was waiting for were set, it is possible that since it * 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 * unblocked another task has set the bits. If this is the case
then it needs to clear the bits before exiting. */ * then it needs to clear the bits before exiting. */
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
{ {
pxEventBits->uxEventBits &= ~uxBitsToWaitFor; pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
@@ -294,7 +298,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/* Control bits might be set as the task had blocked should not be /* Control bits might be set as the task had blocked should not be
returned. */ * returned. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
} }
@@ -307,15 +311,19 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait )
{ {
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
EventBits_t uxReturn, uxControlBits = 0; EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet; BaseType_t xWaitConditionMet;
BaseType_t xTimeoutOccurred = pdFALSE; BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel /* 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. */ * itself, and that at least one bit is being requested. */
configASSERT( xEventGroup ); configASSERT( xEventGroup );
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 ); configASSERT( uxBitsToWaitFor != 0 );
@@ -335,7 +343,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
if( xWaitConditionMet != pdFALSE ) if( xWaitConditionMet != pdFALSE )
{ {
/* The wait condition has already been met so there is no need to /* The wait condition has already been met so there is no need to
block. */ * block. */
uxReturn = uxCurrentEventBits; uxReturn = uxCurrentEventBits;
xTicksToWait = ( TickType_t ) 0; xTicksToWait = ( TickType_t ) 0;
@@ -352,16 +360,16 @@ BaseType_t xTimeoutOccurred = pdFALSE;
else if( xTicksToWait == ( TickType_t ) 0 ) else if( xTicksToWait == ( TickType_t ) 0 )
{ {
/* The wait condition has not been met, but no block time was /* The wait condition has not been met, but no block time was
specified, so just return the current value. */ * specified, so just return the current value. */
uxReturn = uxCurrentEventBits; uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE; xTimeoutOccurred = pdTRUE;
} }
else else
{ {
/* The task is going to block to wait for its required bits to be /* The task is going to block to wait for its required bits to be
set. uxControlBits are used to remember the specified behaviour of * set. uxControlBits are used to remember the specified behaviour of
this call to xEventGroupWaitBits() - for use when the event bits * this call to xEventGroupWaitBits() - for use when the event bits
unblock the task. */ * unblock the task. */
if( xClearOnExit != pdFALSE ) if( xClearOnExit != pdFALSE )
{ {
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
@@ -381,13 +389,13 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/* Store the bits that the calling task is waiting for in the /* 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 * task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */ * found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
/* This is obsolete as it will get set after the task unblocks, but /* This is obsolete as it will get set after the task unblocks, but
some compilers mistakenly generate a warning about the variable * some compilers mistakenly generate a warning about the variable
being returned without being set if it is not done. */ * being returned without being set if it is not done. */
uxReturn = 0; uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
@@ -401,9 +409,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
/* The task blocked to wait for its required bits to be set - at this /* 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 * 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 * 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. */ * event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue(); uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
@@ -414,7 +422,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
/* It is possible that the event bits were updated between this /* It is possible that the event bits were updated between this
task leaving the Blocked state and running again. */ * task leaving the Blocked state and running again. */
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
{ {
if( xClearOnExit != pdFALSE ) if( xClearOnExit != pdFALSE )
@@ -430,6 +438,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
{ {
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
xTimeoutOccurred = pdTRUE; xTimeoutOccurred = pdTRUE;
} }
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
@@ -442,6 +451,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
/* The task blocked so control bits may have been set. */ /* The task blocked so control bits may have been set. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
} }
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */ /* Prevent compiler warnings when trace macros are not used. */
@@ -451,13 +461,14 @@ BaseType_t xTimeoutOccurred = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{ {
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
EventBits_t uxReturn; EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel /* Check the user is not attempting to clear the bits used by the kernel
itself. */ * itself. */
configASSERT( xEventGroup ); configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
@@ -466,7 +477,7 @@ EventBits_t uxReturn;
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being /* The value returned is the event group value prior to the bits being
cleared. */ * cleared. */
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */ /* Clear the bits. */
@@ -480,7 +491,8 @@ EventBits_t uxReturn;
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{ {
BaseType_t xReturn; BaseType_t xReturn;
@@ -490,14 +502,14 @@ EventBits_t uxReturn;
return xReturn; return xReturn;
} }
#endif #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{ {
UBaseType_t uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
EventGroup_t const * const pxEventBits = xEventGroup; EventGroup_t const * const pxEventBits = xEventGroup;
EventBits_t uxReturn; EventBits_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@@ -509,17 +521,18 @@ EventBits_t uxReturn;
} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */ } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet )
{ {
ListItem_t *pxListItem, *pxNext; ListItem_t * pxListItem, * pxNext;
ListItem_t const *pxListEnd; ListItem_t const * pxListEnd;
List_t const * pxList; List_t const * pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t * pxEventBits = xEventGroup;
BaseType_t xMatchFound = pdFALSE; BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel /* Check the user is not attempting to set the bits used by the kernel
itself. */ * itself. */
configASSERT( xEventGroup ); configASSERT( xEventGroup );
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
@@ -581,21 +594,21 @@ BaseType_t xMatchFound = pdFALSE;
} }
/* Store the actual event flag value in the task's event list /* Store the actual event flag value in the task's event list
item before removing the task from the event list. The * item before removing the task from the event list. The
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather * that is was unblocked due to its required bits matching, rather
than because it timed out. */ * than because it timed out. */
xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
} }
/* Move onto the next list item. Note pxListItem->pxNext is not /* 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 * used here as the list item may have been removed from the event list
and inserted into the ready/pending reading list. */ * and inserted into the ready/pending reading list. */
pxListItem = pxNext; pxListItem = pxNext;
} }
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
bit was set in the control word. */ * bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear; pxEventBits->uxEventBits &= ~uxBitsToClear;
} }
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
@@ -606,8 +619,8 @@ BaseType_t xMatchFound = pdFALSE;
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{ {
EventGroup_t *pxEventBits = xEventGroup; EventGroup_t *pxEventBits = xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
traceEVENT_GROUP_DELETE( xEventGroup ); traceEVENT_GROUP_DELETE( xEventGroup );
@@ -616,23 +629,23 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{ {
/* Unblock the task, returning 0 as the event list is being deleted /* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */ * and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
} }
} }
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
{ {
/* The event group can only have been allocated dynamically - free /* The event group can only have been allocated dynamically - free
it again. */ * it again. */
vPortFree( pxEventBits ); vPortFree( pxEventBits );
} }
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{ {
/* The event group could have been allocated statically or /* The event group could have been allocated statically or
dynamically, so check before attempting to free the memory. */ * dynamically, so check before attempting to free the memory. */
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
{ {
vPortFree( pxEventBits ); vPortFree( pxEventBits );
@@ -647,29 +660,33 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* For internal use only - execute a 'set bits' command that was pended from /* For internal use only - execute a 'set bits' command that was pended from
an interrupt. */ * an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) void vEventGroupSetBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToSet )
{ {
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* For internal use only - execute a 'clear bits' command that was pended from /* For internal use only - execute a 'clear bits' command that was pended from
an interrupt. */ * an interrupt. */
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear )
{ {
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits )
{ {
BaseType_t xWaitConditionMet = pdFALSE; BaseType_t xWaitConditionMet = pdFALSE;
if( xWaitForAllBits == pdFALSE ) if( xWaitForAllBits == pdFALSE )
{ {
/* Task only has to wait for one bit within uxBitsToWaitFor to be /* Task only has to wait for one bit within uxBitsToWaitFor to be
set. Is one already set? */ * set. Is one already set? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
{ {
xWaitConditionMet = pdTRUE; xWaitConditionMet = pdTRUE;
@@ -682,7 +699,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
else else
{ {
/* Task has to wait for all the bits in uxBitsToWaitFor to be set. /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
Are they set already? */ * Are they set already? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
{ {
xWaitConditionMet = pdTRUE; xWaitConditionMet = pdTRUE;
@@ -699,7 +716,9 @@ BaseType_t xWaitConditionMet = pdFALSE;
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) #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 xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken )
{ {
BaseType_t xReturn; BaseType_t xReturn;
@@ -709,15 +728,15 @@ BaseType_t xWaitConditionMet = pdFALSE;
return xReturn; return xReturn;
} }
#endif #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if (configUSE_TRACE_FACILITY == 1) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
{ {
UBaseType_t xReturn; UBaseType_t xReturn;
EventGroup_t const *pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
if( xEventGroup == NULL ) if( xEventGroup == NULL )
{ {
@@ -736,7 +755,8 @@ BaseType_t xWaitConditionMet = pdFALSE;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber ) void vEventGroupSetNumber( void * xEventGroup,
UBaseType_t uxEventGroupNumber )
{ {
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
} }

View File

@@ -1,6 +1,6 @@
/* /*
* FreeRTOS Kernel V10.2.1 * FreeRTOS Kernel V10.4.3
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@@ -19,10 +19,9 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* http://www.FreeRTOS.org * https://www.FreeRTOS.org
* http://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
* 1 tab == 4 spaces!
*/ */
@@ -32,29 +31,29 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* PUBLIC LIST API documented in list.h * PUBLIC LIST API documented in list.h
*----------------------------------------------------------*/ *----------------------------------------------------------*/
void vListInitialise( List_t * const pxList ) void vListInitialise( List_t * const pxList )
{ {
/* The list structure contains a list item which is used to mark the /* 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 * end of the list. To initialise the list the list end is inserted
as the only list entry. */ * as the only list entry. */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 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 !e9087 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 /* The list end value is the highest possible value in the list to
ensure it remains at the end of the list. */ * ensure it remains at the end of the list. */
pxList->xListEnd.xItemValue = portMAX_DELAY; pxList->xListEnd.xItemValue = portMAX_DELAY;
/* The list end next and previous pointers point to itself so we know /* The list end next and previous pointers point to itself so we know
when the list is empty. */ * when the list is empty. */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 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 !e9087 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 !e9087 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 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->uxNumberOfItems = ( UBaseType_t ) 0U; pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* Write known values into the list if /* Write known values into the list if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
} }
@@ -66,25 +65,26 @@ void vListInitialiseItem( ListItem_t * const pxItem )
pxItem->pxContainer = NULL; pxItem->pxContainer = NULL;
/* Write known values into the list item if /* Write known values into the list item if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) void vListInsertEnd( List_t * const pxList,
ListItem_t * const pxNewListItem )
{ {
ListItem_t * const pxIndex = pxList->pxIndex; ListItem_t * const pxIndex = pxList->pxIndex;
/* Only effective when configASSERT() is also defined, these tests may catch /* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch * the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */ * data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert a new list item into pxList, but rather than sort the list, /* 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 * makes the new list item the last item to be removed by a call to
listGET_OWNER_OF_NEXT_ENTRY(). */ * listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex; pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious; pxNewListItem->pxPrevious = pxIndex->pxPrevious;
@@ -101,25 +101,26 @@ ListItem_t * const pxIndex = pxList->pxIndex;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) void vListInsert( List_t * const pxList,
ListItem_t * const pxNewListItem )
{ {
ListItem_t *pxIterator; ListItem_t * pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Only effective when configASSERT() is also defined, these tests may catch /* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch * the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */ * data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert the new list item into the list, sorted in xItemValue order. /* 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 * 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 TCBs which are * new list item should be placed after it. This ensures that TCBs which are
stored in ready lists (all of which have the same xItemValue value) get a * 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 * 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 * the iteration loop below will not end. Therefore the value is checked
first, and the algorithm slightly modified if necessary. */ * first, and the algorithm slightly modified if necessary. */
if( xValueOfInsertion == portMAX_DELAY ) if( xValueOfInsertion == portMAX_DELAY )
{ {
pxIterator = pxList->xListEnd.pxPrevious; pxIterator = pxList->xListEnd.pxPrevious;
@@ -127,31 +128,34 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
else else
{ {
/* *** NOTE *********************************************************** /* *** 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 https://www.freertos.org/FAQHelp.html for * listed below. In addition see https://www.freertos.org/FAQHelp.html for
more tips, and ensure configASSERT() is defined! * more tips, and ensure configASSERT() is defined!
https://www.freertos.org/a00110.html#configASSERT * https://www.freertos.org/a00110.html#configASSERT
*
1) Stack overflow - * 1) Stack overflow -
see https://www.freertos.org/Stacks-and-stack-overflow-checking.html * see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M * 2) Incorrect interrupt priority assignment, especially on Cortex-M
parts where numerically high priority values denote low actual * parts where numerically high priority values denote low actual
interrupt priorities, which can seem counter intuitive. See * interrupt priorities, which can seem counter intuitive. See
https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition * https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
of configMAX_SYSCALL_INTERRUPT_PRIORITY on * of configMAX_SYSCALL_INTERRUPT_PRIORITY on
https://www.freertos.org/a00110.html * https://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when * 3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does * the scheduler is suspended, or calling an API function that does
not end in "FromISR" from an interrupt. * not end in "FromISR" from an interrupt.
4) Using a queue or semaphore before it has been initialised or * 4) Using a queue or semaphore before it has been initialised or
before the scheduler has been started (are interrupts firing * before the scheduler has been started (are interrupts firing
before vTaskStartScheduler() has been called?). * before vTaskStartScheduler() has been called?).
* 5) If the FreeRTOS port supports interrupt nesting then ensure that
* the priority of the tick interrupt is at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
**********************************************************************/ **********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
{ {
/* There is nothing to do here, just iterating to the wanted /* There is nothing to do here, just iterating to the wanted
insertion position. */ * insertion position. */
} }
} }
@@ -161,7 +165,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
pxIterator->pxNext = pxNewListItem; pxIterator->pxNext = pxNewListItem;
/* Remember which list the item is in. This allows fast removal of the /* Remember which list the item is in. This allows fast removal of the
item later. */ * item later. */
pxNewListItem->pxContainer = pxList; pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++; ( pxList->uxNumberOfItems )++;
@@ -171,8 +175,8 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{ {
/* The list item knows which list it is in. Obtain the list from the list /* The list item knows which list it is in. Obtain the list from the list
item. */ * item. */
List_t * const pxList = pxItemToRemove->pxContainer; List_t * const pxList = pxItemToRemove->pxContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
@@ -181,7 +185,7 @@ List_t * const pxList = pxItemToRemove->pxContainer;
mtCOVERAGE_TEST_DELAY(); mtCOVERAGE_TEST_DELAY();
/* Make sure the index is left pointing to a valid item. */ /* Make sure the index is left pointing to a valid item. */
if(pxList->pxIndex == pxItemToRemove) if( pxList->pxIndex == pxItemToRemove )
{ {
pxList->pxIndex = pxItemToRemove->pxPrevious; pxList->pxIndex = pxItemToRemove->pxPrevious;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* /*
* FreeRTOS Kernel V10.2.1 * FreeRTOS Kernel V10.4.3
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@@ -19,10 +19,9 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* http://www.FreeRTOS.org * https://www.FreeRTOS.org
* http://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
* 1 tab == 4 spaces!
*/ */
/* Standard includes. */ /* Standard includes. */
@@ -30,8 +29,8 @@
#include <string.h> #include <string.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining /* 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 * all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */ * task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */ /* FreeRTOS includes. */
@@ -39,20 +38,20 @@ task.h is included from an application file. */
#include "task.h" #include "task.h"
#include "stream_buffer.h" #include "stream_buffer.h"
#if( configUSE_TASK_NOTIFICATIONS != 1 ) #if ( configUSE_TASK_NOTIFICATIONS != 1 )
#error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c
#endif #endif
/* Lint e961, e9021 and e750 are suppressed as a MISRA exception justified /* Lint e961, e9021 and e750 are suppressed as a MISRA exception justified
because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined * 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 * for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */ * correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
/* If the user has not provided application specific Rx notification macros, /* If the user has not provided application specific Rx notification macros,
or #defined the notification macros away, them provide default implementations * or #defined the notification macros away, then provide default implementations
that uses task notifications. */ * that uses task notifications. */
/*lint -save -e9026 Function like macros allowed and needed here so they can be overidden. */ /*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */
#ifndef sbRECEIVE_COMPLETED #ifndef sbRECEIVE_COMPLETED
#define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \ taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \
@@ -90,8 +89,8 @@ that uses task notifications. */
#endif /* sbRECEIVE_COMPLETED_FROM_ISR */ #endif /* sbRECEIVE_COMPLETED_FROM_ISR */
/* If the user has not provided an application specific Tx notification macro, /* If the user has not provided an application specific Tx notification macro,
or #defined the notification macro away, them provide a default implementation * or #defined the notification macro away, them provide a default implementation
that uses task notifications. */ * that uses task notifications. */
#ifndef sbSEND_COMPLETED #ifndef sbSEND_COMPLETED
#define sbSEND_COMPLETED( pxStreamBuffer ) \ #define sbSEND_COMPLETED( pxStreamBuffer ) \
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \ taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \
@@ -146,13 +145,12 @@ typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */
size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */ size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */
volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */ volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */ volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */
uint8_t *pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */ uint8_t * pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
uint8_t ucFlags; uint8_t ucFlags;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */ UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
#endif #endif
portMUX_TYPE xStreamBufferMux; //Mutex required due to SMP portMUX_TYPE xStreamBufferMux; //Mutex required due to SMP
} StreamBuffer_t; } StreamBuffer_t;
@@ -167,7 +165,9 @@ static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PR
* success case, or 0 if there was not enough space in the buffer (in which case * success case, or 0 if there was not enough space in the buffer (in which case
* no data is written into the buffer). * no data is written into the buffer).
*/ */
static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) PRIVILEGED_FUNCTION; static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
const uint8_t *pucData,
size_t xCount ) PRIVILEGED_FUNCTION;
/* /*
* If the stream buffer is being used as a message buffer, then reads an entire * If the stream buffer is being used as a message buffer, then reads an entire
@@ -176,8 +176,8 @@ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, cons
* prvReadBytesFromBuffer() is called to actually extract the bytes from the * prvReadBytesFromBuffer() is called to actually extract the bytes from the
* buffer's data storage area. * buffer's data storage area.
*/ */
static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
void *pvRxData, void * pvRxData,
size_t xBufferLengthBytes, size_t xBufferLengthBytes,
size_t xBytesAvailable, size_t xBytesAvailable,
size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION; size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION;
@@ -199,8 +199,8 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
* Read xMaxCount bytes from the pxStreamBuffer message buffer and write them * Read xMaxCount bytes from the pxStreamBuffer message buffer and write them
* to pucData. * to pucData.
*/ */
static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
uint8_t *pucData, uint8_t * pucData,
size_t xMaxCount, size_t xMaxCount,
size_t xBytesAvailable ) PRIVILEGED_FUNCTION; size_t xBytesAvailable ) PRIVILEGED_FUNCTION;
@@ -216,17 +216,19 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer ) StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer )
{ {
uint8_t *pucAllocatedMemory; uint8_t * pucAllocatedMemory;
uint8_t ucFlags; uint8_t ucFlags;
/* In case the stream buffer is going to be used as a message buffer /* In case the stream buffer is going to be used as a message buffer
(that is, it will hold discrete messages with a little meta data that * (that is, it will hold discrete messages with a little meta data that
says how big the next message is) check the buffer will be large enough * says how big the next message is) check the buffer will be large enough
to hold at least one message. */ * to hold at least one message. */
if( xIsMessageBuffer == pdTRUE ) if( xIsMessageBuffer == pdTRUE )
{ {
/* Is a message buffer but not statically allocated. */ /* Is a message buffer but not statically allocated. */
@@ -239,23 +241,24 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
ucFlags = 0; ucFlags = 0;
configASSERT( xBufferSizeBytes > 0 ); configASSERT( xBufferSizeBytes > 0 );
} }
configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
/* A trigger level of 0 would cause a waiting task to unblock even when /* A trigger level of 0 would cause a waiting task to unblock even when
the buffer was empty. */ * the buffer was empty. */
if( xTriggerLevelBytes == ( size_t ) 0 ) if( xTriggerLevelBytes == ( size_t ) 0 )
{ {
xTriggerLevelBytes = ( size_t ) 1; xTriggerLevelBytes = ( size_t ) 1;
} }
/* A stream buffer requires a StreamBuffer_t structure and a buffer. /* A stream buffer requires a StreamBuffer_t structure and a buffer.
Both are allocated in a single call to pvPortMalloc(). The * Both are allocated in a single call to pvPortMalloc(). The
StreamBuffer_t structure is placed at the start of the allocated memory * StreamBuffer_t structure is placed at the start of the allocated memory
and the buffer follows immediately after. The requested size is * and the buffer follows immediately after. The requested size is
incremented so the free space is returned as the user would expect - * incremented so the free space is returned as the user would expect -
this is a quirk of the implementation that means otherwise the free * this is a quirk of the implementation that means otherwise the free
space would be reported as one byte smaller than would be logically * space would be reported as one byte smaller than would be logically
expected. */ * expected. */
if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) )
{ {
xBufferSizeBytes++; xBufferSizeBytes++;
@@ -287,7 +290,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes, size_t xTriggerLevelBytes,
@@ -304,7 +307,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
/* A trigger level of 0 would cause a waiting task to unblock even when /* A trigger level of 0 would cause a waiting task to unblock even when
the buffer was empty. */ * the buffer was empty. */
if( xTriggerLevelBytes == ( size_t ) 0 ) if( xTriggerLevelBytes == ( size_t ) 0 )
{ {
xTriggerLevelBytes = ( size_t ) 1; xTriggerLevelBytes = ( size_t ) 1;
@@ -322,16 +325,16 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
} }
/* In case the stream buffer is going to be used as a message buffer /* In case the stream buffer is going to be used as a message buffer
(that is, it will hold discrete messages with a little meta data that * (that is, it will hold discrete messages with a little meta data that
says how big the next message is) check the buffer will be large enough * says how big the next message is) check the buffer will be large enough
to hold at least one message. */ * to hold at least one message. */
configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
/* Sanity check that the size of the structure used to declare a /* Sanity check that the size of the structure used to declare a
variable of type StaticStreamBuffer_t equals the size of the real * variable of type StaticStreamBuffer_t equals the size of the real
message buffer structure. */ * message buffer structure. */
volatile size_t xSize = sizeof( StaticStreamBuffer_t ); volatile size_t xSize = sizeof( StaticStreamBuffer_t );
configASSERT( xSize == sizeof( StreamBuffer_t ) ); configASSERT( xSize == sizeof( StreamBuffer_t ) );
} /*lint !e529 xSize is referenced is configASSERT() is defined. */ } /*lint !e529 xSize is referenced is configASSERT() is defined. */
@@ -344,8 +347,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
xBufferSizeBytes, xBufferSizeBytes,
xTriggerLevelBytes, xTriggerLevelBytes,
ucFlags ); ucFlags );
/* Remember this was statically allocated in case it is ever deleted /* Remember this was statically allocated in case it is ever deleted
again. */ * again. */
pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED; pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ); traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
@@ -366,7 +370,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
{ {
StreamBuffer_t * pxStreamBuffer = xStreamBuffer; StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -374,16 +378,16 @@ StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE )
{ {
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{ {
/* Both the structure and the buffer were allocated using a single call /* Both the structure and the buffer were allocated using a single call
to pvPortMalloc(), hence only one call to vPortFree() is required. */ * to pvPortMalloc(), hence only one call to vPortFree() is required. */
vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */ vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */
} }
#else #else
{ {
/* Should not be possible to get here, ucFlags must be corrupt. /* Should not be possible to get here, ucFlags must be corrupt.
Force an assert. */ * Force an assert. */
configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 ); configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
} }
#endif #endif
@@ -391,7 +395,7 @@ StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
else else
{ {
/* The structure and buffer were not allocated dynamically and cannot be /* The structure and buffer were not allocated dynamically and cannot be
freed - just scrub the structure so future use will assert. */ * freed - just scrub the structure so future use will assert. */
( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
} }
} }
@@ -399,19 +403,19 @@ StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn = pdFAIL; BaseType_t xReturn = pdFAIL;
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber; UBaseType_t uxStreamBufferNumber;
#endif #endif
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
{ {
/* Store the stream buffer number so it can be restored after the /* Store the stream buffer number so it can be restored after the
reset. */ * reset. */
uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber; uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
} }
#endif #endif
@@ -430,7 +434,7 @@ BaseType_t xReturn = pdFAIL;
pxStreamBuffer->ucFlags ); pxStreamBuffer->ucFlags );
xReturn = pdPASS; xReturn = pdPASS;
#if( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
{ {
pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
} }
@@ -446,10 +450,11 @@ BaseType_t xReturn = pdFAIL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
size_t xTriggerLevel )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn; BaseType_t xReturn;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -460,7 +465,7 @@ BaseType_t xReturn;
} }
/* The trigger level is the number of bytes that must be in the stream /* The trigger level is the number of bytes that must be in the stream
buffer before a task that is waiting for data is unblocked. */ * buffer before a task that is waiting for data is unblocked. */
if( xTriggerLevel <= pxStreamBuffer->xLength ) if( xTriggerLevel <= pxStreamBuffer->xLength )
{ {
pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel; pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
@@ -477,8 +482,8 @@ BaseType_t xReturn;
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer )
{ {
const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xSpace; size_t xSpace;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -501,8 +506,8 @@ size_t xSpace;
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
{ {
const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xReturn; size_t xReturn;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -512,22 +517,22 @@ size_t xReturn;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData, const void * pvTxData,
size_t xDataLengthBytes, size_t xDataLengthBytes,
TickType_t xTicksToWait ) TickType_t xTicksToWait )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xReturn, xSpace = 0; size_t xReturn, xSpace = 0;
size_t xRequiredSpace = xDataLengthBytes; size_t xRequiredSpace = xDataLengthBytes;
TimeOut_t xTimeOut; TimeOut_t xTimeOut;
configASSERT( pvTxData ); configASSERT( pvTxData );
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
/* This send function is used to write to both message buffers and stream /* This send function is used to write to both message buffers and stream
buffers. If this is a message buffer then the space needed must be * buffers. If this is a message buffer then the space needed must be
increased by the amount of bytes needed to store the length of the * increased by the amount of bytes needed to store the length of the
message. */ * message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{ {
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
@@ -547,7 +552,7 @@ TimeOut_t xTimeOut;
do do
{ {
/* Wait until the required number of bytes are free in the message /* Wait until the required number of bytes are free in the message
buffer. */ * buffer. */
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux );
{ {
xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
@@ -572,7 +577,6 @@ TimeOut_t xTimeOut;
traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
pxStreamBuffer->xTaskWaitingToSend = NULL; pxStreamBuffer->xTaskWaitingToSend = NULL;
} while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ); } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
} }
else else
@@ -616,21 +620,21 @@ TimeOut_t xTimeOut;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
const void *pvTxData, const void * pvTxData,
size_t xDataLengthBytes, size_t xDataLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) BaseType_t * const pxHigherPriorityTaskWoken )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xReturn, xSpace; size_t xReturn, xSpace;
size_t xRequiredSpace = xDataLengthBytes; size_t xRequiredSpace = xDataLengthBytes;
configASSERT( pvTxData ); configASSERT( pvTxData );
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
/* This send function is used to write to both message buffers and stream /* This send function is used to write to both message buffers and stream
buffers. If this is a message buffer then the space needed must be * buffers. If this is a message buffer then the space needed must be
increased by the amount of bytes needed to store the length of the * increased by the amount of bytes needed to store the length of the
message. */ * message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{ {
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
@@ -678,23 +682,23 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
if( xSpace == ( size_t ) 0 ) if( xSpace == ( size_t ) 0 )
{ {
/* Doesn't matter if this is a stream buffer or a message buffer, there /* Doesn't matter if this is a stream buffer or a message buffer, there
is no space to write. */ * is no space to write. */
xShouldWrite = pdFALSE; xShouldWrite = pdFALSE;
} }
else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 ) else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 )
{ {
/* This is a stream buffer, as opposed to a message buffer, so writing a /* This is a stream buffer, as opposed to a message buffer, so writing a
stream of bytes rather than discrete messages. Write as many bytes as * stream of bytes rather than discrete messages. Write as many bytes as
possible. */ * possible. */
xShouldWrite = pdTRUE; xShouldWrite = pdTRUE;
xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); xDataLengthBytes = configMIN( xDataLengthBytes, xSpace );
} }
else if( xSpace >= xRequiredSpace ) else if( xSpace >= xRequiredSpace )
{ {
/* This is a message buffer, as opposed to a stream buffer, and there /* This is a message buffer, as opposed to a stream buffer, and there
is enough space to write both the message length and the message itself * is enough space to write both the message length and the message itself
into the buffer. Start by writing the length of the data, the data * into the buffer. Start by writing the length of the data, the data
itself will be written later in this function. */ * itself will be written later in this function. */
xShouldWrite = pdTRUE; xShouldWrite = pdTRUE;
( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH ); ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH );
} }
@@ -719,21 +723,21 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void *pvRxData, void * pvRxData,
size_t xBufferLengthBytes, size_t xBufferLengthBytes,
TickType_t xTicksToWait ) TickType_t xTicksToWait )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
configASSERT( pvRxData ); configASSERT( pvRxData );
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
/* This receive function is used by both message buffers, which store /* This receive function is used by both message buffers, which store
discrete messages, and stream buffers, which store a continuous stream of * discrete messages, and stream buffers, which store a continuous stream of
bytes. Discrete messages include an additional * bytes. Discrete messages include an additional
sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
message. */ * message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{ {
xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
@@ -746,16 +750,16 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
if( xTicksToWait != ( TickType_t ) 0 ) if( xTicksToWait != ( TickType_t ) 0 )
{ {
/* Checking if there is data and clearing the notification state must be /* Checking if there is data and clearing the notification state must be
performed atomically. */ * performed atomically. */
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux );
{ {
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
/* If this function was invoked by a message buffer read then /* If this function was invoked by a message buffer read then
xBytesToStoreMessageLength holds the number of bytes used to hold * xBytesToStoreMessageLength holds the number of bytes used to hold
the length of the next discrete message. If this function was * the length of the next discrete message. If this function was
invoked by a stream buffer read then xBytesToStoreMessageLength will * invoked by a stream buffer read then xBytesToStoreMessageLength will
be 0. */ * be 0. */
if( xBytesAvailable <= xBytesToStoreMessageLength ) if( xBytesAvailable <= xBytesToStoreMessageLength )
{ {
/* Clear notification state as going to wait for data. */ /* Clear notification state as going to wait for data. */
@@ -793,10 +797,10 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
} }
/* Whether receiving a discrete message (where xBytesToStoreMessageLength /* Whether receiving a discrete message (where xBytesToStoreMessageLength
holds the number of bytes used to store the message length) or a stream of * holds the number of bytes used to store the message length) or a stream of
bytes (where xBytesToStoreMessageLength is zero), the number of bytes * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
available must be greater than xBytesToStoreMessageLength to be able to * available must be greater than xBytesToStoreMessageLength to be able to
read bytes from the buffer. */ * read bytes from the buffer. */
if( xBytesAvailable > xBytesToStoreMessageLength ) if( xBytesAvailable > xBytesToStoreMessageLength )
{ {
xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
@@ -824,9 +828,9 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xReturn, xBytesAvailable, xOriginalTail; size_t xReturn, xBytesAvailable, xOriginalTail;
configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn; configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -834,14 +838,15 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{ {
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH ) if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
{ {
/* The number of bytes available is greater than the number of bytes /* The number of bytes available is greater than the number of bytes
required to hold the length of the next message, so another message * required to hold the length of the next message, so another message
is available. Return its length without removing the length bytes * is available. Return its length without removing the length bytes
from the buffer. A copy of the tail is stored so the buffer can be * from the buffer. A copy of the tail is stored so the buffer can be
returned to its prior state as the message is not actually being * returned to its prior state as the message is not actually being
removed from the buffer. */ * removed from the buffer. */
xOriginalTail = pxStreamBuffer->xTail; xOriginalTail = pxStreamBuffer->xTail;
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable ); ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable );
xReturn = ( size_t ) xTempReturn; xReturn = ( size_t ) xTempReturn;
@@ -850,9 +855,9 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
else else
{ {
/* The minimum amount of bytes in a message buffer is /* The minimum amount of bytes in a message buffer is
( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is * ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid * less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
value is 0. */ * value is 0. */
configASSERT( xBytesAvailable == 0 ); configASSERT( xBytesAvailable == 0 );
xReturn = 0; xReturn = 0;
} }
@@ -867,21 +872,21 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
void *pvRxData, void * pvRxData,
size_t xBufferLengthBytes, size_t xBufferLengthBytes,
BaseType_t * const pxHigherPriorityTaskWoken ) BaseType_t * const pxHigherPriorityTaskWoken )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
configASSERT( pvRxData ); configASSERT( pvRxData );
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
/* This receive function is used by both message buffers, which store /* This receive function is used by both message buffers, which store
discrete messages, and stream buffers, which store a continuous stream of * discrete messages, and stream buffers, which store a continuous stream of
bytes. Discrete messages include an additional * bytes. Discrete messages include an additional
sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
message. */ * message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{ {
xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
@@ -894,10 +899,10 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
/* Whether receiving a discrete message (where xBytesToStoreMessageLength /* Whether receiving a discrete message (where xBytesToStoreMessageLength
holds the number of bytes used to store the message length) or a stream of * holds the number of bytes used to store the message length) or a stream of
bytes (where xBytesToStoreMessageLength is zero), the number of bytes * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
available must be greater than xBytesToStoreMessageLength to be able to * available must be greater than xBytesToStoreMessageLength to be able to
read bytes from the buffer. */ * read bytes from the buffer. */
if( xBytesAvailable > xBytesToStoreMessageLength ) if( xBytesAvailable > xBytesToStoreMessageLength )
{ {
xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
@@ -923,36 +928,36 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
void *pvRxData, void * pvRxData,
size_t xBufferLengthBytes, size_t xBufferLengthBytes,
size_t xBytesAvailable, size_t xBytesAvailable,
size_t xBytesToStoreMessageLength ) size_t xBytesToStoreMessageLength )
{ {
size_t xOriginalTail, xReceivedLength, xNextMessageLength; size_t xOriginalTail, xReceivedLength, xNextMessageLength;
configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength; configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
if( xBytesToStoreMessageLength != ( size_t ) 0 ) if( xBytesToStoreMessageLength != ( size_t ) 0 )
{ {
/* A discrete message is being received. First receive the length /* A discrete message is being received. First receive the length
of the message. A copy of the tail is stored so the buffer can be * of the message. A copy of the tail is stored so the buffer can be
returned to its prior state if the length of the message is too * returned to its prior state if the length of the message is too
large for the provided buffer. */ * large for the provided buffer. */
xOriginalTail = pxStreamBuffer->xTail; xOriginalTail = pxStreamBuffer->xTail;
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable ); ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
xNextMessageLength = ( size_t ) xTempNextMessageLength; xNextMessageLength = ( size_t ) xTempNextMessageLength;
/* Reduce the number of bytes available by the number of bytes just /* Reduce the number of bytes available by the number of bytes just
read out. */ * read out. */
xBytesAvailable -= xBytesToStoreMessageLength; xBytesAvailable -= xBytesToStoreMessageLength;
/* Check there is enough space in the buffer provided by the /* Check there is enough space in the buffer provided by the
user. */ * user. */
if( xNextMessageLength > xBufferLengthBytes ) if( xNextMessageLength > xBufferLengthBytes )
{ {
/* The user has provided insufficient space to read the message /* The user has provided insufficient space to read the message
so return the buffer to its previous state (so the length of * so return the buffer to its previous state (so the length of
the message is in the buffer again). */ * the message is in the buffer again). */
pxStreamBuffer->xTail = xOriginalTail; pxStreamBuffer->xTail = xOriginalTail;
xNextMessageLength = 0; xNextMessageLength = 0;
} }
@@ -964,7 +969,7 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
else else
{ {
/* A stream of bytes is being received (as opposed to a discrete /* A stream of bytes is being received (as opposed to a discrete
message), so read as many bytes as possible. */ * message), so read as many bytes as possible. */
xNextMessageLength = xBufferLengthBytes; xNextMessageLength = xBufferLengthBytes;
} }
@@ -977,14 +982,15 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
{ {
const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn; BaseType_t xReturn;
size_t xTail; size_t xTail;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
/* True if no bytes are available. */ /* True if no bytes are available. */
xTail = pxStreamBuffer->xTail; xTail = pxStreamBuffer->xTail;
if( pxStreamBuffer->xHead == xTail ) if( pxStreamBuffer->xHead == xTail )
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
@@ -1000,16 +1006,16 @@ size_t xTail;
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
{ {
BaseType_t xReturn; BaseType_t xReturn;
size_t xBytesToStoreMessageLength; size_t xBytesToStoreMessageLength;
const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
/* This generic version of the receive function is used by both message /* This generic version of the receive function is used by both message
buffers, which store discrete messages, and stream buffers, which store a * buffers, which store discrete messages, and stream buffers, which store a
continuous stream of bytes. Discrete messages include an additional * continuous stream of bytes. Discrete messages include an additional
sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */ * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{ {
xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
@@ -1033,11 +1039,12 @@ const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn; BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -1063,11 +1070,12 @@ UBaseType_t uxSavedInterruptStatus;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken )
{ {
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn; BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@@ -1093,17 +1101,19 @@ UBaseType_t uxSavedInterruptStatus;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
const uint8_t * pucData,
size_t xCount )
{ {
size_t xNextHead, xFirstLength; size_t xNextHead, xFirstLength;
configASSERT( xCount > ( size_t ) 0 ); configASSERT( xCount > ( size_t ) 0 );
xNextHead = pxStreamBuffer->xHead; xNextHead = pxStreamBuffer->xHead;
/* Calculate the number of bytes that can be added in the first write - /* Calculate the number of bytes that can be added in the first write -
which may be less than the total number of bytes that need to be added if * which may be less than the total number of bytes that need to be added if
the buffer will wrap back to the beginning. */ * the buffer will wrap back to the beginning. */
xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount ); xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
/* Write as many bytes as can be written in the first write. */ /* Write as many bytes as can be written in the first write. */
@@ -1111,7 +1121,7 @@ size_t xNextHead, xFirstLength;
( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ ( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
/* If the number of bytes written was less than the number that could be /* If the number of bytes written was less than the number that could be
written in the first write... */ * written in the first write... */
if( xCount > xFirstLength ) if( xCount > xFirstLength )
{ {
/* ...then write the remaining bytes to the start of the buffer. */ /* ...then write the remaining bytes to the start of the buffer. */
@@ -1124,6 +1134,7 @@ size_t xNextHead, xFirstLength;
} }
xNextHead += xCount; xNextHead += xCount;
if( xNextHead >= pxStreamBuffer->xLength ) if( xNextHead >= pxStreamBuffer->xLength )
{ {
xNextHead -= pxStreamBuffer->xLength; xNextHead -= pxStreamBuffer->xLength;
@@ -1139,9 +1150,12 @@ size_t xNextHead, xFirstLength;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, uint8_t *pucData, size_t xMaxCount, size_t xBytesAvailable ) static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
uint8_t * pucData,
size_t xMaxCount,
size_t xBytesAvailable )
{ {
size_t xCount, xFirstLength, xNextTail; size_t xCount, xFirstLength, xNextTail;
/* Use the minimum of the wanted bytes and the available bytes. */ /* Use the minimum of the wanted bytes and the available bytes. */
xCount = configMIN( xBytesAvailable, xMaxCount ); xCount = configMIN( xBytesAvailable, xMaxCount );
@@ -1151,18 +1165,18 @@ size_t xCount, xFirstLength, xNextTail;
xNextTail = pxStreamBuffer->xTail; xNextTail = pxStreamBuffer->xTail;
/* Calculate the number of bytes that can be read - which may be /* Calculate the number of bytes that can be read - which may be
less than the number wanted if the data wraps around to the start of * less than the number wanted if the data wraps around to the start of
the buffer. */ * the buffer. */
xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount ); xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount );
/* Obtain the number of bytes it is possible to obtain in the first /* Obtain the number of bytes it is possible to obtain in the first
read. Asserts check bounds of read and write. */ * read. Asserts check bounds of read and write. */
configASSERT( xFirstLength <= xMaxCount ); configASSERT( xFirstLength <= xMaxCount );
configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength ); configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength );
( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */ ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */
/* If the total number of wanted bytes is greater than the number /* If the total number of wanted bytes is greater than the number
that could be read in the first read... */ * that could be read in the first read... */
if( xCount > xFirstLength ) if( xCount > xFirstLength )
{ {
/*...then read the remaining bytes from the start of the buffer. */ /*...then read the remaining bytes from the start of the buffer. */
@@ -1175,7 +1189,7 @@ size_t xCount, xFirstLength, xNextTail;
} }
/* Move the tail pointer to effectively remove the data read from /* Move the tail pointer to effectively remove the data read from
the buffer. */ * the buffer. */
xNextTail += xCount; xNextTail += xCount;
if( xNextTail >= pxStreamBuffer->xLength ) if( xNextTail >= pxStreamBuffer->xLength )
@@ -1197,11 +1211,12 @@ size_t xCount, xFirstLength, xNextTail;
static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
{ {
/* Returns the distance between xTail and xHead. */ /* Returns the distance between xTail and xHead. */
size_t xCount; size_t xCount;
xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead; xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
xCount -= pxStreamBuffer->xTail; xCount -= pxStreamBuffer->xTail;
if ( xCount >= pxStreamBuffer->xLength )
if( xCount >= pxStreamBuffer->xLength )
{ {
xCount -= pxStreamBuffer->xLength; xCount -= pxStreamBuffer->xLength;
} }
@@ -1221,13 +1236,13 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t ucFlags ) uint8_t ucFlags )
{ {
/* Assert here is deliberately writing to the entire buffer to ensure it can /* Assert here is deliberately writing to the entire buffer to ensure it can
be written to without generating exceptions, and is setting the buffer to a * be written to without generating exceptions, and is setting the buffer to a
known value to assist in development/debugging. */ * known value to assist in development/debugging. */
#if( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
/* The value written just has to be identifiable when looking at the /* The value written just has to be identifiable when looking at the
memory. Don't use 0xA5 as that is the stack fill value and could * memory. Don't use 0xA5 as that is the stack fill value and could
result in confusion as to what is actually being observed. */ * result in confusion as to what is actually being observed. */
const BaseType_t xWriteValue = 0x55; const BaseType_t xWriteValue = 0x55;
configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer ); configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
} /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */ } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */
@@ -1253,7 +1268,8 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
UBaseType_t uxStreamBufferNumber )
{ {
xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
} }
@@ -1265,7 +1281,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
{ {
return ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ); return( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER );
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* configUSE_TRACE_FACILITY */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff