2 * FreeRTOS Kernel V10.2.1
\r
3 * Copyright (C) 2019 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
25 * 1 tab == 4 spaces!
\r
28 /* Standard includes. */
\r
31 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
32 all the API functions to use the MPU wrappers. That should only be done when
\r
33 task.h is included from an application file. */
\r
34 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
36 /* FreeRTOS includes. */
\r
37 #include "FreeRTOS.h"
\r
40 #include "event_groups.h"
\r
42 /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
\r
43 because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
\r
44 for the header files above, but not in this file, in order to generate the
\r
45 correct privileged Vs unprivileged linkage and placement. */
\r
46 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
\r
48 /* The following bit fields convey control information in a task's event list
\r
49 item value. It is important they don't clash with the
\r
50 taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
\r
51 #if configUSE_16_BIT_TICKS == 1
\r
52 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
\r
53 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
\r
54 #define eventWAIT_FOR_ALL_BITS 0x0400U
\r
55 #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
\r
57 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
\r
58 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
\r
59 #define eventWAIT_FOR_ALL_BITS 0x04000000UL
\r
60 #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
\r
63 typedef struct EventGroupDef_t
\r
65 EventBits_t uxEventBits;
\r
66 List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
\r
68 #if( configUSE_TRACE_FACILITY == 1 )
\r
69 UBaseType_t uxEventGroupNumber;
\r
72 #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
73 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
\r
77 /*-----------------------------------------------------------*/
\r
80 * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
\r
81 * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
\r
82 * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
\r
83 * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
\r
84 * wait condition is met if any of the bits set in uxBitsToWait for are also set
\r
85 * in uxCurrentEventBits.
\r
87 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
\r
89 /*-----------------------------------------------------------*/
\r
91 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
93 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
\r
95 EventGroup_t *pxEventBits;
\r
97 /* A StaticEventGroup_t object must be provided. */
\r
98 configASSERT( pxEventGroupBuffer );
\r
100 #if( configASSERT_DEFINED == 1 )
\r
102 /* Sanity check that the size of the structure used to declare a
\r
103 variable of type StaticEventGroup_t equals the size of the real
\r
104 event group structure. */
\r
105 volatile size_t xSize = sizeof( StaticEventGroup_t );
\r
106 configASSERT( xSize == sizeof( EventGroup_t ) );
\r
107 } /*lint !e529 xSize is referenced if configASSERT() is defined. */
\r
108 #endif /* configASSERT_DEFINED */
\r
110 /* The user has provided a statically allocated event group - use it. */
\r
111 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
113 if( pxEventBits != NULL )
\r
115 pxEventBits->uxEventBits = 0;
\r
116 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
118 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
120 /* Both static and dynamic allocation can be used, so note that
\r
121 this event group was created statically in case the event group
\r
122 is later deleted. */
\r
123 pxEventBits->ucStaticallyAllocated = pdTRUE;
\r
125 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
127 traceEVENT_GROUP_CREATE( pxEventBits );
\r
131 /* xEventGroupCreateStatic should only ever be called with
\r
132 pxEventGroupBuffer pointing to a pre-allocated (compile time
\r
133 allocated) StaticEventGroup_t variable. */
\r
134 traceEVENT_GROUP_CREATE_FAILED();
\r
137 return pxEventBits;
\r
140 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
141 /*-----------------------------------------------------------*/
\r
143 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
145 EventGroupHandle_t xEventGroupCreate( void )
\r
147 EventGroup_t *pxEventBits;
\r
149 /* Allocate the event group. Justification for MISRA deviation as
\r
150 follows: pvPortMalloc() always ensures returned memory blocks are
\r
151 aligned per the requirements of the MCU stack. In this case
\r
152 pvPortMalloc() must return a pointer that is guaranteed to meet the
\r
153 alignment requirements of the EventGroup_t structure - which (if you
\r
154 follow it through) is the alignment requirements of the TickType_t type
\r
155 (EventBits_t being of TickType_t itself). Therefore, whenever the
\r
156 stack alignment requirements are greater than or equal to the
\r
157 TickType_t alignment requirements the cast is safe. In other cases,
\r
158 where the natural word size of the architecture is less than
\r
159 sizeof( TickType_t ), the TickType_t variables will be accessed in two
\r
160 or more reads operations, and the alignment requirements is only that
\r
161 of each individual read. */
\r
162 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
\r
164 if( pxEventBits != NULL )
\r
166 pxEventBits->uxEventBits = 0;
\r
167 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
169 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
171 /* Both static and dynamic allocation can be used, so note this
\r
172 event group was allocated statically in case the event group is
\r
174 pxEventBits->ucStaticallyAllocated = pdFALSE;
\r
176 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
178 traceEVENT_GROUP_CREATE( pxEventBits );
\r
182 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
185 return pxEventBits;
\r
188 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
189 /*-----------------------------------------------------------*/
\r
191 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
\r
193 EventBits_t uxOriginalBitValue, uxReturn;
\r
194 EventGroup_t *pxEventBits = xEventGroup;
\r
195 BaseType_t xAlreadyYielded;
\r
196 BaseType_t xTimeoutOccurred = pdFALSE;
\r
198 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
199 configASSERT( uxBitsToWaitFor != 0 );
\r
200 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
202 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
208 uxOriginalBitValue = pxEventBits->uxEventBits;
\r
210 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
\r
212 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
214 /* All the rendezvous bits are now set - no need to block. */
\r
215 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
\r
217 /* Rendezvous always clear the bits. They will have been cleared
\r
218 already unless this is the only task in the rendezvous. */
\r
219 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
225 if( xTicksToWait != ( TickType_t ) 0 )
\r
227 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
\r
229 /* Store the bits that the calling task is waiting for in the
\r
230 task's event list item so the kernel knows when a match is
\r
231 found. Then enter the blocked state. */
\r
232 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
\r
234 /* This assignment is obsolete as uxReturn will get set after
\r
235 the task unblocks, but some compilers mistakenly generate a
\r
236 warning about uxReturn being returned without being set if the
\r
237 assignment is omitted. */
\r
242 /* The rendezvous bits were not set, but no block time was
\r
243 specified - just return the current event bit value. */
\r
244 uxReturn = pxEventBits->uxEventBits;
\r
245 xTimeoutOccurred = pdTRUE;
\r
249 xAlreadyYielded = xTaskResumeAll();
\r
251 if( xTicksToWait != ( TickType_t ) 0 )
\r
253 if( xAlreadyYielded == pdFALSE )
\r
255 portYIELD_WITHIN_API();
\r
259 mtCOVERAGE_TEST_MARKER();
\r
262 /* The task blocked to wait for its required bits to be set - at this
\r
263 point either the required bits were set or the block time expired. If
\r
264 the required bits were set they will have been stored in the task's
\r
265 event list item, and they should now be retrieved then cleared. */
\r
266 uxReturn = uxTaskResetEventItemValue();
\r
268 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
270 /* The task timed out, just return the current event bit value. */
\r
271 taskENTER_CRITICAL();
\r
273 uxReturn = pxEventBits->uxEventBits;
\r
275 /* Although the task got here because it timed out before the
\r
276 bits it was waiting for were set, it is possible that since it
\r
277 unblocked another task has set the bits. If this is the case
\r
278 then it needs to clear the bits before exiting. */
\r
279 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
281 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
285 mtCOVERAGE_TEST_MARKER();
\r
288 taskEXIT_CRITICAL();
\r
290 xTimeoutOccurred = pdTRUE;
\r
294 /* The task unblocked because the bits were set. */
\r
297 /* Control bits might be set as the task had blocked should not be
\r
299 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
302 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
\r
304 /* Prevent compiler warnings when trace macros are not used. */
\r
305 ( void ) xTimeoutOccurred;
\r
309 /*-----------------------------------------------------------*/
\r
311 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
\r
313 EventGroup_t *pxEventBits = xEventGroup;
\r
314 EventBits_t uxReturn, uxControlBits = 0;
\r
315 BaseType_t xWaitConditionMet, xAlreadyYielded;
\r
316 BaseType_t xTimeoutOccurred = pdFALSE;
\r
318 /* Check the user is not attempting to wait on the bits used by the kernel
\r
319 itself, and that at least one bit is being requested. */
\r
320 configASSERT( xEventGroup );
\r
321 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
322 configASSERT( uxBitsToWaitFor != 0 );
\r
323 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
325 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
331 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
\r
333 /* Check to see if the wait condition is already met or not. */
\r
334 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
\r
336 if( xWaitConditionMet != pdFALSE )
\r
338 /* The wait condition has already been met so there is no need to
\r
340 uxReturn = uxCurrentEventBits;
\r
341 xTicksToWait = ( TickType_t ) 0;
\r
343 /* Clear the wait bits if requested to do so. */
\r
344 if( xClearOnExit != pdFALSE )
\r
346 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
350 mtCOVERAGE_TEST_MARKER();
\r
353 else if( xTicksToWait == ( TickType_t ) 0 )
\r
355 /* The wait condition has not been met, but no block time was
\r
356 specified, so just return the current value. */
\r
357 uxReturn = uxCurrentEventBits;
\r
358 xTimeoutOccurred = pdTRUE;
\r
362 /* The task is going to block to wait for its required bits to be
\r
363 set. uxControlBits are used to remember the specified behaviour of
\r
364 this call to xEventGroupWaitBits() - for use when the event bits
\r
365 unblock the task. */
\r
366 if( xClearOnExit != pdFALSE )
\r
368 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
\r
372 mtCOVERAGE_TEST_MARKER();
\r
375 if( xWaitForAllBits != pdFALSE )
\r
377 uxControlBits |= eventWAIT_FOR_ALL_BITS;
\r
381 mtCOVERAGE_TEST_MARKER();
\r
384 /* Store the bits that the calling task is waiting for in the
\r
385 task's event list item so the kernel knows when a match is
\r
386 found. Then enter the blocked state. */
\r
387 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
\r
389 /* This is obsolete as it will get set after the task unblocks, but
\r
390 some compilers mistakenly generate a warning about the variable
\r
391 being returned without being set if it is not done. */
\r
394 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
\r
397 xAlreadyYielded = xTaskResumeAll();
\r
399 if( xTicksToWait != ( TickType_t ) 0 )
\r
401 if( xAlreadyYielded == pdFALSE )
\r
403 portYIELD_WITHIN_API();
\r
407 mtCOVERAGE_TEST_MARKER();
\r
410 /* The task blocked to wait for its required bits to be set - at this
\r
411 point either the required bits were set or the block time expired. If
\r
412 the required bits were set they will have been stored in the task's
\r
413 event list item, and they should now be retrieved then cleared. */
\r
414 uxReturn = uxTaskResetEventItemValue();
\r
416 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
418 taskENTER_CRITICAL();
\r
420 /* The task timed out, just return the current event bit value. */
\r
421 uxReturn = pxEventBits->uxEventBits;
\r
423 /* It is possible that the event bits were updated between this
\r
424 task leaving the Blocked state and running again. */
\r
425 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
\r
427 if( xClearOnExit != pdFALSE )
\r
429 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
433 mtCOVERAGE_TEST_MARKER();
\r
438 mtCOVERAGE_TEST_MARKER();
\r
440 xTimeoutOccurred = pdTRUE;
\r
442 taskEXIT_CRITICAL();
\r
446 /* The task unblocked because the bits were set. */
\r
449 /* The task blocked so control bits may have been set. */
\r
450 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
452 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
\r
454 /* Prevent compiler warnings when trace macros are not used. */
\r
455 ( void ) xTimeoutOccurred;
\r
459 /*-----------------------------------------------------------*/
\r
461 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
\r
463 EventGroup_t *pxEventBits = xEventGroup;
\r
464 EventBits_t uxReturn;
\r
466 /* Check the user is not attempting to clear the bits used by the kernel
\r
468 configASSERT( xEventGroup );
\r
469 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
471 taskENTER_CRITICAL();
\r
473 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
\r
475 /* The value returned is the event group value prior to the bits being
\r
477 uxReturn = pxEventBits->uxEventBits;
\r
479 /* Clear the bits. */
\r
480 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
482 taskEXIT_CRITICAL();
\r
486 /*-----------------------------------------------------------*/
\r
488 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
490 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
\r
492 BaseType_t xReturn;
\r
494 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
\r
495 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
501 /*-----------------------------------------------------------*/
\r
503 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
\r
505 UBaseType_t uxSavedInterruptStatus;
\r
506 EventGroup_t const * const pxEventBits = xEventGroup;
\r
507 EventBits_t uxReturn;
\r
509 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
511 uxReturn = pxEventBits->uxEventBits;
\r
513 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
516 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
\r
517 /*-----------------------------------------------------------*/
\r
519 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
\r
521 ListItem_t *pxListItem, *pxNext;
\r
522 ListItem_t const *pxListEnd;
\r
523 List_t const * pxList;
\r
524 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
\r
525 EventGroup_t *pxEventBits = xEventGroup;
\r
526 BaseType_t xMatchFound = pdFALSE;
\r
528 /* Check the user is not attempting to set the bits used by the kernel
\r
530 configASSERT( xEventGroup );
\r
531 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
533 pxList = &( pxEventBits->xTasksWaitingForBits );
\r
534 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
537 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
\r
539 pxListItem = listGET_HEAD_ENTRY( pxList );
\r
541 /* Set the bits. */
\r
542 pxEventBits->uxEventBits |= uxBitsToSet;
\r
544 /* See if the new bit value should unblock any tasks. */
\r
545 while( pxListItem != pxListEnd )
\r
547 pxNext = listGET_NEXT( pxListItem );
\r
548 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
\r
549 xMatchFound = pdFALSE;
\r
551 /* Split the bits waited for from the control bits. */
\r
552 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
\r
553 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
555 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
\r
557 /* Just looking for single bit being set. */
\r
558 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
\r
560 xMatchFound = pdTRUE;
\r
564 mtCOVERAGE_TEST_MARKER();
\r
567 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
\r
569 /* All bits are set. */
\r
570 xMatchFound = pdTRUE;
\r
574 /* Need all bits to be set, but not all the bits were set. */
\r
577 if( xMatchFound != pdFALSE )
\r
579 /* The bits match. Should the bits be cleared on exit? */
\r
580 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
\r
582 uxBitsToClear |= uxBitsWaitedFor;
\r
586 mtCOVERAGE_TEST_MARKER();
\r
589 /* Store the actual event flag value in the task's event list
\r
590 item before removing the task from the event list. The
\r
591 eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
\r
592 that is was unblocked due to its required bits matching, rather
\r
593 than because it timed out. */
\r
594 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
\r
597 /* Move onto the next list item. Note pxListItem->pxNext is not
\r
598 used here as the list item may have been removed from the event list
\r
599 and inserted into the ready/pending reading list. */
\r
600 pxListItem = pxNext;
\r
603 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
\r
604 bit was set in the control word. */
\r
605 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
607 ( void ) xTaskResumeAll();
\r
609 return pxEventBits->uxEventBits;
\r
611 /*-----------------------------------------------------------*/
\r
613 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
\r
615 EventGroup_t *pxEventBits = xEventGroup;
\r
616 const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
\r
620 traceEVENT_GROUP_DELETE( xEventGroup );
\r
622 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
\r
624 /* Unblock the task, returning 0 as the event list is being deleted
\r
625 and cannot therefore have any bits set. */
\r
626 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
\r
627 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
\r
630 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
\r
632 /* The event group can only have been allocated dynamically - free
\r
634 vPortFree( pxEventBits );
\r
636 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
\r
638 /* The event group could have been allocated statically or
\r
639 dynamically, so check before attempting to free the memory. */
\r
640 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
\r
642 vPortFree( pxEventBits );
\r
646 mtCOVERAGE_TEST_MARKER();
\r
649 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
651 ( void ) xTaskResumeAll();
\r
653 /*-----------------------------------------------------------*/
\r
655 /* For internal use only - execute a 'set bits' command that was pended from
\r
657 void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
\r
659 ( 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
661 /*-----------------------------------------------------------*/
\r
663 /* For internal use only - execute a 'clear bits' command that was pended from
\r
665 void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
\r
667 ( 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
669 /*-----------------------------------------------------------*/
\r
671 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
\r
673 BaseType_t xWaitConditionMet = pdFALSE;
\r
675 if( xWaitForAllBits == pdFALSE )
\r
677 /* Task only has to wait for one bit within uxBitsToWaitFor to be
\r
678 set. Is one already set? */
\r
679 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
\r
681 xWaitConditionMet = pdTRUE;
\r
685 mtCOVERAGE_TEST_MARKER();
\r
690 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
\r
691 Are they set already? */
\r
692 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
694 xWaitConditionMet = pdTRUE;
\r
698 mtCOVERAGE_TEST_MARKER();
\r
702 return xWaitConditionMet;
\r
704 /*-----------------------------------------------------------*/
\r
706 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
708 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
\r
710 BaseType_t xReturn;
\r
712 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
\r
713 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
719 /*-----------------------------------------------------------*/
\r
721 #if (configUSE_TRACE_FACILITY == 1)
\r
723 UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
\r
725 UBaseType_t xReturn;
\r
726 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
728 if( xEventGroup == NULL )
\r
734 xReturn = pxEventBits->uxEventGroupNumber;
\r
740 #endif /* configUSE_TRACE_FACILITY */
\r
741 /*-----------------------------------------------------------*/
\r
743 #if ( configUSE_TRACE_FACILITY == 1 )
\r
745 void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
\r
747 ( ( 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
750 #endif /* configUSE_TRACE_FACILITY */
\r
751 /*-----------------------------------------------------------*/
\r