source: S-port/trunk/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 26.2 KB
Line 
1/*
2 * FreeRTOS Kernel V10.3.1
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
24 *
25 * 1 tab == 4 spaces!
26 */
27
28/* Standard includes. */
29#include <stdlib.h>
30
31/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
32all the API functions to use the MPU wrappers. That should only be done when
33task.h is included from an application file. */
34#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
35
36/* FreeRTOS includes. */
37#include "FreeRTOS.h"
38#include "task.h"
39#include "timers.h"
40#include "event_groups.h"
41
42/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
43because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
44for the header files above, but not in this file, in order to generate the
45correct privileged Vs unprivileged linkage and placement. */
46#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
47
48/* The following bit fields convey control information in a task's event list
49item value. It is important they don't clash with the
50taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
51#if configUSE_16_BIT_TICKS == 1
52 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
53 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
54 #define eventWAIT_FOR_ALL_BITS 0x0400U
55 #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
56#else
57 #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
58 #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
59 #define eventWAIT_FOR_ALL_BITS 0x04000000UL
60 #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
61#endif
62
63typedef struct EventGroupDef_t
64{
65 EventBits_t uxEventBits;
66 List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
67
68 #if( configUSE_TRACE_FACILITY == 1 )
69 UBaseType_t uxEventGroupNumber;
70 #endif
71
72 #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
73 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
74 #endif
75} EventGroup_t;
76
77/*-----------------------------------------------------------*/
78
79/*
80 * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
81 * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
82 * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
83 * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
84 * wait condition is met if any of the bits set in uxBitsToWait for are also set
85 * in uxCurrentEventBits.
86 */
87static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
88
89/*-----------------------------------------------------------*/
90
91#if( configSUPPORT_STATIC_ALLOCATION == 1 )
92
93 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
94 {
95 EventGroup_t *pxEventBits;
96
97 /* A StaticEventGroup_t object must be provided. */
98 configASSERT( pxEventGroupBuffer );
99
100 #if( configASSERT_DEFINED == 1 )
101 {
102 /* Sanity check that the size of the structure used to declare a
103 variable of type StaticEventGroup_t equals the size of the real
104 event group structure. */
105 volatile size_t xSize = sizeof( StaticEventGroup_t );
106 configASSERT( xSize == sizeof( EventGroup_t ) );
107 } /*lint !e529 xSize is referenced if configASSERT() is defined. */
108 #endif /* configASSERT_DEFINED */
109
110 /* The user has provided a statically allocated event group - use it. */
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(). */
112
113 if( pxEventBits != NULL )
114 {
115 pxEventBits->uxEventBits = 0;
116 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
117
118 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
119 {
120 /* Both static and dynamic allocation can be used, so note that
121 this event group was created statically in case the event group
122 is later deleted. */
123 pxEventBits->ucStaticallyAllocated = pdTRUE;
124 }
125 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
126
127 traceEVENT_GROUP_CREATE( pxEventBits );
128 }
129 else
130 {
131 /* xEventGroupCreateStatic should only ever be called with
132 pxEventGroupBuffer pointing to a pre-allocated (compile time
133 allocated) StaticEventGroup_t variable. */
134 traceEVENT_GROUP_CREATE_FAILED();
135 }
136
137 return pxEventBits;
138 }
139
140#endif /* configSUPPORT_STATIC_ALLOCATION */
141/*-----------------------------------------------------------*/
142
143#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
144
145 EventGroupHandle_t xEventGroupCreate( void )
146 {
147 EventGroup_t *pxEventBits;
148
149 /* Allocate the event group. Justification for MISRA deviation as
150 follows: pvPortMalloc() always ensures returned memory blocks are
151 aligned per the requirements of the MCU stack. In this case
152 pvPortMalloc() must return a pointer that is guaranteed to meet the
153 alignment requirements of the EventGroup_t structure - which (if you
154 follow it through) is the alignment requirements of the TickType_t type
155 (EventBits_t being of TickType_t itself). Therefore, whenever the
156 stack alignment requirements are greater than or equal to the
157 TickType_t alignment requirements the cast is safe. In other cases,
158 where the natural word size of the architecture is less than
159 sizeof( TickType_t ), the TickType_t variables will be accessed in two
160 or more reads operations, and the alignment requirements is only that
161 of each individual read. */
162 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
163
164 if( pxEventBits != NULL )
165 {
166 pxEventBits->uxEventBits = 0;
167 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
168
169 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
170 {
171 /* Both static and dynamic allocation can be used, so note this
172 event group was allocated statically in case the event group is
173 later deleted. */
174 pxEventBits->ucStaticallyAllocated = pdFALSE;
175 }
176 #endif /* configSUPPORT_STATIC_ALLOCATION */
177
178 traceEVENT_GROUP_CREATE( pxEventBits );
179 }
180 else
181 {
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. */
183 }
184
185 return pxEventBits;
186 }
187
188#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
189/*-----------------------------------------------------------*/
190
191EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
192{
193EventBits_t uxOriginalBitValue, uxReturn;
194EventGroup_t *pxEventBits = xEventGroup;
195BaseType_t xAlreadyYielded;
196BaseType_t xTimeoutOccurred = pdFALSE;
197
198 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
199 configASSERT( uxBitsToWaitFor != 0 );
200 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
201 {
202 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
203 }
204 #endif
205
206 vTaskSuspendAll();
207 {
208 uxOriginalBitValue = pxEventBits->uxEventBits;
209
210 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
211
212 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
213 {
214 /* All the rendezvous bits are now set - no need to block. */
215 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
216
217 /* Rendezvous always clear the bits. They will have been cleared
218 already unless this is the only task in the rendezvous. */
219 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
220
221 xTicksToWait = 0;
222 }
223 else
224 {
225 if( xTicksToWait != ( TickType_t ) 0 )
226 {
227 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
228
229 /* Store the bits that the calling task is waiting for in the
230 task's event list item so the kernel knows when a match is
231 found. Then enter the blocked state. */
232 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
233
234 /* This assignment is obsolete as uxReturn will get set after
235 the task unblocks, but some compilers mistakenly generate a
236 warning about uxReturn being returned without being set if the
237 assignment is omitted. */
238 uxReturn = 0;
239 }
240 else
241 {
242 /* The rendezvous bits were not set, but no block time was
243 specified - just return the current event bit value. */
244 uxReturn = pxEventBits->uxEventBits;
245 xTimeoutOccurred = pdTRUE;
246 }
247 }
248 }
249 xAlreadyYielded = xTaskResumeAll();
250
251 if( xTicksToWait != ( TickType_t ) 0 )
252 {
253 if( xAlreadyYielded == pdFALSE )
254 {
255 portYIELD_WITHIN_API();
256 }
257 else
258 {
259 mtCOVERAGE_TEST_MARKER();
260 }
261
262 /* The task blocked to wait for its required bits to be set - at this
263 point either the required bits were set or the block time expired. If
264 the required bits were set they will have been stored in the task's
265 event list item, and they should now be retrieved then cleared. */
266 uxReturn = uxTaskResetEventItemValue();
267
268 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
269 {
270 /* The task timed out, just return the current event bit value. */
271 taskENTER_CRITICAL();
272 {
273 uxReturn = pxEventBits->uxEventBits;
274
275 /* Although the task got here because it timed out before the
276 bits it was waiting for were set, it is possible that since it
277 unblocked another task has set the bits. If this is the case
278 then it needs to clear the bits before exiting. */
279 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
280 {
281 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
282 }
283 else
284 {
285 mtCOVERAGE_TEST_MARKER();
286 }
287 }
288 taskEXIT_CRITICAL();
289
290 xTimeoutOccurred = pdTRUE;
291 }
292 else
293 {
294 /* The task unblocked because the bits were set. */
295 }
296
297 /* Control bits might be set as the task had blocked should not be
298 returned. */
299 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
300 }
301
302 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
303
304 /* Prevent compiler warnings when trace macros are not used. */
305 ( void ) xTimeoutOccurred;
306
307 return uxReturn;
308}
309/*-----------------------------------------------------------*/
310
311EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
312{
313EventGroup_t *pxEventBits = xEventGroup;
314EventBits_t uxReturn, uxControlBits = 0;
315BaseType_t xWaitConditionMet, xAlreadyYielded;
316BaseType_t xTimeoutOccurred = pdFALSE;
317
318 /* Check the user is not attempting to wait on the bits used by the kernel
319 itself, and that at least one bit is being requested. */
320 configASSERT( xEventGroup );
321 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
322 configASSERT( uxBitsToWaitFor != 0 );
323 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
324 {
325 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
326 }
327 #endif
328
329 vTaskSuspendAll();
330 {
331 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
332
333 /* Check to see if the wait condition is already met or not. */
334 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
335
336 if( xWaitConditionMet != pdFALSE )
337 {
338 /* The wait condition has already been met so there is no need to
339 block. */
340 uxReturn = uxCurrentEventBits;
341 xTicksToWait = ( TickType_t ) 0;
342
343 /* Clear the wait bits if requested to do so. */
344 if( xClearOnExit != pdFALSE )
345 {
346 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
347 }
348 else
349 {
350 mtCOVERAGE_TEST_MARKER();
351 }
352 }
353 else if( xTicksToWait == ( TickType_t ) 0 )
354 {
355 /* The wait condition has not been met, but no block time was
356 specified, so just return the current value. */
357 uxReturn = uxCurrentEventBits;
358 xTimeoutOccurred = pdTRUE;
359 }
360 else
361 {
362 /* The task is going to block to wait for its required bits to be
363 set. uxControlBits are used to remember the specified behaviour of
364 this call to xEventGroupWaitBits() - for use when the event bits
365 unblock the task. */
366 if( xClearOnExit != pdFALSE )
367 {
368 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
369 }
370 else
371 {
372 mtCOVERAGE_TEST_MARKER();
373 }
374
375 if( xWaitForAllBits != pdFALSE )
376 {
377 uxControlBits |= eventWAIT_FOR_ALL_BITS;
378 }
379 else
380 {
381 mtCOVERAGE_TEST_MARKER();
382 }
383
384 /* Store the bits that the calling task is waiting for in the
385 task's event list item so the kernel knows when a match is
386 found. Then enter the blocked state. */
387 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
388
389 /* This is obsolete as it will get set after the task unblocks, but
390 some compilers mistakenly generate a warning about the variable
391 being returned without being set if it is not done. */
392 uxReturn = 0;
393
394 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
395 }
396 }
397 xAlreadyYielded = xTaskResumeAll();
398
399 if( xTicksToWait != ( TickType_t ) 0 )
400 {
401 if( xAlreadyYielded == pdFALSE )
402 {
403 portYIELD_WITHIN_API();
404 }
405 else
406 {
407 mtCOVERAGE_TEST_MARKER();
408 }
409
410 /* The task blocked to wait for its required bits to be set - at this
411 point either the required bits were set or the block time expired. If
412 the required bits were set they will have been stored in the task's
413 event list item, and they should now be retrieved then cleared. */
414 uxReturn = uxTaskResetEventItemValue();
415
416 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
417 {
418 taskENTER_CRITICAL();
419 {
420 /* The task timed out, just return the current event bit value. */
421 uxReturn = pxEventBits->uxEventBits;
422
423 /* It is possible that the event bits were updated between this
424 task leaving the Blocked state and running again. */
425 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
426 {
427 if( xClearOnExit != pdFALSE )
428 {
429 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
430 }
431 else
432 {
433 mtCOVERAGE_TEST_MARKER();
434 }
435 }
436 else
437 {
438 mtCOVERAGE_TEST_MARKER();
439 }
440 xTimeoutOccurred = pdTRUE;
441 }
442 taskEXIT_CRITICAL();
443 }
444 else
445 {
446 /* The task unblocked because the bits were set. */
447 }
448
449 /* The task blocked so control bits may have been set. */
450 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
451 }
452 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
453
454 /* Prevent compiler warnings when trace macros are not used. */
455 ( void ) xTimeoutOccurred;
456
457 return uxReturn;
458}
459/*-----------------------------------------------------------*/
460
461EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
462{
463EventGroup_t *pxEventBits = xEventGroup;
464EventBits_t uxReturn;
465
466 /* Check the user is not attempting to clear the bits used by the kernel
467 itself. */
468 configASSERT( xEventGroup );
469 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
470
471 taskENTER_CRITICAL();
472 {
473 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
474
475 /* The value returned is the event group value prior to the bits being
476 cleared. */
477 uxReturn = pxEventBits->uxEventBits;
478
479 /* Clear the bits. */
480 pxEventBits->uxEventBits &= ~uxBitsToClear;
481 }
482 taskEXIT_CRITICAL();
483
484 return uxReturn;
485}
486/*-----------------------------------------------------------*/
487
488#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
489
490 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
491 {
492 BaseType_t xReturn;
493
494 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
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. */
496
497 return xReturn;
498 }
499
500#endif
501/*-----------------------------------------------------------*/
502
503EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
504{
505UBaseType_t uxSavedInterruptStatus;
506EventGroup_t const * const pxEventBits = xEventGroup;
507EventBits_t uxReturn;
508
509 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
510 {
511 uxReturn = pxEventBits->uxEventBits;
512 }
513 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
514
515 return uxReturn;
516} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
517/*-----------------------------------------------------------*/
518
519EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
520{
521ListItem_t *pxListItem, *pxNext;
522ListItem_t const *pxListEnd;
523List_t const * pxList;
524EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
525EventGroup_t *pxEventBits = xEventGroup;
526BaseType_t xMatchFound = pdFALSE;
527
528 /* Check the user is not attempting to set the bits used by the kernel
529 itself. */
530 configASSERT( xEventGroup );
531 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
532
533 pxList = &( pxEventBits->xTasksWaitingForBits );
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. */
535 vTaskSuspendAll();
536 {
537 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
538
539 pxListItem = listGET_HEAD_ENTRY( pxList );
540
541 /* Set the bits. */
542 pxEventBits->uxEventBits |= uxBitsToSet;
543
544 /* See if the new bit value should unblock any tasks. */
545 while( pxListItem != pxListEnd )
546 {
547 pxNext = listGET_NEXT( pxListItem );
548 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
549 xMatchFound = pdFALSE;
550
551 /* Split the bits waited for from the control bits. */
552 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
553 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
554
555 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
556 {
557 /* Just looking for single bit being set. */
558 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
559 {
560 xMatchFound = pdTRUE;
561 }
562 else
563 {
564 mtCOVERAGE_TEST_MARKER();
565 }
566 }
567 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
568 {
569 /* All bits are set. */
570 xMatchFound = pdTRUE;
571 }
572 else
573 {
574 /* Need all bits to be set, but not all the bits were set. */
575 }
576
577 if( xMatchFound != pdFALSE )
578 {
579 /* The bits match. Should the bits be cleared on exit? */
580 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
581 {
582 uxBitsToClear |= uxBitsWaitedFor;
583 }
584 else
585 {
586 mtCOVERAGE_TEST_MARKER();
587 }
588
589 /* Store the actual event flag value in the task's event list
590 item before removing the task from the event list. The
591 eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
592 that is was unblocked due to its required bits matching, rather
593 than because it timed out. */
594 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
595 }
596
597 /* Move onto the next list item. Note pxListItem->pxNext is not
598 used here as the list item may have been removed from the event list
599 and inserted into the ready/pending reading list. */
600 pxListItem = pxNext;
601 }
602
603 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
604 bit was set in the control word. */
605 pxEventBits->uxEventBits &= ~uxBitsToClear;
606 }
607 ( void ) xTaskResumeAll();
608
609 return pxEventBits->uxEventBits;
610}
611/*-----------------------------------------------------------*/
612
613void vEventGroupDelete( EventGroupHandle_t xEventGroup )
614{
615EventGroup_t *pxEventBits = xEventGroup;
616const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
617
618 vTaskSuspendAll();
619 {
620 traceEVENT_GROUP_DELETE( xEventGroup );
621
622 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
623 {
624 /* Unblock the task, returning 0 as the event list is being deleted
625 and cannot therefore have any bits set. */
626 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
627 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
628 }
629
630 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
631 {
632 /* The event group can only have been allocated dynamically - free
633 it again. */
634 vPortFree( pxEventBits );
635 }
636 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
637 {
638 /* The event group could have been allocated statically or
639 dynamically, so check before attempting to free the memory. */
640 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
641 {
642 vPortFree( pxEventBits );
643 }
644 else
645 {
646 mtCOVERAGE_TEST_MARKER();
647 }
648 }
649 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
650 }
651 ( void ) xTaskResumeAll();
652}
653/*-----------------------------------------------------------*/
654
655/* For internal use only - execute a 'set bits' command that was pended from
656an interrupt. */
657void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
658{
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. */
660}
661/*-----------------------------------------------------------*/
662
663/* For internal use only - execute a 'clear bits' command that was pended from
664an interrupt. */
665void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
666{
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. */
668}
669/*-----------------------------------------------------------*/
670
671static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
672{
673BaseType_t xWaitConditionMet = pdFALSE;
674
675 if( xWaitForAllBits == pdFALSE )
676 {
677 /* Task only has to wait for one bit within uxBitsToWaitFor to be
678 set. Is one already set? */
679 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
680 {
681 xWaitConditionMet = pdTRUE;
682 }
683 else
684 {
685 mtCOVERAGE_TEST_MARKER();
686 }
687 }
688 else
689 {
690 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
691 Are they set already? */
692 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
693 {
694 xWaitConditionMet = pdTRUE;
695 }
696 else
697 {
698 mtCOVERAGE_TEST_MARKER();
699 }
700 }
701
702 return xWaitConditionMet;
703}
704/*-----------------------------------------------------------*/
705
706#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
707
708 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
709 {
710 BaseType_t xReturn;
711
712 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
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. */
714
715 return xReturn;
716 }
717
718#endif
719/*-----------------------------------------------------------*/
720
721#if (configUSE_TRACE_FACILITY == 1)
722
723 UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
724 {
725 UBaseType_t xReturn;
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. */
727
728 if( xEventGroup == NULL )
729 {
730 xReturn = 0;
731 }
732 else
733 {
734 xReturn = pxEventBits->uxEventGroupNumber;
735 }
736
737 return xReturn;
738 }
739
740#endif /* configUSE_TRACE_FACILITY */
741/*-----------------------------------------------------------*/
742
743#if ( configUSE_TRACE_FACILITY == 1 )
744
745 void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
746 {
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. */
748 }
749
750#endif /* configUSE_TRACE_FACILITY */
751/*-----------------------------------------------------------*/
752
753
Note: See TracBrowser for help on using the repository browser.