| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771 | /* * 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 * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * 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. * * https://www.FreeRTOS.org * https://github.com/FreeRTOS * *//* 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. */#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE/* FreeRTOS includes. */#include "FreeRTOS.h"#include "task.h"#include "timers.h"#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. */#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. */#if configUSE_16_BIT_TICKS == 1    #define eventCLEAR_EVENTS_ON_EXIT_BIT    0x0100U    #define eventUNBLOCKED_DUE_TO_BIT_SET    0x0200U    #define eventWAIT_FOR_ALL_BITS           0x0400U    #define eventEVENT_BITS_CONTROL_BYTES    0xff00U#else    #define eventCLEAR_EVENTS_ON_EXIT_BIT    0x01000000UL    #define eventUNBLOCKED_DUE_TO_BIT_SET    0x02000000UL    #define eventWAIT_FOR_ALL_BITS           0x04000000UL    #define eventEVENT_BITS_CONTROL_BYTES    0xff000000UL#endiftypedef struct EventGroupDef_t{    EventBits_t uxEventBits;    List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */    #if ( configUSE_TRACE_FACILITY == 1 )        UBaseType_t uxEventGroupNumber;    #endif    #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )        uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */    #endif} EventGroup_t;/*-----------------------------------------------------------*//* * Test the bits set in uxCurrentEventBits to see if the wait condition is met. * The wait condition is defined by xWaitForAllBits.  If xWaitForAllBits is * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor * are also set in uxCurrentEventBits.  If xWaitForAllBits is pdFALSE then the * wait condition is met if any of the bits set in uxBitsToWait for are also set * in uxCurrentEventBits. */static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,                                        const EventBits_t uxBitsToWaitFor,                                        const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;/*-----------------------------------------------------------*/#if ( configSUPPORT_STATIC_ALLOCATION == 1 )    EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )    {        EventGroup_t * pxEventBits;        /* A StaticEventGroup_t object must be provided. */        configASSERT( pxEventGroupBuffer );        #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. */                volatile size_t xSize = sizeof( StaticEventGroup_t );                configASSERT( xSize == sizeof( EventGroup_t ) );            } /*lint !e529 xSize is referenced if configASSERT() is defined. */        #endif /* configASSERT_DEFINED */        /* The user has provided a statically allocated event group - use it. */        pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */        if( pxEventBits != NULL )        {            pxEventBits->uxEventBits = 0;            vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );            #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )                {                    /* Both static and dynamic allocation can be used, so note that                     * this event group was created statically in case the event group                     * is later deleted. */                    pxEventBits->ucStaticallyAllocated = pdTRUE;                }            #endif /* configSUPPORT_DYNAMIC_ALLOCATION */            traceEVENT_GROUP_CREATE( pxEventBits );        }        else        {            /* xEventGroupCreateStatic should only ever be called with             * pxEventGroupBuffer pointing to a pre-allocated (compile time             * allocated) StaticEventGroup_t variable. */            traceEVENT_GROUP_CREATE_FAILED();        }        return pxEventBits;    }#endif /* configSUPPORT_STATIC_ALLOCATION *//*-----------------------------------------------------------*/#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )    EventGroupHandle_t xEventGroupCreate( void )    {        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. */        pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */        if( pxEventBits != NULL )        {            pxEventBits->uxEventBits = 0;            vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );            #if ( configSUPPORT_STATIC_ALLOCATION == 1 )                {                    /* Both static and dynamic allocation can be used, so note this                     * event group was allocated statically in case the event group is                     * later deleted. */                    pxEventBits->ucStaticallyAllocated = pdFALSE;                }            #endif /* configSUPPORT_STATIC_ALLOCATION */            traceEVENT_GROUP_CREATE( pxEventBits );        }        else        {            traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */        }        return pxEventBits;    }#endif /* configSUPPORT_DYNAMIC_ALLOCATION *//*-----------------------------------------------------------*/EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,                             const EventBits_t uxBitsToSet,                             const EventBits_t uxBitsToWaitFor,                             TickType_t xTicksToWait ){    EventBits_t uxOriginalBitValue, uxReturn;    EventGroup_t * pxEventBits = xEventGroup;    BaseType_t xAlreadyYielded;    BaseType_t xTimeoutOccurred = pdFALSE;    configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );    configASSERT( uxBitsToWaitFor != 0 );    #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )        {            configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );        }    #endif    vTaskSuspendAll();    {        uxOriginalBitValue = pxEventBits->uxEventBits;        ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );        if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )        {            /* All the rendezvous bits are now set - no need to block. */            uxReturn = ( uxOriginalBitValue | uxBitsToSet );            /* Rendezvous always clear the bits.  They will have been cleared             * already unless this is the only task in the rendezvous. */            pxEventBits->uxEventBits &= ~uxBitsToWaitFor;            xTicksToWait = 0;        }        else        {            if( xTicksToWait != ( TickType_t ) 0 )            {                traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );                /* Store the bits that the calling task is waiting for in the                 * task's event list item so the kernel knows when a match is                 * found.  Then enter the blocked state. */                vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );                /* This assignment is obsolete as uxReturn will get set after                 * the task unblocks, but some compilers mistakenly generate a                 * warning about uxReturn being returned without being set if the                 * assignment is omitted. */                uxReturn = 0;            }            else            {                /* The rendezvous bits were not set, but no block time was                 * specified - just return the current event bit value. */                uxReturn = pxEventBits->uxEventBits;                xTimeoutOccurred = pdTRUE;            }        }    }    xAlreadyYielded = xTaskResumeAll();    if( xTicksToWait != ( TickType_t ) 0 )    {        if( xAlreadyYielded == pdFALSE )        {            portYIELD_WITHIN_API();        }        else        {            mtCOVERAGE_TEST_MARKER();        }        /* The task blocked to wait for its required bits to be set - at this         * point either the required bits were set or the block time expired.  If         * the required bits were set they will have been stored in the task's         * event list item, and they should now be retrieved then cleared. */        uxReturn = uxTaskResetEventItemValue();        if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )        {            /* The task timed out, just return the current event bit value. */            taskENTER_CRITICAL();            {                uxReturn = pxEventBits->uxEventBits;                /* Although the task got here because it timed out before the                 * bits it was waiting for were set, it is possible that since it                 * unblocked another task has set the bits.  If this is the case                 * then it needs to clear the bits before exiting. */                if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )                {                    pxEventBits->uxEventBits &= ~uxBitsToWaitFor;                }                else                {                    mtCOVERAGE_TEST_MARKER();                }            }            taskEXIT_CRITICAL();            xTimeoutOccurred = pdTRUE;        }        else        {            /* The task unblocked because the bits were set. */        }        /* Control bits might be set as the task had blocked should not be         * returned. */        uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;    }    traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );    /* Prevent compiler warnings when trace macros are not used. */    ( void ) xTimeoutOccurred;    return uxReturn;}/*-----------------------------------------------------------*/EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,                                 const EventBits_t uxBitsToWaitFor,                                 const BaseType_t xClearOnExit,                                 const BaseType_t xWaitForAllBits,                                 TickType_t xTicksToWait ){    EventGroup_t * pxEventBits = xEventGroup;    EventBits_t uxReturn, uxControlBits = 0;    BaseType_t xWaitConditionMet, xAlreadyYielded;    BaseType_t xTimeoutOccurred = pdFALSE;    /* Check the user is not attempting to wait on the bits used by the kernel     * itself, and that at least one bit is being requested. */    configASSERT( xEventGroup );    configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );    configASSERT( uxBitsToWaitFor != 0 );    #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )        {            configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );        }    #endif    vTaskSuspendAll();    {        const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;        /* Check to see if the wait condition is already met or not. */        xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );        if( xWaitConditionMet != pdFALSE )        {            /* The wait condition has already been met so there is no need to             * block. */            uxReturn = uxCurrentEventBits;            xTicksToWait = ( TickType_t ) 0;            /* Clear the wait bits if requested to do so. */            if( xClearOnExit != pdFALSE )            {                pxEventBits->uxEventBits &= ~uxBitsToWaitFor;            }            else            {                mtCOVERAGE_TEST_MARKER();            }        }        else if( xTicksToWait == ( TickType_t ) 0 )        {            /* The wait condition has not been met, but no block time was             * specified, so just return the current value. */            uxReturn = uxCurrentEventBits;            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. */            if( xClearOnExit != pdFALSE )            {                uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;            }            else            {                mtCOVERAGE_TEST_MARKER();            }            if( xWaitForAllBits != pdFALSE )            {                uxControlBits |= eventWAIT_FOR_ALL_BITS;            }            else            {                mtCOVERAGE_TEST_MARKER();            }            /* Store the bits that the calling task is waiting for in the             * task's event list item so the kernel knows when a match is             * found.  Then enter the blocked state. */            vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );            /* This is obsolete as it will get set after the task unblocks, but             * some compilers mistakenly generate a warning about the variable             * being returned without being set if it is not done. */            uxReturn = 0;            traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );        }    }    xAlreadyYielded = xTaskResumeAll();    if( xTicksToWait != ( TickType_t ) 0 )    {        if( xAlreadyYielded == pdFALSE )        {            portYIELD_WITHIN_API();        }        else        {            mtCOVERAGE_TEST_MARKER();        }        /* The task blocked to wait for its required bits to be set - at this         * point either the required bits were set or the block time expired.  If         * the required bits were set they will have been stored in the task's         * event list item, and they should now be retrieved then cleared. */        uxReturn = uxTaskResetEventItemValue();        if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )        {            taskENTER_CRITICAL();            {                /* The task timed out, just return the current event bit value. */                uxReturn = pxEventBits->uxEventBits;                /* It is possible that the event bits were updated between this                 * task leaving the Blocked state and running again. */                if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )                {                    if( xClearOnExit != pdFALSE )                    {                        pxEventBits->uxEventBits &= ~uxBitsToWaitFor;                    }                    else                    {                        mtCOVERAGE_TEST_MARKER();                    }                }                else                {                    mtCOVERAGE_TEST_MARKER();                }                xTimeoutOccurred = pdTRUE;            }            taskEXIT_CRITICAL();        }        else        {            /* The task unblocked because the bits were set. */        }        /* The task blocked so control bits may have been set. */        uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;    }    traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );    /* Prevent compiler warnings when trace macros are not used. */    ( void ) xTimeoutOccurred;    return uxReturn;}/*-----------------------------------------------------------*/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. */    configASSERT( xEventGroup );    configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );    taskENTER_CRITICAL();    {        traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );        /* The value returned is the event group value prior to the bits being         * cleared. */        uxReturn = pxEventBits->uxEventBits;        /* Clear the bits. */        pxEventBits->uxEventBits &= ~uxBitsToClear;    }    taskEXIT_CRITICAL();    return uxReturn;}/*-----------------------------------------------------------*/#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )    BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,                                            const EventBits_t uxBitsToClear )    {        BaseType_t xReturn;        traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );        xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */        return xReturn;    }#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) *//*-----------------------------------------------------------*/EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ){    UBaseType_t uxSavedInterruptStatus;    EventGroup_t const * const pxEventBits = xEventGroup;    EventBits_t uxReturn;    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();    {        uxReturn = pxEventBits->uxEventBits;    }    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );    return 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 ){    ListItem_t * pxListItem, * pxNext;    ListItem_t const * pxListEnd;    List_t const * pxList;    EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;    EventGroup_t * pxEventBits = xEventGroup;    BaseType_t xMatchFound = pdFALSE;    /* Check the user is not attempting to set the bits used by the kernel     * itself. */    configASSERT( xEventGroup );    configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );    pxList = &( pxEventBits->xTasksWaitingForBits );    pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. */    vTaskSuspendAll();    {        traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );        pxListItem = listGET_HEAD_ENTRY( pxList );        /* Set the bits. */        pxEventBits->uxEventBits |= uxBitsToSet;        /* See if the new bit value should unblock any tasks. */        while( pxListItem != pxListEnd )        {            pxNext = listGET_NEXT( pxListItem );            uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );            xMatchFound = pdFALSE;            /* Split the bits waited for from the control bits. */            uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;            uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;            if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )            {                /* Just looking for single bit being set. */                if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )                {                    xMatchFound = pdTRUE;                }                else                {                    mtCOVERAGE_TEST_MARKER();                }            }            else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )            {                /* All bits are set. */                xMatchFound = pdTRUE;            }            else            {                /* Need all bits to be set, but not all the bits were set. */            }            if( xMatchFound != pdFALSE )            {                /* The bits match.  Should the bits be cleared on exit? */                if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )                {                    uxBitsToClear |= uxBitsWaitedFor;                }                else                {                    mtCOVERAGE_TEST_MARKER();                }                /* Store the actual event flag value in the task's event list                 * item before removing the task from the event list.  The                 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows                 * that is was unblocked due to its required bits matching, rather                 * than because it timed out. */                vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );            }            /* Move onto the next list item.  Note pxListItem->pxNext is not             * used here as the list item may have been removed from the event list             * and inserted into the ready/pending reading list. */            pxListItem = pxNext;        }        /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT         * bit was set in the control word. */        pxEventBits->uxEventBits &= ~uxBitsToClear;    }    ( void ) xTaskResumeAll();    return pxEventBits->uxEventBits;}/*-----------------------------------------------------------*/void vEventGroupDelete( EventGroupHandle_t xEventGroup ){    EventGroup_t * pxEventBits = xEventGroup;    const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );    vTaskSuspendAll();    {        traceEVENT_GROUP_DELETE( xEventGroup );        while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )        {            /* Unblock the task, returning 0 as the event list is being deleted             * and cannot therefore have any bits set. */            configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );            vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );        }        #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )            {                /* The event group can only have been allocated dynamically - free                 * it again. */                vPortFree( pxEventBits );            }        #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )            {                /* The event group could have been allocated statically or                 * dynamically, so check before attempting to free the memory. */                if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )                {                    vPortFree( pxEventBits );                }                else                {                    mtCOVERAGE_TEST_MARKER();                }            }        #endif /* configSUPPORT_DYNAMIC_ALLOCATION */    }    ( void ) xTaskResumeAll();}/*-----------------------------------------------------------*//* For internal use only - execute a 'set bits' command that was pended from * an interrupt. */void vEventGroupSetBitsCallback( void * pvEventGroup,                                 const uint32_t ulBitsToSet ){    ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*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 ){    ( 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 ){    BaseType_t xWaitConditionMet = pdFALSE;    if( xWaitForAllBits == pdFALSE )    {        /* Task only has to wait for one bit within uxBitsToWaitFor to be         * set.  Is one already set? */        if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )        {            xWaitConditionMet = pdTRUE;        }        else        {            mtCOVERAGE_TEST_MARKER();        }    }    else    {        /* Task has to wait for all the bits in uxBitsToWaitFor to be set.         * Are they set already? */        if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )        {            xWaitConditionMet = pdTRUE;        }        else        {            mtCOVERAGE_TEST_MARKER();        }    }    return xWaitConditionMet;}/*-----------------------------------------------------------*/#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )    BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,                                          const EventBits_t uxBitsToSet,                                          BaseType_t * pxHigherPriorityTaskWoken )    {        BaseType_t xReturn;        traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );        xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */        return xReturn;    }#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) *//*-----------------------------------------------------------*/#if ( configUSE_TRACE_FACILITY == 1 )    UBaseType_t uxEventGroupGetNumber( void * xEventGroup )    {        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. */        if( xEventGroup == NULL )        {            xReturn = 0;        }        else        {            xReturn = pxEventBits->uxEventGroupNumber;        }        return xReturn;    }#endif /* configUSE_TRACE_FACILITY *//*-----------------------------------------------------------*/#if ( configUSE_TRACE_FACILITY == 1 )    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. */    }#endif /* configUSE_TRACE_FACILITY *//*-----------------------------------------------------------*/
 |