2 * FreeRTOS Kernel V10.3.1
\r
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
27 /* Standard includes. */
\r
30 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
31 all the API functions to use the MPU wrappers. That should only be done when
\r
32 task.h is included from an application file. */
\r
33 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
35 /* FreeRTOS includes. */
\r
36 #include "FreeRTOS.h"
\r
39 #include "event_groups.h"
\r
41 /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
\r
42 because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
\r
43 for the header files above, but not in this file, in order to generate the
\r
44 correct privileged Vs unprivileged linkage and placement. */
\r
45 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
\r
47 /* The following bit fields convey control information in a task's event list
\r
48 item value. It is important they don't clash with the
\r
49 taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
\r
50 #if configUSE_16_BIT_TICKS == 1
\r
51 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
\r
52 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
\r
53 #define eventWAIT_FOR_ALL_BITS 0x0400U
\r
54 #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
\r
56 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
\r
57 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
\r
58 #define eventWAIT_FOR_ALL_BITS 0x04000000UL
\r
59 #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
\r
62 typedef struct EventGroupDef_t
\r
64 EventBits_t uxEventBits;
\r
65 List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
\r
67 #if( configUSE_TRACE_FACILITY == 1 )
\r
68 UBaseType_t uxEventGroupNumber;
\r
71 #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
72 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
\r
76 /*-----------------------------------------------------------*/
\r
79 * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
\r
80 * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
\r
81 * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
\r
82 * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
\r
83 * wait condition is met if any of the bits set in uxBitsToWait for are also set
\r
84 * in uxCurrentEventBits.
\r
86 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
\r
88 /*-----------------------------------------------------------*/
\r
90 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
92 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
\r
94 EventGroup_t *pxEventBits;
\r
96 /* A StaticEventGroup_t object must be provided. */
\r
97 configASSERT( pxEventGroupBuffer );
\r
99 #if( configASSERT_DEFINED == 1 )
\r
101 /* Sanity check that the size of the structure used to declare a
\r
102 variable of type StaticEventGroup_t equals the size of the real
\r
103 event group structure. */
\r
104 volatile size_t xSize = sizeof( StaticEventGroup_t );
\r
105 configASSERT( xSize == sizeof( EventGroup_t ) );
\r
106 } /*lint !e529 xSize is referenced if configASSERT() is defined. */
\r
107 #endif /* configASSERT_DEFINED */
\r
109 /* The user has provided a statically allocated event group - use it. */
\r
110 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(). */
\r
112 if( pxEventBits != NULL )
\r
114 pxEventBits->uxEventBits = 0;
\r
115 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
117 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
119 /* Both static and dynamic allocation can be used, so note that
\r
120 this event group was created statically in case the event group
\r
121 is later deleted. */
\r
122 pxEventBits->ucStaticallyAllocated = pdTRUE;
\r
124 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
126 traceEVENT_GROUP_CREATE( pxEventBits );
\r
130 /* xEventGroupCreateStatic should only ever be called with
\r
131 pxEventGroupBuffer pointing to a pre-allocated (compile time
\r
132 allocated) StaticEventGroup_t variable. */
\r
133 traceEVENT_GROUP_CREATE_FAILED();
\r
136 return pxEventBits;
\r
139 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
140 /*-----------------------------------------------------------*/
\r
142 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
144 EventGroupHandle_t xEventGroupCreate( void )
\r
146 EventGroup_t *pxEventBits;
\r
148 /* Allocate the event group. Justification for MISRA deviation as
\r
149 follows: pvPortMalloc() always ensures returned memory blocks are
\r
150 aligned per the requirements of the MCU stack. In this case
\r
151 pvPortMalloc() must return a pointer that is guaranteed to meet the
\r
152 alignment requirements of the EventGroup_t structure - which (if you
\r
153 follow it through) is the alignment requirements of the TickType_t type
\r
154 (EventBits_t being of TickType_t itself). Therefore, whenever the
\r
155 stack alignment requirements are greater than or equal to the
\r
156 TickType_t alignment requirements the cast is safe. In other cases,
\r
157 where the natural word size of the architecture is less than
\r
158 sizeof( TickType_t ), the TickType_t variables will be accessed in two
\r
159 or more reads operations, and the alignment requirements is only that
\r
160 of each individual read. */
\r
161 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
\r
163 if( pxEventBits != NULL )
\r
165 pxEventBits->uxEventBits = 0;
\r
166 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
168 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
170 /* Both static and dynamic allocation can be used, so note this
\r
171 event group was allocated statically in case the event group is
\r
173 pxEventBits->ucStaticallyAllocated = pdFALSE;
\r
175 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
177 traceEVENT_GROUP_CREATE( pxEventBits );
\r
181 traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
\r
184 return pxEventBits;
\r
187 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
188 /*-----------------------------------------------------------*/
\r
190 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
\r
192 EventBits_t uxOriginalBitValue, uxReturn;
\r
193 EventGroup_t *pxEventBits = xEventGroup;
\r
194 BaseType_t xAlreadyYielded;
\r
195 BaseType_t xTimeoutOccurred = pdFALSE;
\r
197 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
198 configASSERT( uxBitsToWaitFor != 0 );
\r
199 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
201 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
207 uxOriginalBitValue = pxEventBits->uxEventBits;
\r
209 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
\r
211 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
213 /* All the rendezvous bits are now set - no need to block. */
\r
214 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
\r
216 /* Rendezvous always clear the bits. They will have been cleared
\r
217 already unless this is the only task in the rendezvous. */
\r
218 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
224 if( xTicksToWait != ( TickType_t ) 0 )
\r
226 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
\r
228 /* Store the bits that the calling task is waiting for in the
\r
229 task's event list item so the kernel knows when a match is
\r
230 found. Then enter the blocked state. */
\r
231 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
\r
233 /* This assignment is obsolete as uxReturn will get set after
\r
234 the task unblocks, but some compilers mistakenly generate a
\r
235 warning about uxReturn being returned without being set if the
\r
236 assignment is omitted. */
\r
241 /* The rendezvous bits were not set, but no block time was
\r
242 specified - just return the current event bit value. */
\r
243 uxReturn = pxEventBits->uxEventBits;
\r
244 xTimeoutOccurred = pdTRUE;
\r
248 xAlreadyYielded = xTaskResumeAll();
\r
250 if( xTicksToWait != ( TickType_t ) 0 )
\r
252 if( xAlreadyYielded == pdFALSE )
\r
254 portYIELD_WITHIN_API();
\r
258 mtCOVERAGE_TEST_MARKER();
\r
261 /* The task blocked to wait for its required bits to be set - at this
\r
262 point either the required bits were set or the block time expired. If
\r
263 the required bits were set they will have been stored in the task's
\r
264 event list item, and they should now be retrieved then cleared. */
\r
265 uxReturn = uxTaskResetEventItemValue();
\r
267 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
269 /* The task timed out, just return the current event bit value. */
\r
270 taskENTER_CRITICAL();
\r
272 uxReturn = pxEventBits->uxEventBits;
\r
274 /* Although the task got here because it timed out before the
\r
275 bits it was waiting for were set, it is possible that since it
\r
276 unblocked another task has set the bits. If this is the case
\r
277 then it needs to clear the bits before exiting. */
\r
278 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
280 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
284 mtCOVERAGE_TEST_MARKER();
\r
287 taskEXIT_CRITICAL();
\r
289 xTimeoutOccurred = pdTRUE;
\r
293 /* The task unblocked because the bits were set. */
\r
296 /* Control bits might be set as the task had blocked should not be
\r
298 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
301 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
\r
303 /* Prevent compiler warnings when trace macros are not used. */
\r
304 ( void ) xTimeoutOccurred;
\r
308 /*-----------------------------------------------------------*/
\r
310 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
\r
312 EventGroup_t *pxEventBits = xEventGroup;
\r
313 EventBits_t uxReturn, uxControlBits = 0;
\r
314 BaseType_t xWaitConditionMet, xAlreadyYielded;
\r
315 BaseType_t xTimeoutOccurred = pdFALSE;
\r
317 /* Check the user is not attempting to wait on the bits used by the kernel
\r
318 itself, and that at least one bit is being requested. */
\r
319 configASSERT( xEventGroup );
\r
320 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
321 configASSERT( uxBitsToWaitFor != 0 );
\r
322 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
324 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
330 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
\r
332 /* Check to see if the wait condition is already met or not. */
\r
333 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
\r
335 if( xWaitConditionMet != pdFALSE )
\r
337 /* The wait condition has already been met so there is no need to
\r
339 uxReturn = uxCurrentEventBits;
\r
340 xTicksToWait = ( TickType_t ) 0;
\r
342 /* Clear the wait bits if requested to do so. */
\r
343 if( xClearOnExit != pdFALSE )
\r
345 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
349 mtCOVERAGE_TEST_MARKER();
\r
352 else if( xTicksToWait == ( TickType_t ) 0 )
\r
354 /* The wait condition has not been met, but no block time was
\r
355 specified, so just return the current value. */
\r
356 uxReturn = uxCurrentEventBits;
\r
357 xTimeoutOccurred = pdTRUE;
\r
361 /* The task is going to block to wait for its required bits to be
\r
362 set. uxControlBits are used to remember the specified behaviour of
\r
363 this call to xEventGroupWaitBits() - for use when the event bits
\r
364 unblock the task. */
\r
365 if( xClearOnExit != pdFALSE )
\r
367 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
\r
371 mtCOVERAGE_TEST_MARKER();
\r
374 if( xWaitForAllBits != pdFALSE )
\r
376 uxControlBits |= eventWAIT_FOR_ALL_BITS;
\r
380 mtCOVERAGE_TEST_MARKER();
\r
383 /* Store the bits that the calling task is waiting for in the
\r
384 task's event list item so the kernel knows when a match is
\r
385 found. Then enter the blocked state. */
\r
386 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
\r
388 /* This is obsolete as it will get set after the task unblocks, but
\r
389 some compilers mistakenly generate a warning about the variable
\r
390 being returned without being set if it is not done. */
\r
393 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
\r
396 xAlreadyYielded = xTaskResumeAll();
\r
398 if( xTicksToWait != ( TickType_t ) 0 )
\r
400 if( xAlreadyYielded == pdFALSE )
\r
402 portYIELD_WITHIN_API();
\r
406 mtCOVERAGE_TEST_MARKER();
\r
409 /* The task blocked to wait for its required bits to be set - at this
\r
410 point either the required bits were set or the block time expired. If
\r
411 the required bits were set they will have been stored in the task's
\r
412 event list item, and they should now be retrieved then cleared. */
\r
413 uxReturn = uxTaskResetEventItemValue();
\r
415 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
417 taskENTER_CRITICAL();
\r
419 /* The task timed out, just return the current event bit value. */
\r
420 uxReturn = pxEventBits->uxEventBits;
\r
422 /* It is possible that the event bits were updated between this
\r
423 task leaving the Blocked state and running again. */
\r
424 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
\r
426 if( xClearOnExit != pdFALSE )
\r
428 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
432 mtCOVERAGE_TEST_MARKER();
\r
437 mtCOVERAGE_TEST_MARKER();
\r
439 xTimeoutOccurred = pdTRUE;
\r
441 taskEXIT_CRITICAL();
\r
445 /* The task unblocked because the bits were set. */
\r
448 /* The task blocked so control bits may have been set. */
\r
449 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
451 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
\r
453 /* Prevent compiler warnings when trace macros are not used. */
\r
454 ( void ) xTimeoutOccurred;
\r
458 /*-----------------------------------------------------------*/
\r
460 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
\r
462 EventGroup_t *pxEventBits = xEventGroup;
\r
463 EventBits_t uxReturn;
\r
465 /* Check the user is not attempting to clear the bits used by the kernel
\r
467 configASSERT( xEventGroup );
\r
468 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
470 taskENTER_CRITICAL();
\r
472 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
\r
474 /* The value returned is the event group value prior to the bits being
\r
476 uxReturn = pxEventBits->uxEventBits;
\r
478 /* Clear the bits. */
\r
479 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
481 taskEXIT_CRITICAL();
\r
485 /*-----------------------------------------------------------*/
\r
487 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
489 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
\r
491 BaseType_t xReturn;
\r
493 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
\r
494 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. */
\r
500 /*-----------------------------------------------------------*/
\r
502 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
\r
504 UBaseType_t uxSavedInterruptStatus;
\r
505 EventGroup_t const * const pxEventBits = xEventGroup;
\r
506 EventBits_t uxReturn;
\r
508 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
510 uxReturn = pxEventBits->uxEventBits;
\r
512 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
515 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
\r
516 /*-----------------------------------------------------------*/
\r
518 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
\r
520 ListItem_t *pxListItem, *pxNext;
\r
521 ListItem_t const *pxListEnd;
\r
522 List_t const * pxList;
\r
523 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
\r
524 EventGroup_t *pxEventBits = xEventGroup;
\r
525 BaseType_t xMatchFound = pdFALSE;
\r
527 /* Check the user is not attempting to set the bits used by the kernel
\r
529 configASSERT( xEventGroup );
\r
530 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
532 pxList = &( pxEventBits->xTasksWaitingForBits );
\r
533 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. */
\r
536 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
\r
538 pxListItem = listGET_HEAD_ENTRY( pxList );
\r
540 /* Set the bits. */
\r
541 pxEventBits->uxEventBits |= uxBitsToSet;
\r
543 /* See if the new bit value should unblock any tasks. */
\r
544 while( pxListItem != pxListEnd )
\r
546 pxNext = listGET_NEXT( pxListItem );
\r
547 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
\r
548 xMatchFound = pdFALSE;
\r
550 /* Split the bits waited for from the control bits. */
\r
551 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
\r
552 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
554 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
\r
556 /* Just looking for single bit being set. */
\r
557 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
\r
559 xMatchFound = pdTRUE;
\r
563 mtCOVERAGE_TEST_MARKER();
\r
566 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
\r
568 /* All bits are set. */
\r
569 xMatchFound = pdTRUE;
\r
573 /* Need all bits to be set, but not all the bits were set. */
\r
576 if( xMatchFound != pdFALSE )
\r
578 /* The bits match. Should the bits be cleared on exit? */
\r
579 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
\r
581 uxBitsToClear |= uxBitsWaitedFor;
\r
585 mtCOVERAGE_TEST_MARKER();
\r
588 /* Store the actual event flag value in the task's event list
\r
589 item before removing the task from the event list. The
\r
590 eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
\r
591 that is was unblocked due to its required bits matching, rather
\r
592 than because it timed out. */
\r
593 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
\r
596 /* Move onto the next list item. Note pxListItem->pxNext is not
\r
597 used here as the list item may have been removed from the event list
\r
598 and inserted into the ready/pending reading list. */
\r
599 pxListItem = pxNext;
\r
602 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
\r
603 bit was set in the control word. */
\r
604 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
606 ( void ) xTaskResumeAll();
\r
608 return pxEventBits->uxEventBits;
\r
610 /*-----------------------------------------------------------*/
\r
612 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
\r
614 EventGroup_t *pxEventBits = xEventGroup;
\r
615 const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
\r
619 traceEVENT_GROUP_DELETE( xEventGroup );
\r
621 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
\r
623 /* Unblock the task, returning 0 as the event list is being deleted
\r
624 and cannot therefore have any bits set. */
\r
625 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
\r
626 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
\r
629 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
\r
631 /* The event group can only have been allocated dynamically - free
\r
633 vPortFree( pxEventBits );
\r
635 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
\r
637 /* The event group could have been allocated statically or
\r
638 dynamically, so check before attempting to free the memory. */
\r
639 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
\r
641 vPortFree( pxEventBits );
\r
645 mtCOVERAGE_TEST_MARKER();
\r
648 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
650 ( void ) xTaskResumeAll();
\r
652 /*-----------------------------------------------------------*/
\r
654 /* For internal use only - execute a 'set bits' command that was pended from
\r
656 void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
\r
658 ( 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. */
\r
660 /*-----------------------------------------------------------*/
\r
662 /* For internal use only - execute a 'clear bits' command that was pended from
\r
664 void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
\r
666 ( 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. */
\r
668 /*-----------------------------------------------------------*/
\r
670 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
\r
672 BaseType_t xWaitConditionMet = pdFALSE;
\r
674 if( xWaitForAllBits == pdFALSE )
\r
676 /* Task only has to wait for one bit within uxBitsToWaitFor to be
\r
677 set. Is one already set? */
\r
678 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
\r
680 xWaitConditionMet = pdTRUE;
\r
684 mtCOVERAGE_TEST_MARKER();
\r
689 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
\r
690 Are they set already? */
\r
691 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
693 xWaitConditionMet = pdTRUE;
\r
697 mtCOVERAGE_TEST_MARKER();
\r
701 return xWaitConditionMet;
\r
703 /*-----------------------------------------------------------*/
\r
705 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
707 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
\r
709 BaseType_t xReturn;
\r
711 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
\r
712 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. */
\r
718 /*-----------------------------------------------------------*/
\r
720 #if (configUSE_TRACE_FACILITY == 1)
\r
722 UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
\r
724 UBaseType_t xReturn;
\r
725 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. */
\r
727 if( xEventGroup == NULL )
\r
733 xReturn = pxEventBits->uxEventGroupNumber;
\r
739 #endif /* configUSE_TRACE_FACILITY */
\r
740 /*-----------------------------------------------------------*/
\r
742 #if ( configUSE_TRACE_FACILITY == 1 )
\r
744 void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
\r
746 ( ( 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. */
\r
749 #endif /* configUSE_TRACE_FACILITY */
\r
750 /*-----------------------------------------------------------*/
\r