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 #if ( configNUMBER_OF_CORES == 1 )
268 portYIELD_WITHIN_API();
270 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
272 vTaskYieldWithinAPI();
274 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
278 mtCOVERAGE_TEST_MARKER();
281 /* The task blocked to wait for its required bits to be set - at this
282 * point either the required bits were set or the block time expired. If
283 * the required bits were set they will have been stored in the task's
284 * event list item, and they should now be retrieved then cleared. */
285 uxReturn = uxTaskResetEventItemValue();
287 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
289 /* The task timed out, just return the current event bit value. */
290 taskENTER_CRITICAL();
292 uxReturn = pxEventBits->uxEventBits;
294 /* Although the task got here because it timed out before the
295 * bits it was waiting for were set, it is possible that since it
296 * unblocked another task has set the bits. If this is the case
297 * then it needs to clear the bits before exiting. */
298 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
300 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
304 mtCOVERAGE_TEST_MARKER();
309 xTimeoutOccurred = pdTRUE;
313 /* The task unblocked because the bits were set. */
316 /* Control bits might be set as the task had blocked should not be
318 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
321 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
323 /* Prevent compiler warnings when trace macros are not used. */
324 ( void ) xTimeoutOccurred;
328 /*-----------------------------------------------------------*/
330 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
331 const EventBits_t uxBitsToWaitFor,
332 const BaseType_t xClearOnExit,
333 const BaseType_t xWaitForAllBits,
334 TickType_t xTicksToWait )
336 EventGroup_t * pxEventBits = xEventGroup;
337 EventBits_t uxReturn, uxControlBits = 0;
338 BaseType_t xWaitConditionMet, xAlreadyYielded;
339 BaseType_t xTimeoutOccurred = pdFALSE;
341 /* Check the user is not attempting to wait on the bits used by the kernel
342 * itself, and that at least one bit is being requested. */
343 configASSERT( xEventGroup );
344 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
345 configASSERT( uxBitsToWaitFor != 0 );
346 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
348 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
354 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
356 /* Check to see if the wait condition is already met or not. */
357 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
359 if( xWaitConditionMet != pdFALSE )
361 /* The wait condition has already been met so there is no need to
363 uxReturn = uxCurrentEventBits;
364 xTicksToWait = ( TickType_t ) 0;
366 /* Clear the wait bits if requested to do so. */
367 if( xClearOnExit != pdFALSE )
369 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
373 mtCOVERAGE_TEST_MARKER();
376 else if( xTicksToWait == ( TickType_t ) 0 )
378 /* The wait condition has not been met, but no block time was
379 * specified, so just return the current value. */
380 uxReturn = uxCurrentEventBits;
381 xTimeoutOccurred = pdTRUE;
385 /* The task is going to block to wait for its required bits to be
386 * set. uxControlBits are used to remember the specified behaviour of
387 * this call to xEventGroupWaitBits() - for use when the event bits
388 * unblock the task. */
389 if( xClearOnExit != pdFALSE )
391 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
395 mtCOVERAGE_TEST_MARKER();
398 if( xWaitForAllBits != pdFALSE )
400 uxControlBits |= eventWAIT_FOR_ALL_BITS;
404 mtCOVERAGE_TEST_MARKER();
407 /* Store the bits that the calling task is waiting for in the
408 * task's event list item so the kernel knows when a match is
409 * found. Then enter the blocked state. */
410 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
412 /* This is obsolete as it will get set after the task unblocks, but
413 * some compilers mistakenly generate a warning about the variable
414 * being returned without being set if it is not done. */
417 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
420 xAlreadyYielded = xTaskResumeAll();
422 if( xTicksToWait != ( TickType_t ) 0 )
424 if( xAlreadyYielded == pdFALSE )
426 #if ( configNUMBER_OF_CORES == 1 )
428 portYIELD_WITHIN_API();
430 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
432 vTaskYieldWithinAPI();
434 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
438 mtCOVERAGE_TEST_MARKER();
441 /* The task blocked to wait for its required bits to be set - at this
442 * point either the required bits were set or the block time expired. If
443 * the required bits were set they will have been stored in the task's
444 * event list item, and they should now be retrieved then cleared. */
445 uxReturn = uxTaskResetEventItemValue();
447 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
449 taskENTER_CRITICAL();
451 /* The task timed out, just return the current event bit value. */
452 uxReturn = pxEventBits->uxEventBits;
454 /* It is possible that the event bits were updated between this
455 * task leaving the Blocked state and running again. */
456 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
458 if( xClearOnExit != pdFALSE )
460 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
464 mtCOVERAGE_TEST_MARKER();
469 mtCOVERAGE_TEST_MARKER();
472 xTimeoutOccurred = pdTRUE;
478 /* The task unblocked because the bits were set. */
481 /* The task blocked so control bits may have been set. */
482 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
485 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
487 /* Prevent compiler warnings when trace macros are not used. */
488 ( void ) xTimeoutOccurred;
492 /*-----------------------------------------------------------*/
494 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
495 const EventBits_t uxBitsToClear )
497 EventGroup_t * pxEventBits = xEventGroup;
498 EventBits_t uxReturn;
500 /* Check the user is not attempting to clear the bits used by the kernel
502 configASSERT( xEventGroup );
503 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
505 taskENTER_CRITICAL();
507 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
509 /* The value returned is the event group value prior to the bits being
511 uxReturn = pxEventBits->uxEventBits;
513 /* Clear the bits. */
514 pxEventBits->uxEventBits &= ~uxBitsToClear;
520 /*-----------------------------------------------------------*/
522 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
524 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
525 const EventBits_t uxBitsToClear )
529 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
530 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. */
535 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
536 /*-----------------------------------------------------------*/
538 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
540 UBaseType_t uxSavedInterruptStatus;
541 EventGroup_t const * const pxEventBits = xEventGroup;
542 EventBits_t uxReturn;
544 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
546 uxReturn = pxEventBits->uxEventBits;
548 taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
551 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
552 /*-----------------------------------------------------------*/
554 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
555 const EventBits_t uxBitsToSet )
557 ListItem_t * pxListItem;
559 ListItem_t const * pxListEnd;
560 List_t const * pxList;
561 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
562 EventGroup_t * pxEventBits = xEventGroup;
563 BaseType_t xMatchFound = pdFALSE;
565 /* Check the user is not attempting to set the bits used by the kernel
567 configASSERT( xEventGroup );
568 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
570 pxList = &( pxEventBits->xTasksWaitingForBits );
571 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. */
574 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
576 pxListItem = listGET_HEAD_ENTRY( pxList );
579 pxEventBits->uxEventBits |= uxBitsToSet;
581 /* See if the new bit value should unblock any tasks. */
582 while( pxListItem != pxListEnd )
584 pxNext = listGET_NEXT( pxListItem );
585 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
586 xMatchFound = pdFALSE;
588 /* Split the bits waited for from the control bits. */
589 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
590 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
592 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
594 /* Just looking for single bit being set. */
595 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
597 xMatchFound = pdTRUE;
601 mtCOVERAGE_TEST_MARKER();
604 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
606 /* All bits are set. */
607 xMatchFound = pdTRUE;
611 /* Need all bits to be set, but not all the bits were set. */
614 if( xMatchFound != pdFALSE )
616 /* The bits match. Should the bits be cleared on exit? */
617 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
619 uxBitsToClear |= uxBitsWaitedFor;
623 mtCOVERAGE_TEST_MARKER();
626 /* Store the actual event flag value in the task's event list
627 * item before removing the task from the event list. The
628 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
629 * that is was unblocked due to its required bits matching, rather
630 * than because it timed out. */
631 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
634 /* Move onto the next list item. Note pxListItem->pxNext is not
635 * used here as the list item may have been removed from the event list
636 * and inserted into the ready/pending reading list. */
640 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
641 * bit was set in the control word. */
642 pxEventBits->uxEventBits &= ~uxBitsToClear;
644 ( void ) xTaskResumeAll();
646 return pxEventBits->uxEventBits;
648 /*-----------------------------------------------------------*/
650 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
652 EventGroup_t * pxEventBits = xEventGroup;
653 const List_t * pxTasksWaitingForBits;
655 configASSERT( pxEventBits );
657 pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
661 traceEVENT_GROUP_DELETE( xEventGroup );
663 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
665 /* Unblock the task, returning 0 as the event list is being deleted
666 * and cannot therefore have any bits set. */
667 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
668 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
671 ( void ) xTaskResumeAll();
673 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
675 /* The event group can only have been allocated dynamically - free
677 vPortFree( pxEventBits );
679 #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
681 /* The event group could have been allocated statically or
682 * dynamically, so check before attempting to free the memory. */
683 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
685 vPortFree( pxEventBits );
689 mtCOVERAGE_TEST_MARKER();
692 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
694 /*-----------------------------------------------------------*/
696 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
697 BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
698 StaticEventGroup_t ** ppxEventGroupBuffer )
701 EventGroup_t * pxEventBits = xEventGroup;
703 configASSERT( pxEventBits );
704 configASSERT( ppxEventGroupBuffer );
706 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
708 /* Check if the event group was statically allocated. */
709 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
711 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
719 #else /* configSUPPORT_DYNAMIC_ALLOCATION */
721 /* Event group must have been statically allocated. */
722 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
725 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
729 #endif /* configSUPPORT_STATIC_ALLOCATION */
730 /*-----------------------------------------------------------*/
732 /* For internal use only - execute a 'set bits' command that was pended from
734 void vEventGroupSetBitsCallback( void * pvEventGroup,
735 const uint32_t ulBitsToSet )
737 ( 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. */
739 /*-----------------------------------------------------------*/
741 /* For internal use only - execute a 'clear bits' command that was pended from
743 void vEventGroupClearBitsCallback( void * pvEventGroup,
744 const uint32_t ulBitsToClear )
746 ( 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. */
748 /*-----------------------------------------------------------*/
750 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
751 const EventBits_t uxBitsToWaitFor,
752 const BaseType_t xWaitForAllBits )
754 BaseType_t xWaitConditionMet = pdFALSE;
756 if( xWaitForAllBits == pdFALSE )
758 /* Task only has to wait for one bit within uxBitsToWaitFor to be
759 * set. Is one already set? */
760 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
762 xWaitConditionMet = pdTRUE;
766 mtCOVERAGE_TEST_MARKER();
771 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
772 * Are they set already? */
773 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
775 xWaitConditionMet = pdTRUE;
779 mtCOVERAGE_TEST_MARKER();
783 return xWaitConditionMet;
785 /*-----------------------------------------------------------*/
787 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
789 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
790 const EventBits_t uxBitsToSet,
791 BaseType_t * pxHigherPriorityTaskWoken )
795 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
796 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. */
801 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
802 /*-----------------------------------------------------------*/
804 #if ( configUSE_TRACE_FACILITY == 1 )
806 UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
809 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. */
811 if( xEventGroup == NULL )
817 xReturn = pxEventBits->uxEventGroupNumber;
823 #endif /* configUSE_TRACE_FACILITY */
824 /*-----------------------------------------------------------*/
826 #if ( configUSE_TRACE_FACILITY == 1 )
828 void vEventGroupSetNumber( void * xEventGroup,
829 UBaseType_t uxEventGroupNumber )
831 ( ( 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. */
834 #endif /* configUSE_TRACE_FACILITY */
835 /*-----------------------------------------------------------*/