blob: 14d7b024e5951fac8d0eeaa4e70687a3a8516aeb [file] [log] [blame]
Qiufang Dai35c31332020-05-13 15:29:06 +08001/*
2 * FreeRTOS Kernel V10.0.1
3 * Copyright (C) 2017 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 and e750 are suppressed as a MISRA exception justified because the
43MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
44header files above, but not in this file, in order to generate the correct
45privileged Vs unprivileged linkage and placement. */
46#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
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 xEventGroupDefinition
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 }
108 #endif /* configASSERT_DEFINED */
109
110 /* The user has provided a statically allocated event group - use it. */
111 pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are 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 traceEVENT_GROUP_CREATE_FAILED();
132 }
133
134 return ( EventGroupHandle_t ) pxEventBits;
135 }
136
137#endif /* configSUPPORT_STATIC_ALLOCATION */
138/*-----------------------------------------------------------*/
139
140#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
141
142 EventGroupHandle_t xEventGroupCreate( void )
143 {
144 EventGroup_t *pxEventBits;
145
146 /* Allocate the event group. */
147 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
148
149 if( pxEventBits != NULL )
150 {
151 pxEventBits->uxEventBits = 0;
152 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
153
154 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
155 {
156 /* Both static and dynamic allocation can be used, so note this
157 event group was allocated statically in case the event group is
158 later deleted. */
159 pxEventBits->ucStaticallyAllocated = pdFALSE;
160 }
161 #endif /* configSUPPORT_STATIC_ALLOCATION */
162
163 traceEVENT_GROUP_CREATE( pxEventBits );
164 }
165 else
166 {
167 traceEVENT_GROUP_CREATE_FAILED();
168 }
169
170 return ( EventGroupHandle_t ) pxEventBits;
171 }
172
173#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
174/*-----------------------------------------------------------*/
175
176EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
177{
178EventBits_t uxOriginalBitValue, uxReturn;
179EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
180BaseType_t xAlreadyYielded;
181BaseType_t xTimeoutOccurred = pdFALSE;
182
183 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
184 configASSERT( uxBitsToWaitFor != 0 );
185 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
186 {
187 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
188 }
189 #endif
190
191 vTaskSuspendAll();
192 {
193 uxOriginalBitValue = pxEventBits->uxEventBits;
194
195 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
196
197 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
198 {
199 /* All the rendezvous bits are now set - no need to block. */
200 uxReturn = ( uxOriginalBitValue | uxBitsToSet );
201
202 /* Rendezvous always clear the bits. They will have been cleared
203 already unless this is the only task in the rendezvous. */
204 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
205
206 xTicksToWait = 0;
207 }
208 else
209 {
210 if( xTicksToWait != ( TickType_t ) 0 )
211 {
212 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
213
214 /* Store the bits that the calling task is waiting for in the
215 task's event list item so the kernel knows when a match is
216 found. Then enter the blocked state. */
217 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
218
219 /* This assignment is obsolete as uxReturn will get set after
220 the task unblocks, but some compilers mistakenly generate a
221 warning about uxReturn being returned without being set if the
222 assignment is omitted. */
223 uxReturn = 0;
224 }
225 else
226 {
227 /* The rendezvous bits were not set, but no block time was
228 specified - just return the current event bit value. */
229 uxReturn = pxEventBits->uxEventBits;
230 xTimeoutOccurred = pdTRUE;
231 }
232 }
233 }
234 xAlreadyYielded = xTaskResumeAll();
235
236 if( xTicksToWait != ( TickType_t ) 0 )
237 {
238 if( xAlreadyYielded == pdFALSE )
239 {
240 portYIELD_WITHIN_API();
241 }
242 else
243 {
244 mtCOVERAGE_TEST_MARKER();
245 }
246
247 /* The task blocked to wait for its required bits to be set - at this
248 point either the required bits were set or the block time expired. If
249 the required bits were set they will have been stored in the task's
250 event list item, and they should now be retrieved then cleared. */
251 uxReturn = uxTaskResetEventItemValue();
252
253 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
254 {
255 /* The task timed out, just return the current event bit value. */
256 taskENTER_CRITICAL();
257 {
258 uxReturn = pxEventBits->uxEventBits;
259
260 /* Although the task got here because it timed out before the
261 bits it was waiting for were set, it is possible that since it
262 unblocked another task has set the bits. If this is the case
263 then it needs to clear the bits before exiting. */
264 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
265 {
266 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
267 }
268 else
269 {
270 mtCOVERAGE_TEST_MARKER();
271 }
272 }
273 taskEXIT_CRITICAL();
274
275 xTimeoutOccurred = pdTRUE;
276 }
277 else
278 {
279 /* The task unblocked because the bits were set. */
280 }
281
282 /* Control bits might be set as the task had blocked should not be
283 returned. */
284 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
285 }
286
287 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
288
289 /* Prevent compiler warnings when trace macros are not used. */
290 ( void ) xTimeoutOccurred;
291
292 return uxReturn;
293}
294/*-----------------------------------------------------------*/
295
296EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
297{
298EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
299EventBits_t uxReturn, uxControlBits = 0;
300BaseType_t xWaitConditionMet, xAlreadyYielded;
301BaseType_t xTimeoutOccurred = pdFALSE;
302
303 /* Check the user is not attempting to wait on the bits used by the kernel
304 itself, and that at least one bit is being requested. */
305 configASSERT( xEventGroup );
306 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
307 configASSERT( uxBitsToWaitFor != 0 );
308 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
309 {
310 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
311 }
312 #endif
313
314 vTaskSuspendAll();
315 {
316 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
317
318 /* Check to see if the wait condition is already met or not. */
319 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
320
321 if( xWaitConditionMet != pdFALSE )
322 {
323 /* The wait condition has already been met so there is no need to
324 block. */
325 uxReturn = uxCurrentEventBits;
326 xTicksToWait = ( TickType_t ) 0;
327
328 /* Clear the wait bits if requested to do so. */
329 if( xClearOnExit != pdFALSE )
330 {
331 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
332 }
333 else
334 {
335 mtCOVERAGE_TEST_MARKER();
336 }
337 }
338 else if( xTicksToWait == ( TickType_t ) 0 )
339 {
340 /* The wait condition has not been met, but no block time was
341 specified, so just return the current value. */
342 uxReturn = uxCurrentEventBits;
343 xTimeoutOccurred = pdTRUE;
344 }
345 else
346 {
347 /* The task is going to block to wait for its required bits to be
348 set. uxControlBits are used to remember the specified behaviour of
349 this call to xEventGroupWaitBits() - for use when the event bits
350 unblock the task. */
351 if( xClearOnExit != pdFALSE )
352 {
353 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
354 }
355 else
356 {
357 mtCOVERAGE_TEST_MARKER();
358 }
359
360 if( xWaitForAllBits != pdFALSE )
361 {
362 uxControlBits |= eventWAIT_FOR_ALL_BITS;
363 }
364 else
365 {
366 mtCOVERAGE_TEST_MARKER();
367 }
368
369 /* Store the bits that the calling task is waiting for in the
370 task's event list item so the kernel knows when a match is
371 found. Then enter the blocked state. */
372 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
373
374 /* This is obsolete as it will get set after the task unblocks, but
375 some compilers mistakenly generate a warning about the variable
376 being returned without being set if it is not done. */
377 uxReturn = 0;
378
379 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
380 }
381 }
382 xAlreadyYielded = xTaskResumeAll();
383
384 if( xTicksToWait != ( TickType_t ) 0 )
385 {
386 if( xAlreadyYielded == pdFALSE )
387 {
388 portYIELD_WITHIN_API();
389 }
390 else
391 {
392 mtCOVERAGE_TEST_MARKER();
393 }
394
395 /* The task blocked to wait for its required bits to be set - at this
396 point either the required bits were set or the block time expired. If
397 the required bits were set they will have been stored in the task's
398 event list item, and they should now be retrieved then cleared. */
399 uxReturn = uxTaskResetEventItemValue();
400
401 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
402 {
403 taskENTER_CRITICAL();
404 {
405 /* The task timed out, just return the current event bit value. */
406 uxReturn = pxEventBits->uxEventBits;
407
408 /* It is possible that the event bits were updated between this
409 task leaving the Blocked state and running again. */
410 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
411 {
412 if( xClearOnExit != pdFALSE )
413 {
414 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
415 }
416 else
417 {
418 mtCOVERAGE_TEST_MARKER();
419 }
420 }
421 else
422 {
423 mtCOVERAGE_TEST_MARKER();
424 }
425 xTimeoutOccurred = pdTRUE;
426 }
427 taskEXIT_CRITICAL();
428 }
429 else
430 {
431 /* The task unblocked because the bits were set. */
432 }
433
434 /* The task blocked so control bits may have been set. */
435 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
436 }
437 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
438
439 /* Prevent compiler warnings when trace macros are not used. */
440 ( void ) xTimeoutOccurred;
441
442 return uxReturn;
443}
444/*-----------------------------------------------------------*/
445
446EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
447{
448EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
449EventBits_t uxReturn;
450
451 /* Check the user is not attempting to clear the bits used by the kernel
452 itself. */
453 configASSERT( xEventGroup );
454 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
455
456 taskENTER_CRITICAL();
457 {
458 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
459
460 /* The value returned is the event group value prior to the bits being
461 cleared. */
462 uxReturn = pxEventBits->uxEventBits;
463
464 /* Clear the bits. */
465 pxEventBits->uxEventBits &= ~uxBitsToClear;
466 }
467 taskEXIT_CRITICAL();
468
469 return uxReturn;
470}
471/*-----------------------------------------------------------*/
472
473#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
474
475 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
476 {
477 BaseType_t xReturn;
478
479 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
480 xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
481
482 return xReturn;
483 }
484
485#endif
486/*-----------------------------------------------------------*/
487
488EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
489{
490UBaseType_t uxSavedInterruptStatus;
491EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
492EventBits_t uxReturn;
493
494 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
495 {
496 uxReturn = pxEventBits->uxEventBits;
497 }
498 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
499
500 return uxReturn;
501}
502/*-----------------------------------------------------------*/
503
504EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
505{
506ListItem_t *pxListItem, *pxNext;
507ListItem_t const *pxListEnd;
508List_t *pxList;
509EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
510EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
511BaseType_t xMatchFound = pdFALSE;
512
513 /* Check the user is not attempting to set the bits used by the kernel
514 itself. */
515 configASSERT( xEventGroup );
516 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
517
518 pxList = &( pxEventBits->xTasksWaitingForBits );
519 pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
520 vTaskSuspendAll();
521 {
522 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
523
524 pxListItem = listGET_HEAD_ENTRY( pxList );
525
526 /* Set the bits. */
527 pxEventBits->uxEventBits |= uxBitsToSet;
528
529 /* See if the new bit value should unblock any tasks. */
530 while( pxListItem != pxListEnd )
531 {
532 pxNext = listGET_NEXT( pxListItem );
533 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
534 xMatchFound = pdFALSE;
535
536 /* Split the bits waited for from the control bits. */
537 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
538 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
539
540 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
541 {
542 /* Just looking for single bit being set. */
543 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
544 {
545 xMatchFound = pdTRUE;
546 }
547 else
548 {
549 mtCOVERAGE_TEST_MARKER();
550 }
551 }
552 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
553 {
554 /* All bits are set. */
555 xMatchFound = pdTRUE;
556 }
557 else
558 {
559 /* Need all bits to be set, but not all the bits were set. */
560 }
561
562 if( xMatchFound != pdFALSE )
563 {
564 /* The bits match. Should the bits be cleared on exit? */
565 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
566 {
567 uxBitsToClear |= uxBitsWaitedFor;
568 }
569 else
570 {
571 mtCOVERAGE_TEST_MARKER();
572 }
573
574 /* Store the actual event flag value in the task's event list
575 item before removing the task from the event list. The
576 eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
577 that is was unblocked due to its required bits matching, rather
578 than because it timed out. */
579 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
580 }
581
582 /* Move onto the next list item. Note pxListItem->pxNext is not
583 used here as the list item may have been removed from the event list
584 and inserted into the ready/pending reading list. */
585 pxListItem = pxNext;
586 }
587
588 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
589 bit was set in the control word. */
590 pxEventBits->uxEventBits &= ~uxBitsToClear;
591 }
592 ( void ) xTaskResumeAll();
593
594 return pxEventBits->uxEventBits;
595}
596/*-----------------------------------------------------------*/
597
598void vEventGroupDelete( EventGroupHandle_t xEventGroup )
599{
600EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
601const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
602
603 vTaskSuspendAll();
604 {
605 traceEVENT_GROUP_DELETE( xEventGroup );
606
607 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
608 {
609 /* Unblock the task, returning 0 as the event list is being deleted
610 and cannot therefore have any bits set. */
611 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
612 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
613 }
614
615 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
616 {
617 /* The event group can only have been allocated dynamically - free
618 it again. */
619 vPortFree( pxEventBits );
620 }
621 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
622 {
623 /* The event group could have been allocated statically or
624 dynamically, so check before attempting to free the memory. */
625 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
626 {
627 vPortFree( pxEventBits );
628 }
629 else
630 {
631 mtCOVERAGE_TEST_MARKER();
632 }
633 }
634 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
635 }
636 ( void ) xTaskResumeAll();
637}
638/*-----------------------------------------------------------*/
639
640/* For internal use only - execute a 'set bits' command that was pended from
641an interrupt. */
642void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
643{
644 ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
645}
646/*-----------------------------------------------------------*/
647
648/* For internal use only - execute a 'clear bits' command that was pended from
649an interrupt. */
650void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
651{
652 ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
653}
654/*-----------------------------------------------------------*/
655
656static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
657{
658BaseType_t xWaitConditionMet = pdFALSE;
659
660 if( xWaitForAllBits == pdFALSE )
661 {
662 /* Task only has to wait for one bit within uxBitsToWaitFor to be
663 set. Is one already set? */
664 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
665 {
666 xWaitConditionMet = pdTRUE;
667 }
668 else
669 {
670 mtCOVERAGE_TEST_MARKER();
671 }
672 }
673 else
674 {
675 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
676 Are they set already? */
677 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
678 {
679 xWaitConditionMet = pdTRUE;
680 }
681 else
682 {
683 mtCOVERAGE_TEST_MARKER();
684 }
685 }
686
687 return xWaitConditionMet;
688}
689/*-----------------------------------------------------------*/
690
691#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
692
693 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
694 {
695 BaseType_t xReturn;
696
697 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
698 xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
699
700 return xReturn;
701 }
702
703#endif
704/*-----------------------------------------------------------*/
705
706#if (configUSE_TRACE_FACILITY == 1)
707
708 UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
709 {
710 UBaseType_t xReturn;
711 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
712
713 if( xEventGroup == NULL )
714 {
715 xReturn = 0;
716 }
717 else
718 {
719 xReturn = pxEventBits->uxEventGroupNumber;
720 }
721
722 return xReturn;
723 }
724
725#endif /* configUSE_TRACE_FACILITY */
726/*-----------------------------------------------------------*/
727
728#if ( configUSE_TRACE_FACILITY == 1 )
729
730 void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
731 {
732 ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
733 }
734
735#endif /* configUSE_TRACE_FACILITY */
736/*-----------------------------------------------------------*/
737
738