2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
\r
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * SPDX-License-Identifier: MIT
\r
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
8 * this software and associated documentation files (the "Software"), to deal in
\r
9 * the Software without restriction, including without limitation the rights to
\r
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
11 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
12 * subject to the following conditions:
\r
14 * The above copyright notice and this permission notice shall be included in all
\r
15 * copies or substantial portions of the Software.
\r
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
24 * https://www.FreeRTOS.org
\r
25 * https://github.com/FreeRTOS
\r
29 /* Standard includes. */
\r
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
33 * all the API functions to use the MPU wrappers. That should only be done when
\r
34 * task.h is included from an application file. */
\r
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
37 /* FreeRTOS includes. */
\r
38 #include "FreeRTOS.h"
\r
41 #include "event_groups.h"
\r
43 /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
\r
44 * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
\r
45 * for the header files above, but not in this file, in order to generate the
\r
46 * correct privileged Vs unprivileged linkage and placement. */
\r
47 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
\r
49 /* The following bit fields convey control information in a task's event list
\r
50 * item value. It is important they don't clash with the
\r
51 * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
\r
52 #if configUSE_16_BIT_TICKS == 1
\r
53 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
\r
54 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
\r
55 #define eventWAIT_FOR_ALL_BITS 0x0400U
\r
56 #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
\r
58 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
\r
59 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
\r
60 #define eventWAIT_FOR_ALL_BITS 0x04000000UL
\r
61 #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
\r
64 typedef struct EventGroupDef_t
\r
66 EventBits_t uxEventBits;
\r
67 List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
\r
69 #if ( configUSE_TRACE_FACILITY == 1 )
\r
70 UBaseType_t uxEventGroupNumber;
\r
73 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
74 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
\r
78 /*-----------------------------------------------------------*/
\r
81 * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
\r
82 * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
\r
83 * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
\r
84 * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
\r
85 * wait condition is met if any of the bits set in uxBitsToWait for are also set
\r
86 * in uxCurrentEventBits.
\r
88 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
\r
89 const EventBits_t uxBitsToWaitFor,
\r
90 const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
\r
92 /*-----------------------------------------------------------*/
\r
94 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
96 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
\r
98 EventGroup_t * pxEventBits;
\r
100 /* A StaticEventGroup_t object must be provided. */
\r
101 configASSERT( pxEventGroupBuffer );
\r
103 #if ( configASSERT_DEFINED == 1 )
\r
105 /* Sanity check that the size of the structure used to declare a
\r
106 * variable of type StaticEventGroup_t equals the size of the real
\r
107 * event group structure. */
\r
108 volatile size_t xSize = sizeof( StaticEventGroup_t );
\r
109 configASSERT( xSize == sizeof( EventGroup_t ) );
\r
110 } /*lint !e529 xSize is referenced if configASSERT() is defined. */
\r
111 #endif /* configASSERT_DEFINED */
\r
113 /* The user has provided a statically allocated event group - use it. */
\r
114 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
116 if( pxEventBits != NULL )
\r
118 pxEventBits->uxEventBits = 0;
\r
119 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
121 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
123 /* Both static and dynamic allocation can be used, so note that
\r
124 * this event group was created statically in case the event group
\r
125 * is later deleted. */
\r
126 pxEventBits->ucStaticallyAllocated = pdTRUE;
\r
128 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
130 traceEVENT_GROUP_CREATE( pxEventBits );
\r
134 /* xEventGroupCreateStatic should only ever be called with
\r
135 * pxEventGroupBuffer pointing to a pre-allocated (compile time
\r
136 * allocated) StaticEventGroup_t variable. */
\r
137 traceEVENT_GROUP_CREATE_FAILED();
\r
140 return pxEventBits;
\r
143 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
144 /*-----------------------------------------------------------*/
\r
146 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
148 EventGroupHandle_t xEventGroupCreate( void )
\r
150 EventGroup_t * pxEventBits;
\r
152 /* Allocate the event group. Justification for MISRA deviation as
\r
153 * follows: pvPortMalloc() always ensures returned memory blocks are
\r
154 * aligned per the requirements of the MCU stack. In this case
\r
155 * pvPortMalloc() must return a pointer that is guaranteed to meet the
\r
156 * alignment requirements of the EventGroup_t structure - which (if you
\r
157 * follow it through) is the alignment requirements of the TickType_t type
\r
158 * (EventBits_t being of TickType_t itself). Therefore, whenever the
\r
159 * stack alignment requirements are greater than or equal to the
\r
160 * TickType_t alignment requirements the cast is safe. In other cases,
\r
161 * where the natural word size of the architecture is less than
\r
162 * sizeof( TickType_t ), the TickType_t variables will be accessed in two
\r
163 * or more reads operations, and the alignment requirements is only that
\r
164 * of each individual read. */
\r
165 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
\r
167 if( pxEventBits != NULL )
\r
169 pxEventBits->uxEventBits = 0;
\r
170 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
\r
172 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
174 /* Both static and dynamic allocation can be used, so note this
\r
175 * event group was allocated statically in case the event group is
\r
176 * later deleted. */
\r
177 pxEventBits->ucStaticallyAllocated = pdFALSE;
\r
179 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
181 traceEVENT_GROUP_CREATE( pxEventBits );
\r
185 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
188 return pxEventBits;
\r
191 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
192 /*-----------------------------------------------------------*/
\r
194 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
\r
195 const EventBits_t uxBitsToSet,
\r
196 const EventBits_t uxBitsToWaitFor,
\r
197 TickType_t xTicksToWait )
\r
199 EventBits_t uxOriginalBitValue, uxReturn;
\r
200 EventGroup_t * pxEventBits = xEventGroup;
\r
201 BaseType_t xAlreadyYielded;
\r
202 BaseType_t xTimeoutOccurred = pdFALSE;
\r
204 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
205 configASSERT( uxBitsToWaitFor != 0 );
\r
206 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
208 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
214 uxOriginalBitValue = pxEventBits->uxEventBits;
\r
216 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
\r
218 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
220 /* All the rendezvous bits are now set - no need to block. */
\r
221 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
\r
223 /* Rendezvous always clear the bits. They will have been cleared
\r
224 * already unless this is the only task in the rendezvous. */
\r
225 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
231 if( xTicksToWait != ( TickType_t ) 0 )
\r
233 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
\r
235 /* Store the bits that the calling task is waiting for in the
\r
236 * task's event list item so the kernel knows when a match is
\r
237 * found. Then enter the blocked state. */
\r
238 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
\r
240 /* This assignment is obsolete as uxReturn will get set after
\r
241 * the task unblocks, but some compilers mistakenly generate a
\r
242 * warning about uxReturn being returned without being set if the
\r
243 * assignment is omitted. */
\r
248 /* The rendezvous bits were not set, but no block time was
\r
249 * specified - just return the current event bit value. */
\r
250 uxReturn = pxEventBits->uxEventBits;
\r
251 xTimeoutOccurred = pdTRUE;
\r
255 xAlreadyYielded = xTaskResumeAll();
\r
257 if( xTicksToWait != ( TickType_t ) 0 )
\r
259 if( xAlreadyYielded == pdFALSE )
\r
261 portYIELD_WITHIN_API();
\r
265 mtCOVERAGE_TEST_MARKER();
\r
268 /* The task blocked to wait for its required bits to be set - at this
\r
269 * point either the required bits were set or the block time expired. If
\r
270 * the required bits were set they will have been stored in the task's
\r
271 * event list item, and they should now be retrieved then cleared. */
\r
272 uxReturn = uxTaskResetEventItemValue();
\r
274 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
276 /* The task timed out, just return the current event bit value. */
\r
277 taskENTER_CRITICAL();
\r
279 uxReturn = pxEventBits->uxEventBits;
\r
281 /* Although the task got here because it timed out before the
\r
282 * bits it was waiting for were set, it is possible that since it
\r
283 * unblocked another task has set the bits. If this is the case
\r
284 * then it needs to clear the bits before exiting. */
\r
285 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
287 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
291 mtCOVERAGE_TEST_MARKER();
\r
294 taskEXIT_CRITICAL();
\r
296 xTimeoutOccurred = pdTRUE;
\r
300 /* The task unblocked because the bits were set. */
\r
303 /* Control bits might be set as the task had blocked should not be
\r
305 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
308 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
\r
310 /* Prevent compiler warnings when trace macros are not used. */
\r
311 ( void ) xTimeoutOccurred;
\r
315 /*-----------------------------------------------------------*/
\r
317 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
\r
318 const EventBits_t uxBitsToWaitFor,
\r
319 const BaseType_t xClearOnExit,
\r
320 const BaseType_t xWaitForAllBits,
\r
321 TickType_t xTicksToWait )
\r
323 EventGroup_t * pxEventBits = xEventGroup;
\r
324 EventBits_t uxReturn, uxControlBits = 0;
\r
325 BaseType_t xWaitConditionMet, xAlreadyYielded;
\r
326 BaseType_t xTimeoutOccurred = pdFALSE;
\r
328 /* Check the user is not attempting to wait on the bits used by the kernel
\r
329 * itself, and that at least one bit is being requested. */
\r
330 configASSERT( xEventGroup );
\r
331 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
332 configASSERT( uxBitsToWaitFor != 0 );
\r
333 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
335 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
341 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
\r
343 /* Check to see if the wait condition is already met or not. */
\r
344 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
\r
346 if( xWaitConditionMet != pdFALSE )
\r
348 /* The wait condition has already been met so there is no need to
\r
350 uxReturn = uxCurrentEventBits;
\r
351 xTicksToWait = ( TickType_t ) 0;
\r
353 /* Clear the wait bits if requested to do so. */
\r
354 if( xClearOnExit != pdFALSE )
\r
356 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
360 mtCOVERAGE_TEST_MARKER();
\r
363 else if( xTicksToWait == ( TickType_t ) 0 )
\r
365 /* The wait condition has not been met, but no block time was
\r
366 * specified, so just return the current value. */
\r
367 uxReturn = uxCurrentEventBits;
\r
368 xTimeoutOccurred = pdTRUE;
\r
372 /* The task is going to block to wait for its required bits to be
\r
373 * set. uxControlBits are used to remember the specified behaviour of
\r
374 * this call to xEventGroupWaitBits() - for use when the event bits
\r
375 * unblock the task. */
\r
376 if( xClearOnExit != pdFALSE )
\r
378 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
\r
382 mtCOVERAGE_TEST_MARKER();
\r
385 if( xWaitForAllBits != pdFALSE )
\r
387 uxControlBits |= eventWAIT_FOR_ALL_BITS;
\r
391 mtCOVERAGE_TEST_MARKER();
\r
394 /* Store the bits that the calling task is waiting for in the
\r
395 * task's event list item so the kernel knows when a match is
\r
396 * found. Then enter the blocked state. */
\r
397 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
\r
399 /* This is obsolete as it will get set after the task unblocks, but
\r
400 * some compilers mistakenly generate a warning about the variable
\r
401 * being returned without being set if it is not done. */
\r
404 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
\r
407 xAlreadyYielded = xTaskResumeAll();
\r
409 if( xTicksToWait != ( TickType_t ) 0 )
\r
411 if( xAlreadyYielded == pdFALSE )
\r
413 portYIELD_WITHIN_API();
\r
417 mtCOVERAGE_TEST_MARKER();
\r
420 /* The task blocked to wait for its required bits to be set - at this
\r
421 * point either the required bits were set or the block time expired. If
\r
422 * the required bits were set they will have been stored in the task's
\r
423 * event list item, and they should now be retrieved then cleared. */
\r
424 uxReturn = uxTaskResetEventItemValue();
\r
426 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
\r
428 taskENTER_CRITICAL();
\r
430 /* The task timed out, just return the current event bit value. */
\r
431 uxReturn = pxEventBits->uxEventBits;
\r
433 /* It is possible that the event bits were updated between this
\r
434 * task leaving the Blocked state and running again. */
\r
435 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
\r
437 if( xClearOnExit != pdFALSE )
\r
439 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
\r
443 mtCOVERAGE_TEST_MARKER();
\r
448 mtCOVERAGE_TEST_MARKER();
\r
451 xTimeoutOccurred = pdTRUE;
\r
453 taskEXIT_CRITICAL();
\r
457 /* The task unblocked because the bits were set. */
\r
460 /* The task blocked so control bits may have been set. */
\r
461 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
464 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
\r
466 /* Prevent compiler warnings when trace macros are not used. */
\r
467 ( void ) xTimeoutOccurred;
\r
471 /*-----------------------------------------------------------*/
\r
473 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
\r
474 const EventBits_t uxBitsToClear )
\r
476 EventGroup_t * pxEventBits = xEventGroup;
\r
477 EventBits_t uxReturn;
\r
479 /* Check the user is not attempting to clear the bits used by the kernel
\r
481 configASSERT( xEventGroup );
\r
482 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
484 taskENTER_CRITICAL();
\r
486 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
\r
488 /* The value returned is the event group value prior to the bits being
\r
490 uxReturn = pxEventBits->uxEventBits;
\r
492 /* Clear the bits. */
\r
493 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
495 taskEXIT_CRITICAL();
\r
499 /*-----------------------------------------------------------*/
\r
501 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
503 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
\r
504 const EventBits_t uxBitsToClear )
\r
506 BaseType_t xReturn;
\r
508 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
\r
509 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
514 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
\r
515 /*-----------------------------------------------------------*/
\r
517 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
\r
519 UBaseType_t uxSavedInterruptStatus;
\r
520 EventGroup_t const * const pxEventBits = xEventGroup;
\r
521 EventBits_t uxReturn;
\r
523 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
525 uxReturn = pxEventBits->uxEventBits;
\r
527 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
530 } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
\r
531 /*-----------------------------------------------------------*/
\r
533 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
\r
534 const EventBits_t uxBitsToSet )
\r
536 ListItem_t * pxListItem, * pxNext;
\r
537 ListItem_t const * pxListEnd;
\r
538 List_t const * pxList;
\r
539 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
\r
540 EventGroup_t * pxEventBits = xEventGroup;
\r
541 BaseType_t xMatchFound = pdFALSE;
\r
543 /* Check the user is not attempting to set the bits used by the kernel
\r
545 configASSERT( xEventGroup );
\r
546 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
\r
548 pxList = &( pxEventBits->xTasksWaitingForBits );
\r
549 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
552 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
\r
554 pxListItem = listGET_HEAD_ENTRY( pxList );
\r
556 /* Set the bits. */
\r
557 pxEventBits->uxEventBits |= uxBitsToSet;
\r
559 /* See if the new bit value should unblock any tasks. */
\r
560 while( pxListItem != pxListEnd )
\r
562 pxNext = listGET_NEXT( pxListItem );
\r
563 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
\r
564 xMatchFound = pdFALSE;
\r
566 /* Split the bits waited for from the control bits. */
\r
567 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
\r
568 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
\r
570 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
\r
572 /* Just looking for single bit being set. */
\r
573 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
\r
575 xMatchFound = pdTRUE;
\r
579 mtCOVERAGE_TEST_MARKER();
\r
582 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
\r
584 /* All bits are set. */
\r
585 xMatchFound = pdTRUE;
\r
589 /* Need all bits to be set, but not all the bits were set. */
\r
592 if( xMatchFound != pdFALSE )
\r
594 /* The bits match. Should the bits be cleared on exit? */
\r
595 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
\r
597 uxBitsToClear |= uxBitsWaitedFor;
\r
601 mtCOVERAGE_TEST_MARKER();
\r
604 /* Store the actual event flag value in the task's event list
\r
605 * item before removing the task from the event list. The
\r
606 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
\r
607 * that is was unblocked due to its required bits matching, rather
\r
608 * than because it timed out. */
\r
609 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
\r
612 /* Move onto the next list item. Note pxListItem->pxNext is not
\r
613 * used here as the list item may have been removed from the event list
\r
614 * and inserted into the ready/pending reading list. */
\r
615 pxListItem = pxNext;
\r
618 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
\r
619 * bit was set in the control word. */
\r
620 pxEventBits->uxEventBits &= ~uxBitsToClear;
\r
622 ( void ) xTaskResumeAll();
\r
624 return pxEventBits->uxEventBits;
\r
626 /*-----------------------------------------------------------*/
\r
628 void vEventGroupDelete( EventGroupHandle_t xEventGroup )
\r
630 EventGroup_t * pxEventBits = xEventGroup;
\r
631 const List_t * pxTasksWaitingForBits;
\r
633 configASSERT( pxEventBits );
\r
635 pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
\r
639 traceEVENT_GROUP_DELETE( xEventGroup );
\r
641 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
\r
643 /* Unblock the task, returning 0 as the event list is being deleted
\r
644 * and cannot therefore have any bits set. */
\r
645 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
\r
646 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
\r
649 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
\r
651 /* The event group can only have been allocated dynamically - free
\r
653 vPortFree( pxEventBits );
\r
655 #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
\r
657 /* The event group could have been allocated statically or
\r
658 * dynamically, so check before attempting to free the memory. */
\r
659 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
\r
661 vPortFree( pxEventBits );
\r
665 mtCOVERAGE_TEST_MARKER();
\r
668 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
670 ( void ) xTaskResumeAll();
\r
672 /*-----------------------------------------------------------*/
\r
674 /* For internal use only - execute a 'set bits' command that was pended from
\r
676 void vEventGroupSetBitsCallback( void * pvEventGroup,
\r
677 const uint32_t ulBitsToSet )
\r
679 ( 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
681 /*-----------------------------------------------------------*/
\r
683 /* For internal use only - execute a 'clear bits' command that was pended from
\r
685 void vEventGroupClearBitsCallback( void * pvEventGroup,
\r
686 const uint32_t ulBitsToClear )
\r
688 ( 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
690 /*-----------------------------------------------------------*/
\r
692 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
\r
693 const EventBits_t uxBitsToWaitFor,
\r
694 const BaseType_t xWaitForAllBits )
\r
696 BaseType_t xWaitConditionMet = pdFALSE;
\r
698 if( xWaitForAllBits == pdFALSE )
\r
700 /* Task only has to wait for one bit within uxBitsToWaitFor to be
\r
701 * set. Is one already set? */
\r
702 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
\r
704 xWaitConditionMet = pdTRUE;
\r
708 mtCOVERAGE_TEST_MARKER();
\r
713 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
\r
714 * Are they set already? */
\r
715 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
\r
717 xWaitConditionMet = pdTRUE;
\r
721 mtCOVERAGE_TEST_MARKER();
\r
725 return xWaitConditionMet;
\r
727 /*-----------------------------------------------------------*/
\r
729 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
\r
731 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
\r
732 const EventBits_t uxBitsToSet,
\r
733 BaseType_t * pxHigherPriorityTaskWoken )
\r
735 BaseType_t xReturn;
\r
737 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
\r
738 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
743 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
\r
744 /*-----------------------------------------------------------*/
\r
746 #if ( configUSE_TRACE_FACILITY == 1 )
\r
748 UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
\r
750 UBaseType_t xReturn;
\r
751 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
753 if( xEventGroup == NULL )
\r
759 xReturn = pxEventBits->uxEventGroupNumber;
\r
765 #endif /* configUSE_TRACE_FACILITY */
\r
766 /*-----------------------------------------------------------*/
\r
768 #if ( configUSE_TRACE_FACILITY == 1 )
\r
770 void vEventGroupSetNumber( void * xEventGroup,
\r
771 UBaseType_t uxEventGroupNumber )
\r
773 ( ( 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
776 #endif /* configUSE_TRACE_FACILITY */
\r
777 /*-----------------------------------------------------------*/
\r