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