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
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,
\r
88 const EventBits_t uxBitsToWaitFor,
\r
89 const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
\r
91 /*-----------------------------------------------------------*/
\r
93 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
95 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
\r
97 EventGroup_t * pxEventBits;
\r
99 /* A StaticEventGroup_t object must be provided. */
\r
100 configASSERT( pxEventGroupBuffer );
\r
102 #if ( configASSERT_DEFINED == 1 )
\r
104 /* Sanity check that the size of the structure used to declare a
\r
105 * variable of type StaticEventGroup_t equals the size of the real
\r
106 * event group structure. */
\r
107 volatile size_t xSize = sizeof( StaticEventGroup_t );
\r
108 configASSERT( xSize == sizeof( EventGroup_t ) );
\r
109 } /*lint !e529 xSize is referenced if configASSERT() is defined. */
\r
110 #endif /* configASSERT_DEFINED */
\r
112 /* The user has provided a statically allocated event group - use it. */
\r
113 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
115 if( pxEventBits != NULL )
\r
117 pxEventBits->uxEventBits = 0;
\r
118 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
120 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
122 /* Both static and dynamic allocation can be used, so note that
\r
123 * this event group was created statically in case the event group
\r
124 * is later deleted. */
\r
125 pxEventBits->ucStaticallyAllocated = pdTRUE;
\r
127 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
129 traceEVENT_GROUP_CREATE( pxEventBits );
\r
133 /* xEventGroupCreateStatic should only ever be called with
\r
134 * pxEventGroupBuffer pointing to a pre-allocated (compile time
\r
135 * allocated) StaticEventGroup_t variable. */
\r
136 traceEVENT_GROUP_CREATE_FAILED();
\r
139 return pxEventBits;
\r
142 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
143 /*-----------------------------------------------------------*/
\r
145 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
147 EventGroupHandle_t xEventGroupCreate( void )
\r
149 EventGroup_t * pxEventBits;
\r
151 /* Allocate the event group. Justification for MISRA deviation as
\r
152 * follows: pvPortMalloc() always ensures returned memory blocks are
\r
153 * aligned per the requirements of the MCU stack. In this case
\r
154 * pvPortMalloc() must return a pointer that is guaranteed to meet the
\r
155 * alignment requirements of the EventGroup_t structure - which (if you
\r
156 * follow it through) is the alignment requirements of the TickType_t type
\r
157 * (EventBits_t being of TickType_t itself). Therefore, whenever the
\r
158 * stack alignment requirements are greater than or equal to the
\r
159 * TickType_t alignment requirements the cast is safe. In other cases,
\r
160 * where the natural word size of the architecture is less than
\r
161 * sizeof( TickType_t ), the TickType_t variables will be accessed in two
\r
162 * or more reads operations, and the alignment requirements is only that
\r
163 * of each individual read. */
\r
164 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
\r
166 if( pxEventBits != NULL )
\r
168 pxEventBits->uxEventBits = 0;
\r
169 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
171 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
173 /* Both static and dynamic allocation can be used, so note this
\r
174 * event group was allocated statically in case the event group is
\r
175 * later deleted. */
\r
176 pxEventBits->ucStaticallyAllocated = pdFALSE;
\r
178 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
180 traceEVENT_GROUP_CREATE( pxEventBits );
\r
184 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
187 return pxEventBits;
\r
190 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
191 /*-----------------------------------------------------------*/
\r
193 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
\r
194 const EventBits_t uxBitsToSet,
\r
195 const EventBits_t uxBitsToWaitFor,
\r
196 TickType_t xTicksToWait )
\r
198 EventBits_t uxOriginalBitValue, uxReturn;
\r
199 EventGroup_t * pxEventBits = xEventGroup;
\r
200 BaseType_t xAlreadyYielded;
\r
201 BaseType_t xTimeoutOccurred = pdFALSE;
\r
203 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
204 configASSERT( uxBitsToWaitFor != 0 );
\r
205 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
207 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
213 uxOriginalBitValue = pxEventBits->uxEventBits;
\r
215 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
\r
217 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
219 /* All the rendezvous bits are now set - no need to block. */
\r
220 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
\r
222 /* Rendezvous always clear the bits. They will have been cleared
\r
223 * already unless this is the only task in the rendezvous. */
\r
224 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
230 if( xTicksToWait != ( TickType_t ) 0 )
\r
232 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
\r
234 /* Store the bits that the calling task is waiting for in the
\r
235 * task's event list item so the kernel knows when a match is
\r
236 * found. Then enter the blocked state. */
\r
237 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
\r
239 /* This assignment is obsolete as uxReturn will get set after
\r
240 * the task unblocks, but some compilers mistakenly generate a
\r
241 * warning about uxReturn being returned without being set if the
\r
242 * assignment is omitted. */
\r
247 /* The rendezvous bits were not set, but no block time was
\r
248 * specified - just return the current event bit value. */
\r
249 uxReturn = pxEventBits->uxEventBits;
\r
250 xTimeoutOccurred = pdTRUE;
\r
254 xAlreadyYielded = xTaskResumeAll();
\r
256 if( xTicksToWait != ( TickType_t ) 0 )
\r
258 if( xAlreadyYielded == pdFALSE )
\r
260 portYIELD_WITHIN_API();
\r
264 mtCOVERAGE_TEST_MARKER();
\r
267 /* The task blocked to wait for its required bits to be set - at this
\r
268 * point either the required bits were set or the block time expired. If
\r
269 * the required bits were set they will have been stored in the task's
\r
270 * event list item, and they should now be retrieved then cleared. */
\r
271 uxReturn = uxTaskResetEventItemValue();
\r
273 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
275 /* The task timed out, just return the current event bit value. */
\r
276 taskENTER_CRITICAL();
\r
278 uxReturn = pxEventBits->uxEventBits;
\r
280 /* Although the task got here because it timed out before the
\r
281 * bits it was waiting for were set, it is possible that since it
\r
282 * unblocked another task has set the bits. If this is the case
\r
283 * then it needs to clear the bits before exiting. */
\r
284 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
286 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
290 mtCOVERAGE_TEST_MARKER();
\r
293 taskEXIT_CRITICAL();
\r
295 xTimeoutOccurred = pdTRUE;
\r
299 /* The task unblocked because the bits were set. */
\r
302 /* Control bits might be set as the task had blocked should not be
\r
304 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
307 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
\r
309 /* Prevent compiler warnings when trace macros are not used. */
\r
310 ( void ) xTimeoutOccurred;
\r
314 /*-----------------------------------------------------------*/
\r
316 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
\r
317 const EventBits_t uxBitsToWaitFor,
\r
318 const BaseType_t xClearOnExit,
\r
319 const BaseType_t xWaitForAllBits,
\r
320 TickType_t xTicksToWait )
\r
322 EventGroup_t * pxEventBits = xEventGroup;
\r
323 EventBits_t uxReturn, uxControlBits = 0;
\r
324 BaseType_t xWaitConditionMet, xAlreadyYielded;
\r
325 BaseType_t xTimeoutOccurred = pdFALSE;
\r
327 /* Check the user is not attempting to wait on the bits used by the kernel
\r
328 * itself, and that at least one bit is being requested. */
\r
329 configASSERT( xEventGroup );
\r
330 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
331 configASSERT( uxBitsToWaitFor != 0 );
\r
332 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
334 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
340 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
\r
342 /* Check to see if the wait condition is already met or not. */
\r
343 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
\r
345 if( xWaitConditionMet != pdFALSE )
\r
347 /* The wait condition has already been met so there is no need to
\r
349 uxReturn = uxCurrentEventBits;
\r
350 xTicksToWait = ( TickType_t ) 0;
\r
352 /* Clear the wait bits if requested to do so. */
\r
353 if( xClearOnExit != pdFALSE )
\r
355 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
359 mtCOVERAGE_TEST_MARKER();
\r
362 else if( xTicksToWait == ( TickType_t ) 0 )
\r
364 /* The wait condition has not been met, but no block time was
\r
365 * specified, so just return the current value. */
\r
366 uxReturn = uxCurrentEventBits;
\r
367 xTimeoutOccurred = pdTRUE;
\r
371 /* The task is going to block to wait for its required bits to be
\r
372 * set. uxControlBits are used to remember the specified behaviour of
\r
373 * this call to xEventGroupWaitBits() - for use when the event bits
\r
374 * unblock the task. */
\r
375 if( xClearOnExit != pdFALSE )
\r
377 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
\r
381 mtCOVERAGE_TEST_MARKER();
\r
384 if( xWaitForAllBits != pdFALSE )
\r
386 uxControlBits |= eventWAIT_FOR_ALL_BITS;
\r
390 mtCOVERAGE_TEST_MARKER();
\r
393 /* Store the bits that the calling task is waiting for in the
\r
394 * task's event list item so the kernel knows when a match is
\r
395 * found. Then enter the blocked state. */
\r
396 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
\r
398 /* This is obsolete as it will get set after the task unblocks, but
\r
399 * some compilers mistakenly generate a warning about the variable
\r
400 * being returned without being set if it is not done. */
\r
403 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
\r
406 xAlreadyYielded = xTaskResumeAll();
\r
408 if( xTicksToWait != ( TickType_t ) 0 )
\r
410 if( xAlreadyYielded == pdFALSE )
\r
412 portYIELD_WITHIN_API();
\r
416 mtCOVERAGE_TEST_MARKER();
\r
419 /* The task blocked to wait for its required bits to be set - at this
\r
420 * point either the required bits were set or the block time expired. If
\r
421 * the required bits were set they will have been stored in the task's
\r
422 * event list item, and they should now be retrieved then cleared. */
\r
423 uxReturn = uxTaskResetEventItemValue();
\r
425 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
427 taskENTER_CRITICAL();
\r
429 /* The task timed out, just return the current event bit value. */
\r
430 uxReturn = pxEventBits->uxEventBits;
\r
432 /* It is possible that the event bits were updated between this
\r
433 * task leaving the Blocked state and running again. */
\r
434 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
\r
436 if( xClearOnExit != pdFALSE )
\r
438 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
442 mtCOVERAGE_TEST_MARKER();
\r
447 mtCOVERAGE_TEST_MARKER();
\r
450 xTimeoutOccurred = pdTRUE;
\r
452 taskEXIT_CRITICAL();
\r
456 /* The task unblocked because the bits were set. */
\r
459 /* The task blocked so control bits may have been set. */
\r
460 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
463 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
\r
465 /* Prevent compiler warnings when trace macros are not used. */
\r
466 ( void ) xTimeoutOccurred;
\r
470 /*-----------------------------------------------------------*/
\r
472 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
\r
473 const EventBits_t uxBitsToClear )
\r
475 EventGroup_t * pxEventBits = xEventGroup;
\r
476 EventBits_t uxReturn;
\r
478 /* Check the user is not attempting to clear the bits used by the kernel
\r
480 configASSERT( xEventGroup );
\r
481 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
483 taskENTER_CRITICAL();
\r
485 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
\r
487 /* The value returned is the event group value prior to the bits being
\r
489 uxReturn = pxEventBits->uxEventBits;
\r
491 /* Clear the bits. */
\r
492 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
494 taskEXIT_CRITICAL();
\r
498 /*-----------------------------------------------------------*/
\r
500 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
502 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
\r
503 const EventBits_t uxBitsToClear )
\r
505 BaseType_t xReturn;
\r
507 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
\r
508 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
513 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
\r
514 /*-----------------------------------------------------------*/
\r
516 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
\r
518 UBaseType_t uxSavedInterruptStatus;
\r
519 EventGroup_t const * const pxEventBits = xEventGroup;
\r
520 EventBits_t uxReturn;
\r
522 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
524 uxReturn = pxEventBits->uxEventBits;
\r
526 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
529 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
\r
530 /*-----------------------------------------------------------*/
\r
532 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
\r
533 const EventBits_t uxBitsToSet )
\r
535 ListItem_t * pxListItem, * pxNext;
\r
536 ListItem_t const * pxListEnd;
\r
537 List_t const * pxList;
\r
538 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
\r
539 EventGroup_t * pxEventBits = xEventGroup;
\r
540 BaseType_t xMatchFound = pdFALSE;
\r
542 /* Check the user is not attempting to set the bits used by the kernel
\r
544 configASSERT( xEventGroup );
\r
545 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
547 pxList = &( pxEventBits->xTasksWaitingForBits );
\r
548 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
551 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
\r
553 pxListItem = listGET_HEAD_ENTRY( pxList );
\r
555 /* Set the bits. */
\r
556 pxEventBits->uxEventBits |= uxBitsToSet;
\r
558 /* See if the new bit value should unblock any tasks. */
\r
559 while( pxListItem != pxListEnd )
\r
561 pxNext = listGET_NEXT( pxListItem );
\r
562 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
\r
563 xMatchFound = pdFALSE;
\r
565 /* Split the bits waited for from the control bits. */
\r
566 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
\r
567 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
569 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
\r
571 /* Just looking for single bit being set. */
\r
572 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
\r
574 xMatchFound = pdTRUE;
\r
578 mtCOVERAGE_TEST_MARKER();
\r
581 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
\r
583 /* All bits are set. */
\r
584 xMatchFound = pdTRUE;
\r
588 /* Need all bits to be set, but not all the bits were set. */
\r
591 if( xMatchFound != pdFALSE )
\r
593 /* The bits match. Should the bits be cleared on exit? */
\r
594 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
\r
596 uxBitsToClear |= uxBitsWaitedFor;
\r
600 mtCOVERAGE_TEST_MARKER();
\r
603 /* Store the actual event flag value in the task's event list
\r
604 * item before removing the task from the event list. The
\r
605 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
\r
606 * that is was unblocked due to its required bits matching, rather
\r
607 * than because it timed out. */
\r
608 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
\r
611 /* Move onto the next list item. Note pxListItem->pxNext is not
\r
612 * used here as the list item may have been removed from the event list
\r
613 * and inserted into the ready/pending reading list. */
\r
614 pxListItem = pxNext;
\r
617 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
\r
618 * bit was set in the control word. */
\r
619 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
621 ( void ) xTaskResumeAll();
\r
623 return pxEventBits->uxEventBits;
\r
625 /*-----------------------------------------------------------*/
\r
627 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
\r
629 EventGroup_t * pxEventBits = xEventGroup;
\r
630 const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
\r
634 traceEVENT_GROUP_DELETE( xEventGroup );
\r
636 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
\r
638 /* Unblock the task, returning 0 as the event list is being deleted
\r
639 * and cannot therefore have any bits set. */
\r
640 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
\r
641 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
\r
644 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
\r
646 /* The event group can only have been allocated dynamically - free
\r
648 vPortFree( pxEventBits );
\r
650 #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
\r
652 /* The event group could have been allocated statically or
\r
653 * dynamically, so check before attempting to free the memory. */
\r
654 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
\r
656 vPortFree( pxEventBits );
\r
660 mtCOVERAGE_TEST_MARKER();
\r
663 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
665 ( void ) xTaskResumeAll();
\r
667 /*-----------------------------------------------------------*/
\r
669 /* For internal use only - execute a 'set bits' command that was pended from
\r
671 void vEventGroupSetBitsCallback( void * pvEventGroup,
\r
672 const uint32_t ulBitsToSet )
\r
674 ( 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
676 /*-----------------------------------------------------------*/
\r
678 /* For internal use only - execute a 'clear bits' command that was pended from
\r
680 void vEventGroupClearBitsCallback( void * pvEventGroup,
\r
681 const uint32_t ulBitsToClear )
\r
683 ( 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
685 /*-----------------------------------------------------------*/
\r
687 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
\r
688 const EventBits_t uxBitsToWaitFor,
\r
689 const BaseType_t xWaitForAllBits )
\r
691 BaseType_t xWaitConditionMet = pdFALSE;
\r
693 if( xWaitForAllBits == pdFALSE )
\r
695 /* Task only has to wait for one bit within uxBitsToWaitFor to be
\r
696 * set. Is one already set? */
\r
697 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
\r
699 xWaitConditionMet = pdTRUE;
\r
703 mtCOVERAGE_TEST_MARKER();
\r
708 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
\r
709 * Are they set already? */
\r
710 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
712 xWaitConditionMet = pdTRUE;
\r
716 mtCOVERAGE_TEST_MARKER();
\r
720 return xWaitConditionMet;
\r
722 /*-----------------------------------------------------------*/
\r
724 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
726 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
\r
727 const EventBits_t uxBitsToSet,
\r
728 BaseType_t * pxHigherPriorityTaskWoken )
\r
730 BaseType_t xReturn;
\r
732 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
\r
733 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
738 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
\r
739 /*-----------------------------------------------------------*/
\r
741 #if ( configUSE_TRACE_FACILITY == 1 )
\r
743 UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
\r
745 UBaseType_t xReturn;
\r
746 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
748 if( xEventGroup == NULL )
\r
754 xReturn = pxEventBits->uxEventGroupNumber;
\r
760 #endif /* configUSE_TRACE_FACILITY */
\r
761 /*-----------------------------------------------------------*/
\r
763 #if ( configUSE_TRACE_FACILITY == 1 )
\r
765 void vEventGroupSetNumber( void * xEventGroup,
\r
766 UBaseType_t uxEventGroupNumber )
\r
768 ( ( 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
771 #endif /* configUSE_TRACE_FACILITY */
\r
772 /*-----------------------------------------------------------*/
\r