freertos: Sync safe changes from Amazon SMP branch

This commit is contained in:
Zim Kalinowski 2021-08-10 05:13:43 +08:00
parent 03b361c5a6
commit afc77dbc5a
7 changed files with 9689 additions and 9538 deletions

View File

@ -1,6 +1,6 @@
/*
* 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
* 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
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
#include "FreeRTOS.h"
@ -45,8 +44,8 @@
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
static List_t * pxDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used. */
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. */
/* Other file private variables. --------------------------------*/
@ -99,17 +98,20 @@ 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,
UBaseType_t uxIndex )
{
BaseType_t xReturn;
CRCB_t * pxCoRoutine;
/* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine )
{
/* 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 )
{
pxCurrentCoRoutine = pxCoRoutine;
@ -133,8 +135,8 @@ CRCB_t *pxCoRoutine;
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the ListItem_t.
This is so we can get back to the containing CRCB from a generic item
in a list. */
* This is so we can get back to the containing CRCB from a generic item
* in a list. */
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
@ -142,7 +144,7 @@ CRCB_t *pxCoRoutine;
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
/* Now the co-routine has been initialised it can be added to the ready
list at the correct priority. */
* list at the correct priority. */
prvAddCoRoutineToReadyQueue( pxCoRoutine );
xReturn = pdPASS;
@ -156,17 +158,18 @@ CRCB_t *pxCoRoutine;
}
/*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
List_t * pxEventList )
{
TickType_t xTimeToWake;
/* Calculate the time to wake - this may overflow but this is
not a problem. */
* not a problem. */
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for
both lists. */
* ourselves to the blocked list as the same list item is used for
* both lists. */
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
/* The list item will be inserted in wake time order. */
@ -175,20 +178,20 @@ TickType_t xTimeToWake;
if( xTimeToWake < xCoRoutineTickCount )
{
/* Wake time has overflowed. Place this item in the
overflow list. */
* overflow list. */
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
}
else
{
/* 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 ) );
}
if( pxEventList )
{
/* 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 ) );
}
}
@ -197,8 +200,8 @@ TickType_t xTimeToWake;
static void prvCheckPendingReadyList( void )
{
/* 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
the ready lists itself. */
* are co-routines that have been readied by an ISR. The ISR cannot access
* the ready lists itself. */
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{
CRCB_t * pxUnblockedCRCB;
@ -222,6 +225,7 @@ static void prvCheckDelayedList( void )
CRCB_t * pxCRCB;
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
while( xPassedTicks )
{
xCoRoutineTickCount++;
@ -233,7 +237,7 @@ CRCB_t *pxCRCB;
List_t * pxTemp;
/* Tick count has overflowed so we need to swap the delay lists. If there are
any items in pxDelayedCoRoutineList here then there is an error! */
* any items in pxDelayedCoRoutineList here then there is an error! */
pxTemp = pxDelayedCoRoutineList;
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
pxOverflowDelayedCoRoutineList = pxTemp;
@ -253,10 +257,10 @@ CRCB_t *pxCRCB;
portDISABLE_INTERRUPTS();
{
/* The event could have occurred just before this critical
section. If this is the case then the generic list item will
have been moved to the pending ready list and the following
line is still valid. Also the pvContainer parameter will have
been set to NULL so the following lines are also valid. */
* section. If this is the case then the generic list item will
* have been moved to the pending ready list and the following
* line is still valid. Also the pvContainer parameter will have
* been set to NULL so the following lines are also valid. */
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
/* Is the co-routine waiting on an event also? */
@ -295,7 +299,7 @@ void vCoRoutineSchedule( void )
}
/* 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 ] ) );
/* Call the co-routine. */
@ -319,7 +323,7 @@ UBaseType_t uxPriority;
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
/* Start with pxDelayedCoRoutineList using list1 and the
pxOverflowDelayedCoRoutineList using list2. */
* pxOverflowDelayedCoRoutineList using list2. */
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
}
@ -331,8 +335,8 @@ CRCB_t *pxUnblockedCRCB;
BaseType_t xReturn;
/* This function is called from within an interrupt. It can only access
event lists and the pending ready list. This function assumes that a
check has already been made to ensure pxEventList is not empty. */
* event lists and the pending ready list. This function assumes that a
* check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );

View File

@ -1,6 +1,6 @@
/*
* 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
* 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
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
@ -40,14 +39,14 @@ task.h is included from an application file. */
#include "event_groups.h"
/* 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
for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* for the header files above, but not in this file, in order to generate the
* correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
/* The following bit fields convey control information in a task's event list
item value. It is important they don't clash with the
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
* item value. It is important they don't clash with the
* taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
@ -86,7 +85,9 @@ typedef struct EventGroupDef_t
* wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits.
*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
@ -102,8 +103,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#if ( configASSERT_DEFINED == 1 )
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticEventGroup_t equals the size of the real
event group structure. */
* variable of type StaticEventGroup_t equals the size of the real
* event group structure. */
volatile size_t xSize = sizeof( StaticEventGroup_t );
configASSERT( xSize == sizeof( EventGroup_t ) );
} /*lint !e529 xSize is referenced if configASSERT() is defined. */
@ -120,8 +121,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* Both static and dynamic allocation can be used, so note that
this event group was created statically in case the event group
is later deleted. */
* this event group was created statically in case the event group
* is later deleted. */
pxEventBits->ucStaticallyAllocated = pdTRUE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
@ -133,8 +134,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
else
{
/* xEventGroupCreateStatic should only ever be called with
pxEventGroupBuffer pointing to a pre-allocated (compile time
allocated) StaticEventGroup_t variable. */
* pxEventGroupBuffer pointing to a pre-allocated (compile time
* allocated) StaticEventGroup_t variable. */
traceEVENT_GROUP_CREATE_FAILED();
}
@ -151,18 +152,18 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
EventGroup_t * pxEventBits;
/* Allocate the event group. Justification for MISRA deviation as
follows: pvPortMalloc() always ensures returned memory blocks are
aligned per the requirements of the MCU stack. In this case
pvPortMalloc() must return a pointer that is guaranteed to meet the
alignment requirements of the EventGroup_t structure - which (if you
follow it through) is the alignment requirements of the TickType_t type
(EventBits_t being of TickType_t itself). Therefore, whenever the
stack alignment requirements are greater than or equal to the
TickType_t alignment requirements the cast is safe. In other cases,
where the natural word size of the architecture is less than
sizeof( TickType_t ), the TickType_t variables will be accessed in two
or more reads operations, and the alignment requirements is only that
of each individual read. */
* follows: pvPortMalloc() always ensures returned memory blocks are
* aligned per the requirements of the MCU stack. In this case
* pvPortMalloc() must return a pointer that is guaranteed to meet the
* alignment requirements of the EventGroup_t structure - which (if you
* follow it through) is the alignment requirements of the TickType_t type
* (EventBits_t being of TickType_t itself). Therefore, whenever the
* stack alignment requirements are greater than or equal to the
* TickType_t alignment requirements the cast is safe. In other cases,
* where the natural word size of the architecture is less than
* sizeof( TickType_t ), the TickType_t variables will be accessed in two
* or more reads operations, and the alignment requirements is only that
* of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
if( pxEventBits != NULL )
@ -173,8 +174,8 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* Both static and dynamic allocation can be used, so note this
event group was allocated statically in case the event group is
later deleted. */
* event group was allocated statically in case the event group is
* later deleted. */
pxEventBits->ucStaticallyAllocated = pdFALSE;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
@ -194,7 +195,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
#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;
EventGroup_t * pxEventBits = xEventGroup;
@ -220,7 +224,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
/* 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;
xTicksToWait = 0;
@ -232,20 +236,20 @@ BaseType_t xTimeoutOccurred = pdFALSE;
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
/* Store the bits that the calling task is waiting for in the
task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */
* task's event list item so the kernel knows when a match is
* found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
/* This assignment is obsolete as uxReturn will get set after
the task unblocks, but some compilers mistakenly generate a
warning about uxReturn being returned without being set if the
assignment is omitted. */
* the task unblocks, but some compilers mistakenly generate a
* warning about uxReturn being returned without being set if the
* assignment is omitted. */
uxReturn = 0;
}
else
{
/* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */
* specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
xTimeoutOccurred = pdTRUE;
}
@ -259,9 +263,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
portYIELD_WITHIN_API();
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
the required bits were set they will have been stored in the task's
event list item, and they should now be retrieved then cleared. */
* point either the required bits were set or the block time expired. If
* the required bits were set they will have been stored in the task's
* event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
@ -272,9 +276,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = pxEventBits->uxEventBits;
/* Although the task got here because it timed out before the
bits it was waiting for were set, it is possible that since it
unblocked another task has set the bits. If this is the case
then it needs to clear the bits before exiting. */
* bits it was waiting for were set, it is possible that since it
* unblocked another task has set the bits. If this is the case
* then it needs to clear the bits before exiting. */
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
@ -294,7 +298,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
}
/* Control bits might be set as the task had blocked should not be
returned. */
* returned. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
@ -307,7 +311,11 @@ 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;
EventBits_t uxReturn, uxControlBits = 0;
@ -315,7 +323,7 @@ BaseType_t xWaitConditionMet;
BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel
itself, and that at least one bit is being requested. */
* itself, and that at least one bit is being requested. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
@ -335,7 +343,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
if( xWaitConditionMet != pdFALSE )
{
/* The wait condition has already been met so there is no need to
block. */
* block. */
uxReturn = uxCurrentEventBits;
xTicksToWait = ( TickType_t ) 0;
@ -352,16 +360,16 @@ BaseType_t xTimeoutOccurred = pdFALSE;
else if( xTicksToWait == ( TickType_t ) 0 )
{
/* The wait condition has not been met, but no block time was
specified, so just return the current value. */
* specified, so just return the current value. */
uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE;
}
else
{
/* The task is going to block to wait for its required bits to be
set. uxControlBits are used to remember the specified behaviour of
this call to xEventGroupWaitBits() - for use when the event bits
unblock the task. */
* set. uxControlBits are used to remember the specified behaviour of
* this call to xEventGroupWaitBits() - for use when the event bits
* unblock the task. */
if( xClearOnExit != pdFALSE )
{
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
@ -381,13 +389,13 @@ BaseType_t xTimeoutOccurred = pdFALSE;
}
/* Store the bits that the calling task is waiting for in the
task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */
* task's event list item so the kernel knows when a match is
* found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
/* This is obsolete as it will get set after the task unblocks, but
some compilers mistakenly generate a warning about the variable
being returned without being set if it is not done. */
* some compilers mistakenly generate a warning about the variable
* being returned without being set if it is not done. */
uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
@ -401,9 +409,9 @@ BaseType_t xTimeoutOccurred = pdFALSE;
portYIELD_WITHIN_API();
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
the required bits were set they will have been stored in the task's
event list item, and they should now be retrieved then cleared. */
* point either the required bits were set or the block time expired. If
* the required bits were set they will have been stored in the task's
* event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
@ -414,7 +422,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
uxReturn = pxEventBits->uxEventBits;
/* 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( xClearOnExit != pdFALSE )
@ -430,6 +438,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
{
mtCOVERAGE_TEST_MARKER();
}
xTimeoutOccurred = pdTRUE;
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
@ -442,6 +451,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
/* The task blocked so control bits may have been set. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
/* 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;
EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
itself. */
* itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
@ -466,7 +477,7 @@ EventBits_t uxReturn;
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being
cleared. */
* cleared. */
uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */
@ -480,7 +491,8 @@ EventBits_t uxReturn;
#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;
@ -490,7 +502,7 @@ EventBits_t uxReturn;
return xReturn;
}
#endif
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
@ -509,7 +521,8 @@ EventBits_t uxReturn;
} /*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 const * pxListEnd;
@ -519,7 +532,7 @@ EventGroup_t *pxEventBits = xEventGroup;
BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel
itself. */
* itself. */
configASSERT( xEventGroup );
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
item before removing the task from the event list. The
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather
than because it timed out. */
* item before removing the task from the event list. The
* eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
* that is was unblocked due to its required bits matching, rather
* than because it timed out. */
xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
}
/* Move onto the next list item. Note pxListItem->pxNext is not
used here as the list item may have been removed from the event list
and inserted into the ready/pending reading list. */
* used here as the list item may have been removed from the event list
* and inserted into the ready/pending reading list. */
pxListItem = pxNext;
}
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
bit was set in the control word. */
* bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
@ -616,7 +629,7 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{
/* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */
* and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
@ -626,13 +639,13 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
{
/* The event group can only have been allocated dynamically - free
it again. */
* it again. */
vPortFree( pxEventBits );
}
#elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* The event group could have been allocated statically or
dynamically, so check before attempting to free the memory. */
* dynamically, so check before attempting to free the memory. */
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
{
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
an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
* an interrupt. */
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. */
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'clear bits' command that was pended from
an interrupt. */
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
* an interrupt. */
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. */
}
/*-----------------------------------------------------------*/
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;
if( xWaitForAllBits == pdFALSE )
{
/* 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 )
{
xWaitConditionMet = pdTRUE;
@ -682,7 +699,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
else
{
/* 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 )
{
xWaitConditionMet = pdTRUE;
@ -699,7 +716,9 @@ BaseType_t xWaitConditionMet = pdFALSE;
#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;
@ -709,7 +728,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
return xReturn;
}
#endif
#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
@ -736,7 +755,8 @@ BaseType_t xWaitConditionMet = pdFALSE;
#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. */
}

View File

@ -1,6 +1,6 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* FreeRTOS Kernel V10.4.3
* 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
* 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
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
@ -38,23 +37,23 @@
void vListInitialise( List_t * const pxList )
{
/* The list structure contains a list item which is used to mark the
end of the list. To initialise the list the list end is inserted
as the only list entry. */
* end of the list. To initialise the list the list end is inserted
* 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. */
/* 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;
/* 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.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;
/* 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_2_VALUE( pxList );
}
@ -66,25 +65,26 @@ void vListInitialiseItem( ListItem_t * const pxItem )
pxItem->pxContainer = NULL;
/* 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_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;
/* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */
* the list data structures being overwritten in memory. They will not catch
* data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert a new list item into pxList, but rather than sort the list,
makes the new list item the last item to be removed by a call to
listGET_OWNER_OF_NEXT_ENTRY(). */
* makes the new list item the last item to be removed by a call to
* listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex;
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;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */
* the list data structures being overwritten in memory. They will not catch
* data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert the new list item into the list, sorted in xItemValue order.
If the list already contains a list item with the same item value then the
new list item should be placed after it. This ensures that TCBs which are
stored in ready lists (all of which have the same xItemValue value) get a
share of the CPU. However, if the xItemValue is the same as the back marker
the iteration loop below will not end. Therefore the value is checked
first, and the algorithm slightly modified if necessary. */
*
* If 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
* stored in ready lists (all of which have the same xItemValue value) get a
* share of the CPU. However, if the xItemValue is the same as the back marker
* the iteration loop below will not end. Therefore the value is checked
* first, and the algorithm slightly modified if necessary. */
if( xValueOfInsertion == portMAX_DELAY )
{
pxIterator = pxList->xListEnd.pxPrevious;
@ -127,31 +128,34 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
else
{
/* *** NOTE ***********************************************************
If you find your application is crashing here then likely causes are
listed below. In addition see https://www.freertos.org/FAQHelp.html for
more tips, and ensure configASSERT() is defined!
https://www.freertos.org/a00110.html#configASSERT
1) Stack overflow -
see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M
parts where numerically high priority values denote low actual
interrupt priorities, which can seem counter intuitive. See
https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
of configMAX_SYSCALL_INTERRUPT_PRIORITY on
https://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does
not end in "FromISR" from an interrupt.
4) Using a queue or semaphore before it has been initialised or
before the scheduler has been started (are interrupts firing
before vTaskStartScheduler() has been called?).
* If you find your application is crashing here then likely causes are
* listed below. In addition see https://www.freertos.org/FAQHelp.html for
* more tips, and ensure configASSERT() is defined!
* https://www.freertos.org/a00110.html#configASSERT
*
* 1) Stack overflow -
* see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
* 2) Incorrect interrupt priority assignment, especially on Cortex-M
* parts where numerically high priority values denote low actual
* interrupt priorities, which can seem counter intuitive. See
* https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
* of configMAX_SYSCALL_INTERRUPT_PRIORITY on
* https://www.freertos.org/a00110.html
* 3) Calling an API function from within a critical section or when
* the scheduler is suspended, or calling an API function that does
* not end in "FromISR" from an interrupt.
* 4) Using a queue or semaphore before it has been initialised or
* before the scheduler has been started (are interrupts firing
* before vTaskStartScheduler() has been called?).
* 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. */
{
/* 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;
/* Remember which list the item is in. This allows fast removal of the
item later. */
* item later. */
pxNewListItem->pxContainer = pxList;
( pxList->uxNumberOfItems )++;
@ -171,7 +175,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* The list item knows which list it is in. Obtain the list from the list
item. */
* item. */
List_t * const pxList = pxItemToRemove->pxContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* FreeRTOS Kernel V10.4.3
* 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
* 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
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
@ -30,8 +29,8 @@
#include <string.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
@ -44,15 +43,15 @@ task.h is included from an application file. */
#endif
/* 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
for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* for the header files above, but not in this file, in order to generate the
* correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
/* If the user has not provided application specific Rx notification macros,
or #defined the notification macros away, them provide default implementations
that uses task notifications. */
/*lint -save -e9026 Function like macros allowed and needed here so they can be overidden. */
* or #defined the notification macros away, then provide default implementations
* that uses task notifications. */
/*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */
#ifndef sbRECEIVE_COMPLETED
#define sbRECEIVE_COMPLETED( pxStreamBuffer ) \
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \
@ -90,8 +89,8 @@ that uses task notifications. */
#endif /* sbRECEIVE_COMPLETED_FROM_ISR */
/* If the user has not provided an application specific Tx notification macro,
or #defined the notification macro away, them provide a default implementation
that uses task notifications. */
* or #defined the notification macro away, them provide a default implementation
* that uses task notifications. */
#ifndef sbSEND_COMPLETED
#define sbSEND_COMPLETED( pxStreamBuffer ) \
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \
@ -152,7 +151,6 @@ typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
#endif
portMUX_TYPE xStreamBufferMux; //Mutex required due to SMP
} 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
* 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
@ -218,15 +218,17 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
#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 ucFlags;
/* 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
says how big the next message is) check the buffer will be large enough
to hold at least one message. */
* (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
* to hold at least one message. */
if( xIsMessageBuffer == pdTRUE )
{
/* Is a message buffer but not statically allocated. */
@ -239,23 +241,24 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
ucFlags = 0;
configASSERT( xBufferSizeBytes > 0 );
}
configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
/* 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 )
{
xTriggerLevelBytes = ( size_t ) 1;
}
/* A stream buffer requires a StreamBuffer_t structure and a buffer.
Both are allocated in a single call to pvPortMalloc(). The
StreamBuffer_t structure is placed at the start of the allocated memory
and the buffer follows immediately after. The requested size is
incremented so the free space is returned as the user would expect -
this is a quirk of the implementation that means otherwise the free
space would be reported as one byte smaller than would be logically
expected. */
* Both are allocated in a single call to pvPortMalloc(). The
* StreamBuffer_t structure is placed at the start of the allocated memory
* and the buffer follows immediately after. The requested size is
* incremented so the free space is returned as the user would expect -
* this is a quirk of the implementation that means otherwise the free
* space would be reported as one byte smaller than would be logically
* expected. */
if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) )
{
xBufferSizeBytes++;
@ -304,7 +307,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
/* 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 )
{
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
(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
to hold at least one message. */
* (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
* to hold at least one message. */
configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
#if ( configASSERT_DEFINED == 1 )
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticStreamBuffer_t equals the size of the real
message buffer structure. */
* variable of type StaticStreamBuffer_t equals the size of the real
* message buffer structure. */
volatile size_t xSize = sizeof( StaticStreamBuffer_t );
configASSERT( xSize == sizeof( StreamBuffer_t ) );
} /*lint !e529 xSize is referenced is configASSERT() is defined. */
@ -344,8 +347,9 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags );
/* Remember this was statically allocated in case it is ever deleted
again. */
* again. */
pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
@ -377,13 +381,13 @@ StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* 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(). */
}
#else
{
/* Should not be possible to get here, ucFlags must be corrupt.
Force an assert. */
* Force an assert. */
configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
}
#endif
@ -391,7 +395,7 @@ StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
else
{
/* 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 ) );
}
}
@ -411,7 +415,7 @@ BaseType_t xReturn = pdFAIL;
#if ( configUSE_TRACE_FACILITY == 1 )
{
/* Store the stream buffer number so it can be restored after the
reset. */
* reset. */
uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
}
#endif
@ -446,7 +450,8 @@ 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;
BaseType_t xReturn;
@ -460,7 +465,7 @@ BaseType_t xReturn;
}
/* 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 )
{
pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
@ -525,9 +530,9 @@ TimeOut_t xTimeOut;
configASSERT( pxStreamBuffer );
/* 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
increased by the amount of bytes needed to store the length of the
message. */
* 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
* message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
@ -547,7 +552,7 @@ TimeOut_t xTimeOut;
do
{
/* Wait until the required number of bytes are free in the message
buffer. */
* buffer. */
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux );
{
xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
@ -572,7 +577,6 @@ TimeOut_t xTimeOut;
traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
pxStreamBuffer->xTaskWaitingToSend = NULL;
} while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
}
else
@ -628,9 +632,9 @@ size_t xRequiredSpace = xDataLengthBytes;
configASSERT( pxStreamBuffer );
/* 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
increased by the amount of bytes needed to store the length of the
message. */
* 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
* message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
@ -678,23 +682,23 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
if( xSpace == ( size_t ) 0 )
{
/* 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;
}
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
stream of bytes rather than discrete messages. Write as many bytes as
possible. */
* stream of bytes rather than discrete messages. Write as many bytes as
* possible. */
xShouldWrite = pdTRUE;
xDataLengthBytes = configMIN( xDataLengthBytes, xSpace );
}
else if( xSpace >= xRequiredSpace )
{
/* 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
into the buffer. Start by writing the length of the data, the data
itself will be written later in this function. */
* 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
* itself will be written later in this function. */
xShouldWrite = pdTRUE;
( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH );
}
@ -730,10 +734,10 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
configASSERT( pxStreamBuffer );
/* This receive function is used by both message buffers, which store
discrete messages, and stream buffers, which store a continuous stream of
bytes. Discrete messages include an additional
sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
message. */
* discrete messages, and stream buffers, which store a continuous stream of
* bytes. Discrete messages include an additional
* sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
* message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
@ -746,16 +750,16 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
if( xTicksToWait != ( TickType_t ) 0 )
{
/* Checking if there is data and clearing the notification state must be
performed atomically. */
* performed atomically. */
taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux );
{
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
/* If this function was invoked by a message buffer read then
xBytesToStoreMessageLength holds the number of bytes used to hold
the length of the next discrete message. If this function was
invoked by a stream buffer read then xBytesToStoreMessageLength will
be 0. */
* xBytesToStoreMessageLength holds the number of bytes used to hold
* the length of the next discrete message. If this function was
* invoked by a stream buffer read then xBytesToStoreMessageLength will
* be 0. */
if( xBytesAvailable <= xBytesToStoreMessageLength )
{
/* 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
holds the number of bytes used to store the message length) or a stream of
bytes (where xBytesToStoreMessageLength is zero), the number of bytes
available must be greater than xBytesToStoreMessageLength to be able to
read bytes from the buffer. */
* holds the number of bytes used to store the message length) or a stream of
* bytes (where xBytesToStoreMessageLength is zero), the number of bytes
* available must be greater than xBytesToStoreMessageLength to be able to
* read bytes from the buffer. */
if( xBytesAvailable > xBytesToStoreMessageLength )
{
xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
@ -834,14 +838,15 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
{
/* The number of bytes available is greater than the number of bytes
required to hold the length of the next message, so another message
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
returned to its prior state as the message is not actually being
removed from the buffer. */
* required to hold the length of the next message, so another message
* 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
* returned to its prior state as the message is not actually being
* removed from the buffer. */
xOriginalTail = pxStreamBuffer->xTail;
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable );
xReturn = ( size_t ) xTempReturn;
@ -850,9 +855,9 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
else
{
/* The minimum amount of bytes in a message buffer is
( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
value is 0. */
* ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
* less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
* value is 0. */
configASSERT( xBytesAvailable == 0 );
xReturn = 0;
}
@ -878,10 +883,10 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
configASSERT( pxStreamBuffer );
/* This receive function is used by both message buffers, which store
discrete messages, and stream buffers, which store a continuous stream of
bytes. Discrete messages include an additional
sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
message. */
* discrete messages, and stream buffers, which store a continuous stream of
* bytes. Discrete messages include an additional
* sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
* message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
@ -894,10 +899,10 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
/* Whether receiving a discrete message (where xBytesToStoreMessageLength
holds the number of bytes used to store the message length) or a stream of
bytes (where xBytesToStoreMessageLength is zero), the number of bytes
available must be greater than xBytesToStoreMessageLength to be able to
read bytes from the buffer. */
* holds the number of bytes used to store the message length) or a stream of
* bytes (where xBytesToStoreMessageLength is zero), the number of bytes
* available must be greater than xBytesToStoreMessageLength to be able to
* read bytes from the buffer. */
if( xBytesAvailable > xBytesToStoreMessageLength )
{
xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
@ -935,24 +940,24 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
if( xBytesToStoreMessageLength != ( size_t ) 0 )
{
/* 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
returned to its prior state if the length of the message is too
large for the provided buffer. */
* 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
* large for the provided buffer. */
xOriginalTail = pxStreamBuffer->xTail;
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
xNextMessageLength = ( size_t ) xTempNextMessageLength;
/* Reduce the number of bytes available by the number of bytes just
read out. */
* read out. */
xBytesAvailable -= xBytesToStoreMessageLength;
/* Check there is enough space in the buffer provided by the
user. */
* user. */
if( xNextMessageLength > xBufferLengthBytes )
{
/* The user has provided insufficient space to read the message
so return the buffer to its previous state (so the length of
the message is in the buffer again). */
* so return the buffer to its previous state (so the length of
* the message is in the buffer again). */
pxStreamBuffer->xTail = xOriginalTail;
xNextMessageLength = 0;
}
@ -964,7 +969,7 @@ configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
else
{
/* 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;
}
@ -985,6 +990,7 @@ size_t xTail;
/* True if no bytes are available. */
xTail = pxStreamBuffer->xTail;
if( pxStreamBuffer->xHead == xTail )
{
xReturn = pdTRUE;
@ -1007,9 +1013,9 @@ const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
configASSERT( pxStreamBuffer );
/* This generic version of the receive function is used by both message
buffers, which store discrete messages, and stream buffers, which store a
continuous stream of bytes. Discrete messages include an additional
sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
* buffers, which store discrete messages, and stream buffers, which store a
* continuous stream of bytes. Discrete messages include an additional
* sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
@ -1033,7 +1039,8 @@ 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;
BaseType_t xReturn;
@ -1063,7 +1070,8 @@ 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;
BaseType_t xReturn;
@ -1093,7 +1101,9 @@ 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;
@ -1102,8 +1112,8 @@ size_t xNextHead, xFirstLength;
xNextHead = pxStreamBuffer->xHead;
/* 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
the buffer will wrap back to the beginning. */
* which may be less than the total number of bytes that need to be added if
* the buffer will wrap back to the beginning. */
xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
/* 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 *. */
/* 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 )
{
/* ...then write the remaining bytes to the start of the buffer. */
@ -1124,6 +1134,7 @@ size_t xNextHead, xFirstLength;
}
xNextHead += xCount;
if( xNextHead >= pxStreamBuffer->xLength )
{
xNextHead -= pxStreamBuffer->xLength;
@ -1139,7 +1150,10 @@ 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;
@ -1151,18 +1165,18 @@ size_t xCount, xFirstLength, xNextTail;
xNextTail = pxStreamBuffer->xTail;
/* 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
the buffer. */
* less than the number wanted if the data wraps around to the start of
* the buffer. */
xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount );
/* 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( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength );
( 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
that could be read in the first read... */
* that could be read in the first read... */
if( xCount > xFirstLength )
{
/*...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
the buffer. */
* the buffer. */
xNextTail += xCount;
if( xNextTail >= pxStreamBuffer->xLength )
@ -1201,6 +1215,7 @@ size_t xCount;
xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
xCount -= pxStreamBuffer->xTail;
if( xCount >= pxStreamBuffer->xLength )
{
xCount -= pxStreamBuffer->xLength;
@ -1221,13 +1236,13 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t ucFlags )
{
/* 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
known value to assist in development/debugging. */
* be written to without generating exceptions, and is setting the buffer to a
* known value to assist in development/debugging. */
#if ( configASSERT_DEFINED == 1 )
{
/* 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
result in confusion as to what is actually being observed. */
* memory. Don't use 0xA5 as that is the stack fill value and could
* result in confusion as to what is actually being observed. */
const BaseType_t xWriteValue = 0x55;
configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
} /*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 )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
UBaseType_t uxStreamBufferNumber )
{
xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* 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
* 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
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "FreeRTOS.h"
@ -43,23 +42,23 @@ task.h is included from an application file. */
#endif
/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
for the header files above, but not in this file, in order to generate the
correct privileged Vs unprivileged linkage and placement. */
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* for the header files above, but not in this file, in order to generate the
* correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */
/* This entire source file will be skipped if the application is not configured
to include software timer functionality. This #if is closed at the very bottom
of this file. If you want to include software timer functionality then ensure
configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
* to include software timer functionality. This #if is closed at the very bottom
* of this file. If you want to include software timer functionality then ensure
* configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
#if ( configUSE_TIMERS == 1 )
/* Misc definitions. */
#define tmrNO_DELAY ( TickType_t ) 0U
/* The name assigned to the timer service task. This can be overridden by
defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
* defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
#ifndef configTIMER_SERVICE_TASK_NAME
#define configTIMER_SERVICE_TASK_NAME "Tmr Svc"
#endif
@ -84,14 +83,14 @@ typedef struct tmrTimerControl /* The old naming convention is used to prevent b
} xTIMER;
/* The old xTIMER name is maintained above then typedefed to the new Timer_t
name below to enable the use of older kernel aware debuggers. */
* name below to enable the use of older kernel aware debuggers. */
typedef xTIMER Timer_t;
/* The definition of messages that can be sent and received on the timer queue.
Two types of message can be queued - messages that manipulate a software timer,
and messages that request the execution of a non-timer related callback. The
two message types are defined in two separate structures, xTimerParametersType
and xCallbackParametersType respectively. */
* Two types of message can be queued - messages that manipulate a software timer,
* and messages that request the execution of a non-timer related callback. The
* two message types are defined in two separate structures, xTimerParametersType
* and xCallbackParametersType respectively. */
typedef struct tmrTimerParameters
{
TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */
@ -107,7 +106,7 @@ typedef struct tmrCallbackParameters
} CallbackParameters_t;
/* The structure that contains the two message types, along with an identifier
that is used to determine which message type is valid. */
* that is used to determine which message type is valid. */
typedef struct tmrTimerQueueMessage
{
BaseType_t xMessageID; /*<< The command being sent to the timer service task. */
@ -116,7 +115,7 @@ typedef struct tmrTimerQueueMessage
TimerParameter_t xTimerParameters;
/* Don't include xCallbackParameters if it is not going to be used as
it makes the structure (and therefore the timer queue) larger. */
* it makes the structure (and therefore the timer queue) larger. */
#if ( INCLUDE_xTimerPendFunctionCall == 1 )
CallbackParameters_t xCallbackParameters;
#endif /* INCLUDE_xTimerPendFunctionCall */
@ -124,14 +123,14 @@ typedef struct tmrTimerQueueMessage
} DaemonTaskMessage_t;
/*lint -save -e956 A manual analysis and inspection has been used to determine
which static variables must be declared volatile. */
* which static variables must be declared volatile. */
/* The list in which active timers are stored. Timers are referenced in expire
time order, with the nearest expiry time at the front of the list. Only the
timer service task is allowed to access these lists.
xActiveTimerList1 and xActiveTimerList2 could be at function scope but that
breaks some kernel aware debuggers, and debuggers that reply on removing the
static qualifier. */
* time order, with the nearest expiry time at the front of the list. Only the
* timer service task is allowed to access these lists.
* xActiveTimerList1 and xActiveTimerList2 could be at function scope but that
* breaks some kernel aware debuggers, and debuggers that reply on removing the
* static qualifier. */
PRIVILEGED_DATA static List_t xActiveTimerList1;
PRIVILEGED_DATA static List_t xActiveTimerList2;
PRIVILEGED_DATA static List_t * pxCurrentTimerList;
@ -151,9 +150,9 @@ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED;
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
/* If static allocation is supported then the application must provide the
following callback function - which enables the application to optionally
provide the memory that will be used by the timer task as the task's stack
and TCB. */
* following callback function - which enables the application to optionally
* provide the memory that will be used by the timer task as the task's stack
* and TCB. */
extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );
#endif
@ -181,13 +180,17 @@ static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
* Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
* depending on if the expire time causes a timer counter overflow.
*/
static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer,
const TickType_t xNextExpiryTime,
const TickType_t xTimeNow,
const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
/*
* An active timer has reached its expire time. Reload the timer if it is an
* auto reload timer, then call its callback.
* auto-reload timer, then call its callback.
*/
static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
static void prvProcessExpiredTimer( const TickType_t xNextExpireTime,
const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
/*
* The tick count has overflowed. Switch the timer lists after ensuring the
@ -213,7 +216,8 @@ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIV
* If a timer has expired, process it. Otherwise, block the timer service task
* until either a timer does expire or a command is received.
*/
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime,
BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
/*
* Called after a Timer_t structure has been allocated either statically or
@ -232,9 +236,9 @@ BaseType_t xTimerCreateTimerTask( void )
BaseType_t xReturn = pdFAIL;
/* This function is called when the scheduler is started if
configUSE_TIMERS is set to 1. Check that the infrastructure used by the
timer service task has been created/initialised. If timers have already
been created then the initialisation will already have been performed. */
* configUSE_TIMERS is set to 1. Check that the infrastructure used by the
* timer service task has been created/initialised. If timers have already
* been created then the initialisation will already have been performed. */
prvCheckForValidListAndQueue();
if( xTimerQueue != NULL )
@ -260,7 +264,7 @@ BaseType_t xReturn = pdFAIL;
xReturn = pdPASS;
}
}
#else
#else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
{
xReturn = xTaskCreatePinnedToCore( prvTimerTask,
configTIMER_SERVICE_TASK_NAME,
@ -296,8 +300,8 @@ BaseType_t xReturn = pdFAIL;
if( pxNewTimer != NULL )
{
/* Status is thus far zero as the timer is not created statically
and has not been started. The autoreload bit may get set in
prvInitialiseNewTimer. */
* and has not been started. The auto-reload bit may get set in
* prvInitialiseNewTimer. */
pxNewTimer->ucStatus = 0x00;
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
}
@ -322,8 +326,8 @@ BaseType_t xReturn = pdFAIL;
#if ( configASSERT_DEFINED == 1 )
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticTimer_t equals the size of the real timer
structure. */
* variable of type StaticTimer_t equals the size of the real timer
* structure. */
volatile size_t xSize = sizeof( StaticTimer_t );
configASSERT( xSize == sizeof( Timer_t ) );
( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
@ -337,8 +341,8 @@ BaseType_t xReturn = pdFAIL;
if( pxNewTimer != NULL )
{
/* Timers can be created statically or dynamically so note this
timer was created statically in case it is later deleted. The
autoreload bit may get set in prvInitialiseNewTimer(). */
* timer was created statically in case it is later deleted. The
* auto-reload bit may get set in prvInitialiseNewTimer(). */
pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;
prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
@ -363,26 +367,32 @@ static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e97
if( pxNewTimer != NULL )
{
/* Ensure the infrastructure used by the timer service task has been
created/initialised. */
* created/initialised. */
prvCheckForValidListAndQueue();
/* Initialise the timer structure members using the function
parameters. */
* parameters. */
pxNewTimer->pcTimerName = pcTimerName;
pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
pxNewTimer->pvTimerID = pvTimerID;
pxNewTimer->pxCallbackFunction = pxCallbackFunction;
vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
if( uxAutoReload != pdFALSE )
{
pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
}
traceTIMER_CREATE( pxNewTimer );
}
}
/*-----------------------------------------------------------*/
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer,
const BaseType_t xCommandID,
const TickType_t xOptionalValue,
BaseType_t * const pxHigherPriorityTaskWoken,
const TickType_t xTicksToWait )
{
BaseType_t xReturn = pdFAIL;
DaemonTaskMessage_t xMessage;
@ -390,7 +400,7 @@ DaemonTaskMessage_t xMessage;
configASSERT( xTimer );
/* Send a message to the timer service task to perform a particular action
on a particular timer definition. */
* on a particular timer definition. */
if( xTimerQueue != NULL )
{
/* Send a command to the timer service task to start the xTimer timer. */
@ -428,7 +438,7 @@ DaemonTaskMessage_t xMessage;
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
{
/* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
started, then xTimerTaskHandle will be NULL. */
* started, then xTimerTaskHandle will be NULL. */
configASSERT( ( xTimerTaskHandle != NULL ) );
return xTimerTaskHandle;
}
@ -443,7 +453,8 @@ Timer_t *pxTimer = xTimer;
}
/*-----------------------------------------------------------*/
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload )
void vTimerSetReloadMode( TimerHandle_t xTimer,
const UBaseType_t uxAutoReload )
{
Timer_t * pxTimer = xTimer;
@ -758,11 +769,11 @@ TickType_t xTimeNow;
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
/* In this case the xTimerListsWereSwitched parameter is not used, but
it must be present in the function call. prvSampleTimeNow() must be
called after the message is received from xTimerQueue so there is no
possibility of a higher priority task adding a message to the message
queue with a time that is ahead of the timer daemon task (because it
pre-empted the timer daemon task after the xTimeNow value was set). */
* it must be present in the function call. prvSampleTimeNow() must be
* called after the message is received from xTimerQueue so there is no
* possibility of a higher priority task adding a message to the message
* queue with a time that is ahead of the timer daemon task (because it
* pre-empted the timer daemon task after the xTimeNow value was set). */
xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
switch( xMessage.xMessageID )
@ -774,10 +785,11 @@ TickType_t xTimeNow;
case tmrCOMMAND_START_DONT_TRACE:
/* Start or restart a timer. */
pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )
{
/* The timer expired before it was added to the active
timer list. Process it now. */
* timer list. Process it now. */
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
traceTIMER_EXPIRED( pxTimer );
@ -796,6 +808,7 @@ TickType_t xTimeNow;
{
mtCOVERAGE_TEST_MARKER();
}
break;
case tmrCOMMAND_STOP:
@ -811,11 +824,11 @@ TickType_t xTimeNow;
configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
/* The new period does not really have a reference, and can
be longer or shorter than the old one. The command time is
therefore set to the current time, and as the period cannot
be zero the next expiry time can only be in the future,
meaning (unlike for the xTimerStart() case above) there is
no fail case that needs to be handled here. */
* be longer or shorter than the old one. The command time is
* therefore set to the current time, and as the period cannot
* be zero the next expiry time can only be in the future,
* meaning (unlike for the xTimerStart() case above) there is
* no fail case that needs to be handled here. */
( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
break;
@ -823,8 +836,8 @@ TickType_t xTimeNow;
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* The timer has already been removed from the active list,
just free up the memory if the memory was dynamically
allocated. */
* just free up the memory if the memory was dynamically
* allocated. */
if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 )
{
vPortFree( pxTimer );
@ -834,12 +847,12 @@ TickType_t xTimeNow;
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
}
}
#else
#else /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
{
/* If dynamic allocation is not enabled, the memory
could not have been dynamically allocated. So there is
no need to free the memory - just mark the timer as
"not active". */
* could not have been dynamically allocated. So there is
* no need to free the memory - just mark the timer as
* "not active". */
pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
@ -862,9 +875,9 @@ Timer_t *pxTimer;
BaseType_t xResult;
/* The tick count has overflowed. The timer lists must be switched.
If there are any timers still referenced from the current timer list
then they must have expired and should be processed before the lists
are switched. */
* If there are any timers still referenced from the current timer list
* then they must have expired and should be processed before the lists
* are switched. */
while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )
{
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
@ -875,19 +888,20 @@ BaseType_t xResult;
traceTIMER_EXPIRED( pxTimer );
/* Execute its callback, then send a command to restart the timer if
it is an auto-reload timer. It cannot be restarted here as the lists
have not yet been switched. */
* it is an auto-reload timer. It cannot be restarted here as the lists
* have not yet been switched. */
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
{
/* Calculate the reload value, and if the reload value results in
the timer going into the same timer list then it has already expired
and the timer should be re-inserted into the current list so it is
processed again within this loop. Otherwise a command should be sent
to restart the timer to ensure it is only inserted into a list after
the lists have been swapped. */
* the timer going into the same timer list then it has already expired
* and the timer should be re-inserted into the current list so it is
* processed again within this loop. Otherwise a command should be sent
* to restart the timer to ensure it is only inserted into a list after
* the lists have been swapped. */
xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks );
if( xReloadTime > xNextExpireTime )
{
listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime );
@ -916,8 +930,8 @@ BaseType_t xResult;
static void prvCheckForValidListAndQueue( void )
{
/* Check that the list from which active timers are referenced, and the
queue used to communicate with the timer service, have been
initialised. */
* queue used to communicate with the timer service, have been
* initialised. */
if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux );
@ -933,7 +947,7 @@ static void prvCheckForValidListAndQueue( void )
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* The timer queue is allocated statically in case
configSUPPORT_DYNAMIC_ALLOCATION is 0. */
* configSUPPORT_DYNAMIC_ALLOCATION is 0. */
static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
@ -943,7 +957,7 @@ static void prvCheckForValidListAndQueue( void )
{
xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
}
#endif
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{
@ -1009,7 +1023,8 @@ void *pvReturn;
}
/*-----------------------------------------------------------*/
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID )
void vTimerSetTimerID( TimerHandle_t xTimer,
void * pvNewID )
{
Timer_t * const pxTimer = xTimer;
@ -1025,13 +1040,16 @@ Timer_t * const pxTimer = xTimer;
#if ( INCLUDE_xTimerPendFunctionCall == 1 )
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken )
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
void * pvParameter1,
uint32_t ulParameter2,
BaseType_t * pxHigherPriorityTaskWoken )
{
DaemonTaskMessage_t xMessage;
BaseType_t xReturn;
/* Complete the message with the function parameters and post it to the
daemon task. */
* daemon task. */
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
@ -1049,18 +1067,21 @@ Timer_t * const pxTimer = xTimer;
#if ( INCLUDE_xTimerPendFunctionCall == 1 )
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait )
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
void * pvParameter1,
uint32_t ulParameter2,
TickType_t xTicksToWait )
{
DaemonTaskMessage_t xMessage;
BaseType_t xReturn;
/* This function can only be called after a timer has been created or
after the scheduler has been started because, until then, the timer
queue does not exist. */
* after the scheduler has been started because, until then, the timer
* queue does not exist. */
configASSERT( xTimerQueue );
/* Complete the message with the function parameters and post it to the
daemon task. */
* daemon task. */
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
@ -1088,7 +1109,8 @@ Timer_t * const pxTimer = xTimer;
#if ( configUSE_TRACE_FACILITY == 1 )
void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber )
void vTimerSetTimerNumber( TimerHandle_t xTimer,
UBaseType_t uxTimerNumber )
{
( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber;
}
@ -1097,6 +1119,6 @@ Timer_t * const pxTimer = xTimer;
/*-----------------------------------------------------------*/
/* This entire source file will be skipped if the application is not configured
to include software timer functionality. If you want to include software timer
functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
* to include software timer functionality. If you want to include software timer
* functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
#endif /* configUSE_TIMERS == 1 */