]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/event_groups.c
Ensure the code builds when configSUPPORT_STATIC_ALLOCATION is 0.
[freertos] / FreeRTOS / Source / event_groups.c
1 /*\r
2     FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /* Standard includes. */\r
71 #include <stdlib.h>\r
72 \r
73 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
74 all the API functions to use the MPU wrappers.  That should only be done when\r
75 task.h is included from an application file. */\r
76 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
77 \r
78 /* FreeRTOS includes. */\r
79 #include "FreeRTOS.h"\r
80 #include "task.h"\r
81 #include "timers.h"\r
82 #include "event_groups.h"\r
83 \r
84 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
85 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
86 header files above, but not in this file, in order to generate the correct\r
87 privileged Vs unprivileged linkage and placement. */\r
88 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
89 \r
90 /* The following bit fields convey control information in a task's event list\r
91 item value.  It is important they don't clash with the\r
92 taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */\r
93 #if configUSE_16_BIT_TICKS == 1\r
94         #define eventCLEAR_EVENTS_ON_EXIT_BIT   0x0100U\r
95         #define eventUNBLOCKED_DUE_TO_BIT_SET   0x0200U\r
96         #define eventWAIT_FOR_ALL_BITS                  0x0400U\r
97         #define eventEVENT_BITS_CONTROL_BYTES   0xff00U\r
98 #else\r
99         #define eventCLEAR_EVENTS_ON_EXIT_BIT   0x01000000UL\r
100         #define eventUNBLOCKED_DUE_TO_BIT_SET   0x02000000UL\r
101         #define eventWAIT_FOR_ALL_BITS                  0x04000000UL\r
102         #define eventEVENT_BITS_CONTROL_BYTES   0xff000000UL\r
103 #endif\r
104 \r
105 typedef struct xEventGroupDefinition\r
106 {\r
107         EventBits_t uxEventBits;\r
108         List_t xTasksWaitingForBits;            /*< List of tasks waiting for a bit to be set. */\r
109 \r
110         #if( configUSE_TRACE_FACILITY == 1 )\r
111                 UBaseType_t uxEventGroupNumber;\r
112         #endif\r
113 \r
114         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
115                 uint8_t ucStaticallyAllocated;\r
116         #endif\r
117 } EventGroup_t;\r
118 \r
119 /*-----------------------------------------------------------*/\r
120 \r
121 /*\r
122  * Test the bits set in uxCurrentEventBits to see if the wait condition is met.\r
123  * The wait condition is defined by xWaitForAllBits.  If xWaitForAllBits is\r
124  * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor\r
125  * are also set in uxCurrentEventBits.  If xWaitForAllBits is pdFALSE then the\r
126  * wait condition is met if any of the bits set in uxBitsToWait for are also set\r
127  * in uxCurrentEventBits.\r
128  */\r
129 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits );\r
130 \r
131 /*-----------------------------------------------------------*/\r
132 \r
133 EventGroupHandle_t xEventGroupGenericCreate( StaticEventGroup_t *pxStaticEventGroup )\r
134 {\r
135 EventGroup_t *pxEventBits;\r
136 \r
137         if( pxStaticEventGroup == NULL )\r
138         {\r
139                 /* The user has not provided a statically allocated event group, so\r
140                 create on dynamically. */\r
141                 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );\r
142         }\r
143         else\r
144         {\r
145                 /* The user has provided a statically allocated event group - use it. */\r
146                 pxEventBits = ( EventGroup_t * ) pxStaticEventGroup;\r
147         }\r
148 \r
149         if( pxEventBits != NULL )\r
150         {\r
151                 pxEventBits->uxEventBits = 0;\r
152                 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );\r
153 \r
154                 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
155                 {\r
156                         if( pxStaticEventGroup == NULL )\r
157                         {\r
158                                 pxEventBits->ucStaticallyAllocated = pdFALSE;\r
159                         }\r
160                         else\r
161                         {\r
162                                 pxEventBits->ucStaticallyAllocated = pdTRUE;\r
163                         }\r
164                 }\r
165                 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
166 \r
167                 traceEVENT_GROUP_CREATE( pxEventBits );\r
168         }\r
169         else\r
170         {\r
171                 traceEVENT_GROUP_CREATE_FAILED();\r
172         }\r
173 \r
174         return ( EventGroupHandle_t ) pxEventBits;\r
175 }\r
176 /*-----------------------------------------------------------*/\r
177 \r
178 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )\r
179 {\r
180 EventBits_t uxOriginalBitValue, uxReturn;\r
181 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
182 BaseType_t xAlreadyYielded;\r
183 BaseType_t xTimeoutOccurred = pdFALSE;\r
184 \r
185         configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );\r
186         configASSERT( uxBitsToWaitFor != 0 );\r
187         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
188         {\r
189                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
190         }\r
191         #endif\r
192 \r
193         vTaskSuspendAll();\r
194         {\r
195                 uxOriginalBitValue = pxEventBits->uxEventBits;\r
196 \r
197                 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );\r
198 \r
199                 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )\r
200                 {\r
201                         /* All the rendezvous bits are now set - no need to block. */\r
202                         uxReturn = ( uxOriginalBitValue | uxBitsToSet );\r
203 \r
204                         /* Rendezvous always clear the bits.  They will have been cleared\r
205                         already unless this is the only task in the rendezvous. */\r
206                         pxEventBits->uxEventBits &= ~uxBitsToWaitFor;\r
207 \r
208                         xTicksToWait = 0;\r
209                 }\r
210                 else\r
211                 {\r
212                         if( xTicksToWait != ( TickType_t ) 0 )\r
213                         {\r
214                                 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );\r
215 \r
216                                 /* Store the bits that the calling task is waiting for in the\r
217                                 task's event list item so the kernel knows when a match is\r
218                                 found.  Then enter the blocked state. */\r
219                                 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );\r
220 \r
221                                 /* This assignment is obsolete as uxReturn will get set after\r
222                                 the task unblocks, but some compilers mistakenly generate a\r
223                                 warning about uxReturn being returned without being set if the\r
224                                 assignment is omitted. */\r
225                                 uxReturn = 0;\r
226                         }\r
227                         else\r
228                         {\r
229                                 /* The rendezvous bits were not set, but no block time was\r
230                                 specified - just return the current event bit value. */\r
231                                 uxReturn = pxEventBits->uxEventBits;\r
232                         }\r
233                 }\r
234         }\r
235         xAlreadyYielded = xTaskResumeAll();\r
236 \r
237         if( xTicksToWait != ( TickType_t ) 0 )\r
238         {\r
239                 if( xAlreadyYielded == pdFALSE )\r
240                 {\r
241                         portYIELD_WITHIN_API();\r
242                 }\r
243                 else\r
244                 {\r
245                         mtCOVERAGE_TEST_MARKER();\r
246                 }\r
247 \r
248                 /* The task blocked to wait for its required bits to be set - at this\r
249                 point either the required bits were set or the block time expired.  If\r
250                 the required bits were set they will have been stored in the task's\r
251                 event list item, and they should now be retrieved then cleared. */\r
252                 uxReturn = uxTaskResetEventItemValue();\r
253 \r
254                 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )\r
255                 {\r
256                         /* The task timed out, just return the current event bit value. */\r
257                         taskENTER_CRITICAL();\r
258                         {\r
259                                 uxReturn = pxEventBits->uxEventBits;\r
260 \r
261                                 /* Although the task got here because it timed out before the\r
262                                 bits it was waiting for were set, it is possible that since it\r
263                                 unblocked another task has set the bits.  If this is the case\r
264                                 then it needs to clear the bits before exiting. */\r
265                                 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )\r
266                                 {\r
267                                         pxEventBits->uxEventBits &= ~uxBitsToWaitFor;\r
268                                 }\r
269                                 else\r
270                                 {\r
271                                         mtCOVERAGE_TEST_MARKER();\r
272                                 }\r
273                         }\r
274                         taskEXIT_CRITICAL();\r
275 \r
276                         xTimeoutOccurred = pdTRUE;\r
277                 }\r
278                 else\r
279                 {\r
280                         /* The task unblocked because the bits were set. */\r
281                 }\r
282 \r
283                 /* Control bits might be set as the task had blocked should not be\r
284                 returned. */\r
285                 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;\r
286         }\r
287 \r
288         traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );\r
289 \r
290         return uxReturn;\r
291 }\r
292 /*-----------------------------------------------------------*/\r
293 \r
294 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )\r
295 {\r
296 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
297 EventBits_t uxReturn, uxControlBits = 0;\r
298 BaseType_t xWaitConditionMet, xAlreadyYielded;\r
299 BaseType_t xTimeoutOccurred = pdFALSE;\r
300 \r
301         /* Check the user is not attempting to wait on the bits used by the kernel\r
302         itself, and that at least one bit is being requested. */\r
303         configASSERT( xEventGroup );\r
304         configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );\r
305         configASSERT( uxBitsToWaitFor != 0 );\r
306         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
307         {\r
308                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
309         }\r
310         #endif\r
311 \r
312         vTaskSuspendAll();\r
313         {\r
314                 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;\r
315 \r
316                 /* Check to see if the wait condition is already met or not. */\r
317                 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );\r
318 \r
319                 if( xWaitConditionMet != pdFALSE )\r
320                 {\r
321                         /* The wait condition has already been met so there is no need to\r
322                         block. */\r
323                         uxReturn = uxCurrentEventBits;\r
324                         xTicksToWait = ( TickType_t ) 0;\r
325 \r
326                         /* Clear the wait bits if requested to do so. */\r
327                         if( xClearOnExit != pdFALSE )\r
328                         {\r
329                                 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;\r
330                         }\r
331                         else\r
332                         {\r
333                                 mtCOVERAGE_TEST_MARKER();\r
334                         }\r
335                 }\r
336                 else if( xTicksToWait == ( TickType_t ) 0 )\r
337                 {\r
338                         /* The wait condition has not been met, but no block time was\r
339                         specified, so just return the current value. */\r
340                         uxReturn = uxCurrentEventBits;\r
341                 }\r
342                 else\r
343                 {\r
344                         /* The task is going to block to wait for its required bits to be\r
345                         set.  uxControlBits are used to remember the specified behaviour of\r
346                         this call to xEventGroupWaitBits() - for use when the event bits\r
347                         unblock the task. */\r
348                         if( xClearOnExit != pdFALSE )\r
349                         {\r
350                                 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;\r
351                         }\r
352                         else\r
353                         {\r
354                                 mtCOVERAGE_TEST_MARKER();\r
355                         }\r
356 \r
357                         if( xWaitForAllBits != pdFALSE )\r
358                         {\r
359                                 uxControlBits |= eventWAIT_FOR_ALL_BITS;\r
360                         }\r
361                         else\r
362                         {\r
363                                 mtCOVERAGE_TEST_MARKER();\r
364                         }\r
365 \r
366                         /* Store the bits that the calling task is waiting for in the\r
367                         task's event list item so the kernel knows when a match is\r
368                         found.  Then enter the blocked state. */\r
369                         vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );\r
370 \r
371                         /* This is obsolete as it will get set after the task unblocks, but\r
372                         some compilers mistakenly generate a warning about the variable\r
373                         being returned without being set if it is not done. */\r
374                         uxReturn = 0;\r
375 \r
376                         traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );\r
377                 }\r
378         }\r
379         xAlreadyYielded = xTaskResumeAll();\r
380 \r
381         if( xTicksToWait != ( TickType_t ) 0 )\r
382         {\r
383                 if( xAlreadyYielded == pdFALSE )\r
384                 {\r
385                         portYIELD_WITHIN_API();\r
386                 }\r
387                 else\r
388                 {\r
389                         mtCOVERAGE_TEST_MARKER();\r
390                 }\r
391 \r
392                 /* The task blocked to wait for its required bits to be set - at this\r
393                 point either the required bits were set or the block time expired.  If\r
394                 the required bits were set they will have been stored in the task's\r
395                 event list item, and they should now be retrieved then cleared. */\r
396                 uxReturn = uxTaskResetEventItemValue();\r
397 \r
398                 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )\r
399                 {\r
400                         taskENTER_CRITICAL();\r
401                         {\r
402                                 /* The task timed out, just return the current event bit value. */\r
403                                 uxReturn = pxEventBits->uxEventBits;\r
404 \r
405                                 /* It is possible that the event bits were updated between this\r
406                                 task leaving the Blocked state and running again. */\r
407                                 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )\r
408                                 {\r
409                                         if( xClearOnExit != pdFALSE )\r
410                                         {\r
411                                                 pxEventBits->uxEventBits &= ~uxBitsToWaitFor;\r
412                                         }\r
413                                         else\r
414                                         {\r
415                                                 mtCOVERAGE_TEST_MARKER();\r
416                                         }\r
417                                 }\r
418                                 else\r
419                                 {\r
420                                         mtCOVERAGE_TEST_MARKER();\r
421                                 }\r
422                         }\r
423                         taskEXIT_CRITICAL();\r
424 \r
425                         /* Prevent compiler warnings when trace macros are not used. */\r
426                         xTimeoutOccurred = pdFALSE;\r
427                 }\r
428                 else\r
429                 {\r
430                         /* The task unblocked because the bits were set. */\r
431                 }\r
432 \r
433                 /* The task blocked so control bits may have been set. */\r
434                 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;\r
435         }\r
436         traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );\r
437 \r
438         return uxReturn;\r
439 }\r
440 /*-----------------------------------------------------------*/\r
441 \r
442 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )\r
443 {\r
444 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
445 EventBits_t uxReturn;\r
446 \r
447         /* Check the user is not attempting to clear the bits used by the kernel\r
448         itself. */\r
449         configASSERT( xEventGroup );\r
450         configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );\r
451 \r
452         taskENTER_CRITICAL();\r
453         {\r
454                 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );\r
455 \r
456                 /* The value returned is the event group value prior to the bits being\r
457                 cleared. */\r
458                 uxReturn = pxEventBits->uxEventBits;\r
459 \r
460                 /* Clear the bits. */\r
461                 pxEventBits->uxEventBits &= ~uxBitsToClear;\r
462         }\r
463         taskEXIT_CRITICAL();\r
464 \r
465         return uxReturn;\r
466 }\r
467 /*-----------------------------------------------------------*/\r
468 \r
469 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )\r
470 \r
471         BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )\r
472         {\r
473                 BaseType_t xReturn;\r
474 \r
475                 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );\r
476                 xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );\r
477 \r
478                 return xReturn;\r
479         }\r
480 \r
481 #endif\r
482 /*-----------------------------------------------------------*/\r
483 \r
484 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )\r
485 {\r
486 UBaseType_t uxSavedInterruptStatus;\r
487 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
488 EventBits_t uxReturn;\r
489 \r
490         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
491         {\r
492                 uxReturn = pxEventBits->uxEventBits;\r
493         }\r
494         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
495 \r
496         return uxReturn;\r
497 }\r
498 /*-----------------------------------------------------------*/\r
499 \r
500 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )\r
501 {\r
502 ListItem_t *pxListItem, *pxNext;\r
503 ListItem_t const *pxListEnd;\r
504 List_t *pxList;\r
505 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;\r
506 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
507 BaseType_t xMatchFound = pdFALSE;\r
508 \r
509         /* Check the user is not attempting to set the bits used by the kernel\r
510         itself. */\r
511         configASSERT( xEventGroup );\r
512         configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );\r
513 \r
514         pxList = &( pxEventBits->xTasksWaitingForBits );\r
515         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. */\r
516         vTaskSuspendAll();\r
517         {\r
518                 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );\r
519 \r
520                 pxListItem = listGET_HEAD_ENTRY( pxList );\r
521 \r
522                 /* Set the bits. */\r
523                 pxEventBits->uxEventBits |= uxBitsToSet;\r
524 \r
525                 /* See if the new bit value should unblock any tasks. */\r
526                 while( pxListItem != pxListEnd )\r
527                 {\r
528                         pxNext = listGET_NEXT( pxListItem );\r
529                         uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );\r
530                         xMatchFound = pdFALSE;\r
531 \r
532                         /* Split the bits waited for from the control bits. */\r
533                         uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;\r
534                         uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;\r
535 \r
536                         if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )\r
537                         {\r
538                                 /* Just looking for single bit being set. */\r
539                                 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )\r
540                                 {\r
541                                         xMatchFound = pdTRUE;\r
542                                 }\r
543                                 else\r
544                                 {\r
545                                         mtCOVERAGE_TEST_MARKER();\r
546                                 }\r
547                         }\r
548                         else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )\r
549                         {\r
550                                 /* All bits are set. */\r
551                                 xMatchFound = pdTRUE;\r
552                         }\r
553                         else\r
554                         {\r
555                                 /* Need all bits to be set, but not all the bits were set. */\r
556                         }\r
557 \r
558                         if( xMatchFound != pdFALSE )\r
559                         {\r
560                                 /* The bits match.  Should the bits be cleared on exit? */\r
561                                 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )\r
562                                 {\r
563                                         uxBitsToClear |= uxBitsWaitedFor;\r
564                                 }\r
565                                 else\r
566                                 {\r
567                                         mtCOVERAGE_TEST_MARKER();\r
568                                 }\r
569 \r
570                                 /* Store the actual event flag value in the task's event list\r
571                                 item before removing the task from the event list.  The\r
572                                 eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows\r
573                                 that is was unblocked due to its required bits matching, rather\r
574                                 than because it timed out. */\r
575                                 ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );\r
576                         }\r
577 \r
578                         /* Move onto the next list item.  Note pxListItem->pxNext is not\r
579                         used here as the list item may have been removed from the event list\r
580                         and inserted into the ready/pending reading list. */\r
581                         pxListItem = pxNext;\r
582                 }\r
583 \r
584                 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT\r
585                 bit was set in the control word. */\r
586                 pxEventBits->uxEventBits &= ~uxBitsToClear;\r
587         }\r
588         ( void ) xTaskResumeAll();\r
589 \r
590         return pxEventBits->uxEventBits;\r
591 }\r
592 /*-----------------------------------------------------------*/\r
593 \r
594 void vEventGroupDelete( EventGroupHandle_t xEventGroup )\r
595 {\r
596 EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
597 const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );\r
598 \r
599         vTaskSuspendAll();\r
600         {\r
601                 traceEVENT_GROUP_DELETE( xEventGroup );\r
602 \r
603                 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )\r
604                 {\r
605                         /* Unblock the task, returning 0 as the event list is being deleted\r
606                         and     cannot therefore have any bits set. */\r
607                         configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );\r
608                         ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );\r
609                 }\r
610 \r
611                 /* Only free the memory if it was allocated dynamically. */\r
612                 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
613                 {\r
614                         if( pxEventBits->ucStaticallyAllocated == pdFALSE )\r
615                         {\r
616                                 vPortFree( pxEventBits );\r
617                         }\r
618                 }\r
619                 #else\r
620                 {\r
621                         vPortFree( pxEventBits );\r
622                 }\r
623                 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
624         }\r
625         ( void ) xTaskResumeAll();\r
626 }\r
627 /*-----------------------------------------------------------*/\r
628 \r
629 /* For internal use only - execute a 'set bits' command that was pended from\r
630 an interrupt. */\r
631 void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )\r
632 {\r
633         ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );\r
634 }\r
635 /*-----------------------------------------------------------*/\r
636 \r
637 /* For internal use only - execute a 'clear bits' command that was pended from\r
638 an interrupt. */\r
639 void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )\r
640 {\r
641         ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );\r
642 }\r
643 /*-----------------------------------------------------------*/\r
644 \r
645 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )\r
646 {\r
647 BaseType_t xWaitConditionMet = pdFALSE;\r
648 \r
649         if( xWaitForAllBits == pdFALSE )\r
650         {\r
651                 /* Task only has to wait for one bit within uxBitsToWaitFor to be\r
652                 set.  Is one already set? */\r
653                 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )\r
654                 {\r
655                         xWaitConditionMet = pdTRUE;\r
656                 }\r
657                 else\r
658                 {\r
659                         mtCOVERAGE_TEST_MARKER();\r
660                 }\r
661         }\r
662         else\r
663         {\r
664                 /* Task has to wait for all the bits in uxBitsToWaitFor to be set.\r
665                 Are they set already? */\r
666                 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )\r
667                 {\r
668                         xWaitConditionMet = pdTRUE;\r
669                 }\r
670                 else\r
671                 {\r
672                         mtCOVERAGE_TEST_MARKER();\r
673                 }\r
674         }\r
675 \r
676         return xWaitConditionMet;\r
677 }\r
678 /*-----------------------------------------------------------*/\r
679 \r
680 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )\r
681 \r
682         BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )\r
683         {\r
684         BaseType_t xReturn;\r
685 \r
686                 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );\r
687                 xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );\r
688 \r
689                 return xReturn;\r
690         }\r
691 \r
692 #endif\r
693 /*-----------------------------------------------------------*/\r
694 \r
695 #if (configUSE_TRACE_FACILITY == 1)\r
696 \r
697         UBaseType_t uxEventGroupGetNumber( void* xEventGroup )\r
698         {\r
699         UBaseType_t xReturn;\r
700         EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
701 \r
702                 if( xEventGroup == NULL )\r
703                 {\r
704                         xReturn = 0;\r
705                 }\r
706                 else\r
707                 {\r
708                         xReturn = pxEventBits->uxEventGroupNumber;\r
709                 }\r
710 \r
711                 return xReturn;\r
712         }\r
713 \r
714 #endif\r
715 \r