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