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