2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * SPDX-License-Identifier: MIT
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
29 /* Standard includes. */
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
33 * all the API functions to use the MPU wrappers. That should only be done when
34 * task.h is included from an application file. */
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
37 /* FreeRTOS includes. */
41 #include "event_groups.h"
43 /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
44 * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
45 * for the header files above, but not in this file, in order to generate the
46 * correct privileged Vs unprivileged linkage and placement. */
47 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
49 /* The following bit fields convey control information in a task's event list
50 * item value. It is important they don't clash with the
51 * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
52 #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
53 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
54 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
55 #define eventWAIT_FOR_ALL_BITS 0x0400U
56 #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
57 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
58 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
59 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
60 #define eventWAIT_FOR_ALL_BITS 0x04000000UL
61 #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
62 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
63 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100000000000000ULL
64 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200000000000000ULL
65 #define eventWAIT_FOR_ALL_BITS 0x0400000000000000ULL
66 #define eventEVENT_BITS_CONTROL_BYTES 0xff00000000000000ULL
67 #endif /* if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) */
69 typedef struct EventGroupDef_t
71 EventBits_t uxEventBits;
72 List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */
74 #if ( configUSE_TRACE_FACILITY == 1 )
75 UBaseType_t uxEventGroupNumber;
78 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
79 uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
83 /*-----------------------------------------------------------*/
86 * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
87 * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
88 * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
89 * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
90 * wait condition is met if any of the bits set in uxBitsToWait for are also set
91 * in uxCurrentEventBits.
93 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
94 const EventBits_t uxBitsToWaitFor,
95 const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
97 /*-----------------------------------------------------------*/
99 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
101 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
103 EventGroup_t * pxEventBits;
105 /* A StaticEventGroup_t object must be provided. */
106 configASSERT( pxEventGroupBuffer );
108 #if ( configASSERT_DEFINED == 1 )
110 /* Sanity check that the size of the structure used to declare a
111 * variable of type StaticEventGroup_t equals the size of the real
112 * event group structure. */
113 volatile size_t xSize = sizeof( StaticEventGroup_t );
114 configASSERT( xSize == sizeof( EventGroup_t ) );
115 } /*lint !e529 xSize is referenced if configASSERT() is defined. */
116 #endif /* configASSERT_DEFINED */
118 /* The user has provided a statically allocated event group - use it. */
119 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(). */
121 if( pxEventBits != NULL )
123 pxEventBits->uxEventBits = 0;
124 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
126 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
128 /* Both static and dynamic allocation can be used, so note that
129 * this event group was created statically in case the event group
130 * is later deleted. */
131 pxEventBits->ucStaticallyAllocated = pdTRUE;
133 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
135 traceEVENT_GROUP_CREATE( pxEventBits );
139 /* xEventGroupCreateStatic should only ever be called with
140 * pxEventGroupBuffer pointing to a pre-allocated (compile time
141 * allocated) StaticEventGroup_t variable. */
142 traceEVENT_GROUP_CREATE_FAILED();
148 #endif /* configSUPPORT_STATIC_ALLOCATION */
149 /*-----------------------------------------------------------*/
151 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
153 EventGroupHandle_t xEventGroupCreate( void )
155 EventGroup_t * pxEventBits;
157 /* Allocate the event group. Justification for MISRA deviation as
158 * follows: pvPortMalloc() always ensures returned memory blocks are
159 * aligned per the requirements of the MCU stack. In this case
160 * pvPortMalloc() must return a pointer that is guaranteed to meet the
161 * alignment requirements of the EventGroup_t structure - which (if you
162 * follow it through) is the alignment requirements of the TickType_t type
163 * (EventBits_t being of TickType_t itself). Therefore, whenever the
164 * stack alignment requirements are greater than or equal to the
165 * TickType_t alignment requirements the cast is safe. In other cases,
166 * where the natural word size of the architecture is less than
167 * sizeof( TickType_t ), the TickType_t variables will be accessed in two
168 * or more reads operations, and the alignment requirements is only that
169 * of each individual read. */
170 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
172 if( pxEventBits != NULL )
174 pxEventBits->uxEventBits = 0;
175 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
177 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
179 /* Both static and dynamic allocation can be used, so note this
180 * event group was allocated statically in case the event group is
182 pxEventBits->ucStaticallyAllocated = pdFALSE;
184 #endif /* configSUPPORT_STATIC_ALLOCATION */
186 traceEVENT_GROUP_CREATE( pxEventBits );
190 traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
196 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
197 /*-----------------------------------------------------------*/
199 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
200 const EventBits_t uxBitsToSet,
201 const EventBits_t uxBitsToWaitFor,
202 TickType_t xTicksToWait )
204 EventBits_t uxOriginalBitValue, uxReturn;
205 EventGroup_t * pxEventBits = xEventGroup;
206 BaseType_t xAlreadyYielded;
207 BaseType_t xTimeoutOccurred = pdFALSE;
209 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
210 configASSERT( uxBitsToWaitFor != 0 );
211 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
213 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
219 uxOriginalBitValue = pxEventBits->uxEventBits;
221 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
223 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
225 /* All the rendezvous bits are now set - no need to block. */
226 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
228 /* Rendezvous always clear the bits. They will have been cleared
229 * already unless this is the only task in the rendezvous. */
230 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
236 if( xTicksToWait != ( TickType_t ) 0 )
238 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
240 /* Store the bits that the calling task is waiting for in the
241 * task's event list item so the kernel knows when a match is
242 * found. Then enter the blocked state. */
243 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
245 /* This assignment is obsolete as uxReturn will get set after
246 * the task unblocks, but some compilers mistakenly generate a
247 * warning about uxReturn being returned without being set if the
248 * assignment is omitted. */
253 /* The rendezvous bits were not set, but no block time was
254 * specified - just return the current event bit value. */
255 uxReturn = pxEventBits->uxEventBits;
256 xTimeoutOccurred = pdTRUE;
260 xAlreadyYielded = xTaskResumeAll();
262 if( xTicksToWait != ( TickType_t ) 0 )
264 if( xAlreadyYielded == pdFALSE )
266 portYIELD_WITHIN_API();
270 mtCOVERAGE_TEST_MARKER();
273 /* The task blocked to wait for its required bits to be set - at this
274 * point either the required bits were set or the block time expired. If
275 * the required bits were set they will have been stored in the task's
276 * event list item, and they should now be retrieved then cleared. */
277 uxReturn = uxTaskResetEventItemValue();
279 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
281 /* The task timed out, just return the current event bit value. */
282 taskENTER_CRITICAL();
284 uxReturn = pxEventBits->uxEventBits;
286 /* Although the task got here because it timed out before the
287 * bits it was waiting for were set, it is possible that since it
288 * unblocked another task has set the bits. If this is the case
289 * then it needs to clear the bits before exiting. */
290 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
292 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
296 mtCOVERAGE_TEST_MARKER();
301 xTimeoutOccurred = pdTRUE;
305 /* The task unblocked because the bits were set. */
308 /* Control bits might be set as the task had blocked should not be
310 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
313 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
315 /* Prevent compiler warnings when trace macros are not used. */
316 ( void ) xTimeoutOccurred;
320 /*-----------------------------------------------------------*/
322 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
323 const EventBits_t uxBitsToWaitFor,
324 const BaseType_t xClearOnExit,
325 const BaseType_t xWaitForAllBits,
326 TickType_t xTicksToWait )
328 EventGroup_t * pxEventBits = xEventGroup;
329 EventBits_t uxReturn, uxControlBits = 0;
330 BaseType_t xWaitConditionMet, xAlreadyYielded;
331 BaseType_t xTimeoutOccurred = pdFALSE;
333 /* Check the user is not attempting to wait on the bits used by the kernel
334 * itself, and that at least one bit is being requested. */
335 configASSERT( xEventGroup );
336 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
337 configASSERT( uxBitsToWaitFor != 0 );
338 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
340 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
346 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
348 /* Check to see if the wait condition is already met or not. */
349 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
351 if( xWaitConditionMet != pdFALSE )
353 /* The wait condition has already been met so there is no need to
355 uxReturn = uxCurrentEventBits;
356 xTicksToWait = ( TickType_t ) 0;
358 /* Clear the wait bits if requested to do so. */
359 if( xClearOnExit != pdFALSE )
361 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
365 mtCOVERAGE_TEST_MARKER();
368 else if( xTicksToWait == ( TickType_t ) 0 )
370 /* The wait condition has not been met, but no block time was
371 * specified, so just return the current value. */
372 uxReturn = uxCurrentEventBits;
373 xTimeoutOccurred = pdTRUE;
377 /* The task is going to block to wait for its required bits to be
378 * set. uxControlBits are used to remember the specified behaviour of
379 * this call to xEventGroupWaitBits() - for use when the event bits
380 * unblock the task. */
381 if( xClearOnExit != pdFALSE )
383 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
387 mtCOVERAGE_TEST_MARKER();
390 if( xWaitForAllBits != pdFALSE )
392 uxControlBits |= eventWAIT_FOR_ALL_BITS;
396 mtCOVERAGE_TEST_MARKER();
399 /* Store the bits that the calling task is waiting for in the
400 * task's event list item so the kernel knows when a match is
401 * found. Then enter the blocked state. */
402 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
404 /* This is obsolete as it will get set after the task unblocks, but
405 * some compilers mistakenly generate a warning about the variable
406 * being returned without being set if it is not done. */
409 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
412 xAlreadyYielded = xTaskResumeAll();
414 if( xTicksToWait != ( TickType_t ) 0 )
416 if( xAlreadyYielded == pdFALSE )
418 portYIELD_WITHIN_API();
422 mtCOVERAGE_TEST_MARKER();
425 /* The task blocked to wait for its required bits to be set - at this
426 * point either the required bits were set or the block time expired. If
427 * the required bits were set they will have been stored in the task's
428 * event list item, and they should now be retrieved then cleared. */
429 uxReturn = uxTaskResetEventItemValue();
431 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
433 taskENTER_CRITICAL();
435 /* The task timed out, just return the current event bit value. */
436 uxReturn = pxEventBits->uxEventBits;
438 /* It is possible that the event bits were updated between this
439 * task leaving the Blocked state and running again. */
440 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
442 if( xClearOnExit != pdFALSE )
444 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
448 mtCOVERAGE_TEST_MARKER();
453 mtCOVERAGE_TEST_MARKER();
456 xTimeoutOccurred = pdTRUE;
462 /* The task unblocked because the bits were set. */
465 /* The task blocked so control bits may have been set. */
466 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
469 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
471 /* Prevent compiler warnings when trace macros are not used. */
472 ( void ) xTimeoutOccurred;
476 /*-----------------------------------------------------------*/
478 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
479 const EventBits_t uxBitsToClear )
481 EventGroup_t * pxEventBits = xEventGroup;
482 EventBits_t uxReturn;
484 /* Check the user is not attempting to clear the bits used by the kernel
486 configASSERT( xEventGroup );
487 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
489 taskENTER_CRITICAL();
491 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
493 /* The value returned is the event group value prior to the bits being
495 uxReturn = pxEventBits->uxEventBits;
497 /* Clear the bits. */
498 pxEventBits->uxEventBits &= ~uxBitsToClear;
504 /*-----------------------------------------------------------*/
506 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
508 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
509 const EventBits_t uxBitsToClear )
513 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
514 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. */
519 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
520 /*-----------------------------------------------------------*/
522 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
524 UBaseType_t uxSavedInterruptStatus;
525 EventGroup_t const * const pxEventBits = xEventGroup;
526 EventBits_t uxReturn;
528 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
530 uxReturn = pxEventBits->uxEventBits;
532 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
535 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
536 /*-----------------------------------------------------------*/
538 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
539 const EventBits_t uxBitsToSet )
541 ListItem_t * pxListItem;
543 ListItem_t const * pxListEnd;
544 List_t const * pxList;
545 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
546 EventGroup_t * pxEventBits = xEventGroup;
547 BaseType_t xMatchFound = pdFALSE;
549 /* Check the user is not attempting to set the bits used by the kernel
551 configASSERT( xEventGroup );
552 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
554 pxList = &( pxEventBits->xTasksWaitingForBits );
555 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. */
558 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
560 pxListItem = listGET_HEAD_ENTRY( pxList );
563 pxEventBits->uxEventBits |= uxBitsToSet;
565 /* See if the new bit value should unblock any tasks. */
566 while( pxListItem != pxListEnd )
568 pxNext = listGET_NEXT( pxListItem );
569 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
570 xMatchFound = pdFALSE;
572 /* Split the bits waited for from the control bits. */
573 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
574 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
576 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
578 /* Just looking for single bit being set. */
579 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
581 xMatchFound = pdTRUE;
585 mtCOVERAGE_TEST_MARKER();
588 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
590 /* All bits are set. */
591 xMatchFound = pdTRUE;
595 /* Need all bits to be set, but not all the bits were set. */
598 if( xMatchFound != pdFALSE )
600 /* The bits match. Should the bits be cleared on exit? */
601 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
603 uxBitsToClear |= uxBitsWaitedFor;
607 mtCOVERAGE_TEST_MARKER();
610 /* Store the actual event flag value in the task's event list
611 * item before removing the task from the event list. The
612 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
613 * that is was unblocked due to its required bits matching, rather
614 * than because it timed out. */
615 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
618 /* Move onto the next list item. Note pxListItem->pxNext is not
619 * used here as the list item may have been removed from the event list
620 * and inserted into the ready/pending reading list. */
624 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
625 * bit was set in the control word. */
626 pxEventBits->uxEventBits &= ~uxBitsToClear;
628 ( void ) xTaskResumeAll();
630 return pxEventBits->uxEventBits;
632 /*-----------------------------------------------------------*/
634 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
636 EventGroup_t * pxEventBits = xEventGroup;
637 const List_t * pxTasksWaitingForBits;
639 configASSERT( pxEventBits );
641 pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
645 traceEVENT_GROUP_DELETE( xEventGroup );
647 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
649 /* Unblock the task, returning 0 as the event list is being deleted
650 * and cannot therefore have any bits set. */
651 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
652 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
655 ( void ) xTaskResumeAll();
657 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
659 /* The event group can only have been allocated dynamically - free
661 vPortFree( pxEventBits );
663 #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
665 /* The event group could have been allocated statically or
666 * dynamically, so check before attempting to free the memory. */
667 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
669 vPortFree( pxEventBits );
673 mtCOVERAGE_TEST_MARKER();
676 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
678 /*-----------------------------------------------------------*/
680 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
681 BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
682 StaticEventGroup_t ** ppxEventGroupBuffer )
685 EventGroup_t * pxEventBits = xEventGroup;
687 configASSERT( pxEventBits );
688 configASSERT( ppxEventGroupBuffer );
690 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
692 /* Check if the event group was statically allocated. */
693 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
695 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
703 #else /* configSUPPORT_DYNAMIC_ALLOCATION */
705 /* Event group must have been statically allocated. */
706 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
709 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
713 #endif /* configSUPPORT_STATIC_ALLOCATION */
714 /*-----------------------------------------------------------*/
716 /* For internal use only - execute a 'set bits' command that was pended from
718 void vEventGroupSetBitsCallback( void * pvEventGroup,
719 const uint32_t ulBitsToSet )
721 ( 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. */
723 /*-----------------------------------------------------------*/
725 /* For internal use only - execute a 'clear bits' command that was pended from
727 void vEventGroupClearBitsCallback( void * pvEventGroup,
728 const uint32_t ulBitsToClear )
730 ( 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. */
732 /*-----------------------------------------------------------*/
734 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
735 const EventBits_t uxBitsToWaitFor,
736 const BaseType_t xWaitForAllBits )
738 BaseType_t xWaitConditionMet = pdFALSE;
740 if( xWaitForAllBits == pdFALSE )
742 /* Task only has to wait for one bit within uxBitsToWaitFor to be
743 * set. Is one already set? */
744 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
746 xWaitConditionMet = pdTRUE;
750 mtCOVERAGE_TEST_MARKER();
755 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
756 * Are they set already? */
757 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
759 xWaitConditionMet = pdTRUE;
763 mtCOVERAGE_TEST_MARKER();
767 return xWaitConditionMet;
769 /*-----------------------------------------------------------*/
771 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
773 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
774 const EventBits_t uxBitsToSet,
775 BaseType_t * pxHigherPriorityTaskWoken )
779 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
780 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. */
785 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
786 /*-----------------------------------------------------------*/
788 #if ( configUSE_TRACE_FACILITY == 1 )
790 UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
793 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. */
795 if( xEventGroup == NULL )
801 xReturn = pxEventBits->uxEventGroupNumber;
807 #endif /* configUSE_TRACE_FACILITY */
808 /*-----------------------------------------------------------*/
810 #if ( configUSE_TRACE_FACILITY == 1 )
812 void vEventGroupSetNumber( void * xEventGroup,
813 UBaseType_t uxEventGroupNumber )
815 ( ( 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. */
818 #endif /* configUSE_TRACE_FACILITY */
819 /*-----------------------------------------------------------*/