]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
Replace use of legacy portTYPE macros from old demos and standard demo files.
[freertos] / FreeRTOS / Demo / Common / Minimal / EventGroupsDemo.c
1 /*\r
2     FreeRTOS V7.6.0 - Copyright (C) 2013 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     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS provides completely free yet professionally developed,    *\r
10      *    robust, strictly quality controlled, supported, and cross          *\r
11      *    platform software that has become a de facto standard.             *\r
12      *                                                                       *\r
13      *    Help yourself get started quickly and support the FreeRTOS         *\r
14      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
15      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
16      *                                                                       *\r
17      *    Thank you!                                                         *\r
18      *                                                                       *\r
19     ***************************************************************************\r
20 \r
21     This file is part of the FreeRTOS distribution.\r
22 \r
23     FreeRTOS is free software; you can redistribute it and/or modify it under\r
24     the terms of the GNU General Public License (version 2) as published by the\r
25     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
26 \r
27     >>! NOTE: The modification to the GPL is included to allow you to distribute\r
28     >>! a combined work that includes FreeRTOS without being obliged to provide\r
29     >>! the source code for proprietary components outside of the FreeRTOS\r
30     >>! kernel.\r
31 \r
32     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
33     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
34     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
35     link: http://www.freertos.org/a00114.html\r
36 \r
37     1 tab == 4 spaces!\r
38 \r
39     ***************************************************************************\r
40      *                                                                       *\r
41      *    Having a problem?  Start by reading the FAQ "My application does   *\r
42      *    not run, what could be wrong?"                                     *\r
43      *                                                                       *\r
44      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
49     license and Real Time Engineers Ltd. contact details.\r
50 \r
51     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
52     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
53     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
54 \r
55     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
56     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
57     licenses offer ticketed support, indemnification and middleware.\r
58 \r
59     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
60     engineered and independently SIL3 certified version for use in safety and\r
61     mission critical applications that require provable dependability.\r
62 \r
63     1 tab == 4 spaces!\r
64 */\r
65 \r
66 \r
67 \r
68 /*\r
69  * This file contains fairly comprehensive checks on the behaviour of event\r
70  * groups.  It is not intended to be a user friendly demonstration of the event\r
71  * groups API.\r
72  */\r
73 \r
74 \r
75 \r
76 /* Scheduler include files. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 #include "event_groups.h"\r
80 \r
81 /* Priorities used by the tasks. */\r
82 #define ebSET_BIT_TASK_PRIORITY         ( tskIDLE_PRIORITY )\r
83 #define ebWAIT_BIT_TASK_PRIORITY        ( tskIDLE_PRIORITY + 1 )\r
84 \r
85 /* Generic bit definitions. */\r
86 #define ebBIT_0         ( 0x01UL )\r
87 #define ebBIT_1         ( 0x02UL )\r
88 #define ebBIT_2         ( 0x04UL )\r
89 #define ebBIT_3         ( 0x08UL )\r
90 #define ebBIT_4         ( 0x10UL )\r
91 #define ebBIT_5         ( 0x20UL )\r
92 #define ebBIT_6         ( 0x40UL )\r
93 #define ebBIT_7         ( 0x80UL )\r
94 \r
95 /* Combinations of bits used in the tests. */\r
96 #define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 )\r
97 #define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )\r
98 \r
99 /* Associate a bit to each task.  These bits are used to identify all the tasks\r
100 that synchronise with the xEventGroupSync() function. */\r
101 #define ebSET_BIT_TASK_SYNC_BIT                 ebBIT_0\r
102 #define ebWAIT_BIT_TASK_SYNC_BIT                ebBIT_1\r
103 #define ebRENDESVOUS_TASK_1_SYNC_BIT    ebBIT_2\r
104 #define ebRENDESVOUS_TASK_2_SYNC_BIT    ebBIT_3\r
105 #define ebALL_SYNC_BITS ( ebSET_BIT_TASK_SYNC_BIT | ebWAIT_BIT_TASK_SYNC_BIT | ebRENDESVOUS_TASK_1_SYNC_BIT | ebRENDESVOUS_TASK_2_SYNC_BIT )\r
106 \r
107 /* A block time of zero simply means "don't block". */\r
108 #define ebDONT_BLOCK    ( 0 )\r
109 \r
110 /* A 5ms delay. */\r
111 #define ebSHORT_DELAY   ( 5 / portTICK_RATE_MS )\r
112 \r
113 /* Used in the selective bits test which checks no, one or both tasks blocked on\r
114 event bits in a group are unblocked as appropriate as different bits get set. */\r
115 #define ebSELECTIVE_BITS_1              0x03\r
116 #define ebSELECTIVE_BITS_2              0x05\r
117 \r
118 /*-----------------------------------------------------------*/\r
119 \r
120 /*\r
121  * The primary task that manages and controls all the behavioural tests.\r
122  */\r
123 static void prvSetBitsTask( void *pvParameters );\r
124 \r
125 /*\r
126  * The task that participates in most of the non 'single task' tests performed\r
127  * by prvSetBitsTask().\r
128  */\r
129 static void prvWaitBitsTask( void *pvParameters );\r
130 \r
131 /*\r
132  * Two instances of prvSyncTask() are created.  Their only purpose is to\r
133  * participate in synchronisations and test the behaviour when an event group on\r
134  * which they are blocked is deleted.\r
135  */\r
136 static void prvSyncTask( void *pvParameters );\r
137 \r
138 /*\r
139  * Functions used in a test that blocks two tasks on various different bits\r
140  * within an event group - then sets each bit in turn and checks that the \r
141  * correct tasks unblock at the correct times.\r
142  */\r
143 static portBASE_TYPE prvTestSelectiveBits( void );\r
144 static void prvPreSyncSelectiveWakeTest( void );\r
145 \r
146 /*-----------------------------------------------------------*/\r
147 \r
148 /* Variables that are incremented by the tasks on each cycle provided no errors\r
149 have been found.  Used to detect an error or stall in the test cycling. */\r
150 static volatile unsigned long ulSetBitCycles = 0, ulWaitBitCycles = 0;\r
151 \r
152 /* The event group used by all the tests. */\r
153 static EventGroupHandle_t xEventBits = NULL;\r
154 \r
155 /* Handles to the tasks that only take part in the synchronisation calls. */\r
156 static xTaskHandle xSyncTask1 = NULL, xSyncTask2 = NULL;\r
157 \r
158 /*-----------------------------------------------------------*/\r
159 \r
160 void vStartEventGroupTasks( void )\r
161 {\r
162 xTaskHandle xWaitBitsTaskHandle;\r
163 \r
164         /*\r
165          * This file contains fairly comprehensive checks on the behaviour of event\r
166          * groups.  It is not intended to be a user friendly demonstration of the\r
167          * event groups API.\r
168          */\r
169 \r
170         xTaskCreate( prvWaitBitsTask, "WaitO", configMINIMAL_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xWaitBitsTaskHandle );\r
171         xTaskCreate( prvSetBitsTask, "SetB", configMINIMAL_STACK_SIZE, ( void * ) xWaitBitsTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL );\r
172         xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );\r
173         xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 );\r
174 \r
175         /* If the last task was created then the others will have been too. */\r
176         configASSERT( xSyncTask2 );\r
177 }\r
178 /*-----------------------------------------------------------*/\r
179 \r
180 static void prvSyncTask( void *pvParameters )\r
181 {\r
182 EventBits_t uxSynchronisationBit, uxReturned;\r
183 \r
184         /* The bit to use to indicate this task is at the synchronisation point is\r
185         passed in as the task parameter. */\r
186         uxSynchronisationBit = ( EventBits_t ) pvParameters;\r
187 \r
188         /* A few tests are performed before entering the main demo loop. */\r
189         prvPreSyncSelectiveWakeTest();\r
190 \r
191         for( ;; )\r
192         {\r
193                 /* Wait until the 'set bit' task unsuspends this task. */\r
194                 vTaskSuspend( NULL );\r
195 \r
196                 /* Set the bit that indicates this task is at the synchronisation\r
197                 point.  The first time this is done the 'set bit' task has a lower\r
198                 priority than this task. */\r
199                 uxReturned = xEventGroupSync( xEventBits, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );\r
200                 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
201 \r
202                 /* Wait until the 'set bit' task unsuspends this task again. */\r
203                 vTaskSuspend( NULL );\r
204 \r
205                 /* Set the bit that indicates this task is at the synchronisation\r
206                 point again.  This time the 'set bit' task has a higher priority than\r
207                 this task. */\r
208                 uxReturned = xEventGroupSync( xEventBits, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );\r
209                 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
210 \r
211                 /* Block on the event group again.  This time the event group is going\r
212                 to be deleted, so 0 should be returned. */\r
213                 uxReturned = xEventGroupWaitBits( xEventBits, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
214                 configASSERT( uxReturned == 0 );\r
215         }\r
216 }\r
217 /*-----------------------------------------------------------*/\r
218 \r
219 static void prvWaitBitsTask( void *pvParameters )\r
220 {\r
221 EventBits_t uxReturned;\r
222 portBASE_TYPE xError = pdFALSE;\r
223 \r
224         /* Avoid compiler warnings. */\r
225         ( void ) pvParameters;\r
226 \r
227         for( ;; )\r
228         {\r
229                 /* This task is controller by the prvSetBitsTask().  Suspend until resumed\r
230                 by prvSetBitsTask(). */\r
231                 vTaskSuspend( NULL );\r
232 \r
233                 /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get\r
234                 set.  Clear the bit on exit. */\r
235                 uxReturned = xEventGroupWaitBits( xEventBits,   /* The event bits being queried. */\r
236                                                                          ebBIT_1,               /* The bit to wait for. */\r
237                                                                          pdTRUE,                /* Clear the bit on exit. */\r
238                                                                          pdTRUE,                /* Wait for all the bits (only one in this case anyway. */\r
239                                                                          portMAX_DELAY );\r
240 \r
241                 /* Should unblock after the 'set bit' task has set all the bits in the\r
242                 ebCOMBINED_BITS constant, therefore ebCOMBINED_BITS is what should have\r
243                 been returned. */\r
244                 if( uxReturned != ebCOMBINED_BITS )\r
245                 {\r
246                         xError = pdTRUE;\r
247                 }\r
248 \r
249                 /* Now call xEventGroupWaitBits() again, this time waiting for all the bits\r
250                 in ebCOMBINED_BITS to be set.  This call should block until the 'set\r
251                 bits' task sets ebBIT_1 - which was the bit cleared in the call to\r
252                 xEventGroupWaitBits() above. */\r
253                 uxReturned = xEventGroupWaitBits( xEventBits,\r
254                                                                          ebCOMBINED_BITS, /* The bits being waited on. */\r
255                                                                          pdFALSE,                 /* Don't clear the bits on exit. */\r
256                                                                          pdTRUE,                  /* All the bits must be set to unblock. */\r
257                                                                          portMAX_DELAY );\r
258 \r
259                 /* Were all the bits set? */\r
260                 if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS )\r
261                 {\r
262                         xError = pdTRUE;\r
263                 }\r
264 \r
265                 /* Suspend again to wait for the 'set bit' task. */\r
266                 vTaskSuspend( NULL );\r
267 \r
268                 /* Now call xEventGroupWaitBits() again, again waiting for all the bits in\r
269                 ebCOMBINED_BITS to be set, but this time clearing the bits when the task\r
270                 is unblocked. */\r
271                 uxReturned = xEventGroupWaitBits( xEventBits,\r
272                                                                          ebCOMBINED_BITS, /* The bits being waited on. */\r
273                                                                          pdTRUE,                  /* Clear the bits on exit. */\r
274                                                                          pdTRUE,                  /* All the bits must be set to unblock. */\r
275                                                                          portMAX_DELAY );\r
276 \r
277 \r
278                 if( uxReturned != ebALL_BITS )\r
279                 {\r
280                         xError = pdTRUE;\r
281                 }\r
282 \r
283                 vTaskSuspend( NULL );\r
284 \r
285                 /* Now to synchronise with when 'set bit' task has the lowest\r
286                 priority. */\r
287                 uxReturned = xEventGroupSync( xEventBits, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
288 \r
289                 /* A sync with a max delay should only exit when all the synchronisation\r
290                 bits are set... */\r
291                 if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
292                 {\r
293                         xError = pdTRUE;\r
294                 }\r
295 \r
296                 /* ...but now the synchronisation bits should be clear again. */\r
297                 if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
298                 {\r
299                         xError = pdTRUE;\r
300                 }\r
301 \r
302                 if( xError == pdFALSE )\r
303                 {\r
304                         /* This task is still cycling without finding an error. */\r
305                         ulWaitBitCycles++;\r
306                 }\r
307 \r
308                 vTaskSuspend( NULL );\r
309 \r
310                 /* This time sync when the 'set bit' task has the highest priority\r
311                 at the point where it sets its sync bit. */\r
312                 uxReturned = xEventGroupSync( xEventBits, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
313 \r
314                 /* A sync with a max delay should only exit when all the synchronisation\r
315                 bits are set... */\r
316                 if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
317                 {\r
318                         xError = pdTRUE;\r
319                 }\r
320 \r
321                 /* ...but now the sync bits should be clear again. */\r
322                 if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
323                 {\r
324                         xError = pdTRUE;\r
325                 }\r
326 \r
327                 /* Block on the event group again.  This time the event group is going\r
328                 to be deleted, so 0 should be returned. */\r
329                 uxReturned = xEventGroupWaitBits( xEventBits, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
330 \r
331                 if( uxReturned != 0 )\r
332                 {\r
333                         xError = pdTRUE;\r
334                 }\r
335 \r
336                 if( xError == pdFALSE )\r
337                 {\r
338                         /* This task is still cycling without finding an error. */\r
339                         ulWaitBitCycles++;\r
340                 }\r
341 \r
342                 configASSERT( xError == pdFALSE );\r
343         }\r
344 }\r
345 /*-----------------------------------------------------------*/\r
346 \r
347 static void prvSetBitsTask( void *pvParameters )\r
348 {\r
349 EventBits_t uxBits;\r
350 portBASE_TYPE xError;\r
351 \r
352 /* The handle to the other task is passed in as the task parameter. */\r
353 xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;\r
354 \r
355         /* Avoid compiler warnings. */\r
356         ( void ) pvParameters;\r
357 \r
358         /* Create the event group ready for the initial tests. */\r
359         xEventBits = xEventGroupCreate();\r
360         configASSERT( xEventBits );\r
361 \r
362         /* Perform the tests that block two tasks on different combinations of bits, \r
363         then set each bit in turn and check the correct tasks unblock at the correct \r
364         times. */\r
365         xError = prvTestSelectiveBits();\r
366 \r
367         for( ;; )\r
368         {\r
369                 /* Recreate the event group ready for the next cycle. */\r
370                 xEventBits = xEventGroupCreate();\r
371                 configASSERT( xEventBits );\r
372 \r
373                 /* Resume the other task.  It will block, pending a single bit from\r
374                 within ebCOMBINED_BITS. */\r
375                 vTaskResume( xWaitBitsTaskHandle );\r
376 \r
377                 /* Ensure the other task is blocked on the task. */\r
378                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
379                 {\r
380                         xError = pdTRUE;\r
381                 }\r
382 \r
383                 /* Set all the bits in ebCOMBINED_BITS - the 'wait bits' task is only\r
384                 blocked waiting for one of them. */\r
385                 xEventGroupSetBits( xEventBits, ebCOMBINED_BITS );\r
386 \r
387                 /* The 'wait bits' task should now have executed, clearing ebBIT_1 (the\r
388                 bit it was blocked on), then re-entered the Blocked state to wait for\r
389                 all the other bits in ebCOMBINED_BITS to be set again.  First check\r
390                 ebBIT_1 is clear. */\r
391                 uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
392 \r
393                 if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )\r
394                 {\r
395                         xError = pdTRUE;\r
396                 }\r
397 \r
398                 /* Ensure the other task is still in the blocked state. */\r
399                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
400                 {\r
401                         xError = pdTRUE;\r
402                 }\r
403 \r
404                 /* Set all the bits other than ebBIT_1 - which is the bit that must be\r
405                 set before the other task unblocks. */\r
406                 xEventGroupSetBits( xEventBits, ebALL_BITS & ~ebBIT_1 );\r
407 \r
408                 /* Ensure all the expected bits are still set. */\r
409                 uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
410 \r
411                 if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) )\r
412                 {\r
413                         xError = pdTRUE;\r
414                 }\r
415 \r
416                 /* Ensure the other task is still in the blocked state. */\r
417                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
418                 {\r
419                         xError = pdTRUE;\r
420                 }\r
421 \r
422                 /* Now also set ebBIT_1, which should unblock the other task, which will\r
423                 then suspend itself. */\r
424                 xEventGroupSetBits( xEventBits, ebBIT_1 );\r
425 \r
426                 /* Ensure the other task is suspended. */\r
427                 if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
428                 {\r
429                         xError = pdTRUE;\r
430                 }\r
431 \r
432                 /* The other task should not have cleared the bits - so all the bits\r
433                 should still be set. */\r
434                 if( xEventGroupSetBits( xEventBits, 0x00 ) != ebALL_BITS )\r
435                 {\r
436                         xError = pdTRUE;\r
437                 }\r
438 \r
439                 /* Clear ebBIT_1 again. */\r
440                 if( xEventGroupClearBits( xEventBits, ebBIT_1 ) != ebALL_BITS )\r
441                 {\r
442                         xError = pdTRUE;\r
443                 }\r
444 \r
445                 /* Resume the other task - which will wait on all the ebCOMBINED_BITS\r
446                 again - this time clearing the bits when it is unblocked. */\r
447                 vTaskResume( xWaitBitsTaskHandle );\r
448 \r
449                 /* Ensure the other task is blocked once again. */\r
450                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
451                 {\r
452                         xError = pdTRUE;\r
453                 }\r
454 \r
455                 /* Set the bit the other task is waiting for. */\r
456                 xEventGroupSetBits( xEventBits, ebBIT_1 );\r
457 \r
458                 /* Ensure the other task is suspended once again. */\r
459                 if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
460                 {\r
461                         xError = pdTRUE;\r
462                 }\r
463 \r
464                 /* The other task should have cleared the bits in ebCOMBINED_BITS.\r
465                 Clear the remaining bits. */\r
466                 uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
467 \r
468                 if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
469                 {\r
470                         xError = pdTRUE;\r
471                 }\r
472 \r
473                 /* Clear all bits ready for the sync with the other three tasks.  The\r
474                 value returned is the value prior to the bits being cleared. */\r
475                 if( xEventGroupClearBits( xEventBits, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
476                 {\r
477                         xError = pdTRUE;\r
478                 }\r
479 \r
480                 /* The bits should be clear now. */\r
481                 if( xEventGroupGetBits( xEventBits ) != 0x00 )\r
482                 {\r
483                         xError = pdTRUE;\r
484                 }\r
485 \r
486                 /* Check the other three tasks are suspended. */\r
487                 if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
488                 {\r
489                         xError = pdTRUE;\r
490                 }\r
491 \r
492                 if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
493                 {\r
494                         xError = pdTRUE;\r
495                 }\r
496 \r
497                 if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
498                 {\r
499                         xError = pdTRUE;\r
500                 }\r
501 \r
502                 /* Unsuspend the other tasks then check they have executed up to the\r
503                 synchronisation point. */\r
504                 vTaskResume( xWaitBitsTaskHandle );\r
505                 vTaskResume( xSyncTask1 );\r
506                 vTaskResume( xSyncTask2 );\r
507 \r
508                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
509                 {\r
510                         xError = pdTRUE;\r
511                 }\r
512 \r
513                 if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
514                 {\r
515                         xError = pdTRUE;\r
516                 }\r
517 \r
518                 if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
519                 {\r
520                         xError = pdTRUE;\r
521                 }\r
522 \r
523                 /* Set this task's sync bit. */\r
524                 uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
525 \r
526                 /* A sync with a max delay should only exit when all the synchronise\r
527                 bits are set... */\r
528                 if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
529                 {\r
530                         xError = pdTRUE;\r
531                 }\r
532 \r
533                 /* ...but now the sync bits should be clear again. */\r
534                 if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
535                 {\r
536                         xError = pdTRUE;\r
537                 }\r
538 \r
539 \r
540                 /* The other tasks should now all be suspended again, ready for the next\r
541                 synchronisation. */\r
542                 if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
543                 {\r
544                         xError = pdTRUE;\r
545                 }\r
546 \r
547                 if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
548                 {\r
549                         xError = pdTRUE;\r
550                 }\r
551 \r
552                 if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
553                 {\r
554                         xError = pdTRUE;\r
555                 }\r
556 \r
557 \r
558                 /* Sync again - but this time set the last necessary bit as the\r
559                 highest priority task, rather than the lowest priority task.  Unsuspend\r
560                 the other tasks then check they have executed up to the synchronisation\r
561                 point. */\r
562                 vTaskResume( xWaitBitsTaskHandle );\r
563                 vTaskResume( xSyncTask1 );\r
564                 vTaskResume( xSyncTask2 );\r
565 \r
566                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
567                 {\r
568                         xError = pdTRUE;\r
569                 }\r
570 \r
571                 if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
572                 {\r
573                         xError = pdTRUE;\r
574                 }\r
575 \r
576                 if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
577                 {\r
578                         xError = pdTRUE;\r
579                 }\r
580 \r
581                 /* Raise the priority of this task above that of the other tasks. */\r
582                 vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 );\r
583 \r
584                 /* Set this task's sync bit. */\r
585                 uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
586 \r
587                 /* A sync with a max delay should only exit when all the synchronisation\r
588                 bits are set... */\r
589                 if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
590                 {\r
591                         xError = pdTRUE;\r
592                 }\r
593 \r
594                 /* ...but now the sync bits should be clear again. */\r
595                 if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
596                 {\r
597                         xError = pdTRUE;\r
598                 }\r
599 \r
600 \r
601                 /* The other tasks should now all be in the ready state again, but not\r
602                 executed yet as this task still has a higher relative priority. */\r
603                 if( eTaskGetState( xWaitBitsTaskHandle ) != eReady )\r
604                 {\r
605                         xError = pdTRUE;\r
606                 }\r
607 \r
608                 if( eTaskGetState( xSyncTask1 ) != eReady )\r
609                 {\r
610                         xError = pdTRUE;\r
611                 }\r
612 \r
613                 if( eTaskGetState( xSyncTask2 ) != eReady )\r
614                 {\r
615                         xError = pdTRUE;\r
616                 }\r
617 \r
618 \r
619                 /* Reset the priority of this task back to its original value. */\r
620                 vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );\r
621 \r
622                 /* Now all the other tasks should have reblocked on the event bits\r
623                 to test the behaviour when the event bits are deleted. */\r
624                 if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
625                 {\r
626                         xError = pdTRUE;\r
627                 }\r
628 \r
629                 if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
630                 {\r
631                         xError = pdTRUE;\r
632                 }\r
633 \r
634                 if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
635                 {\r
636                         xError = pdTRUE;\r
637                 }\r
638 \r
639                 /* Delete the event group. */\r
640                 vEventGroupDelete( xEventBits );\r
641 \r
642                 /* Now all the other tasks should have completed and suspended\r
643                 themselves ready for the next go around the loop. */\r
644                 if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
645                 {\r
646                         xError = pdTRUE;\r
647                 }\r
648 \r
649                 if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
650                 {\r
651                         xError = pdTRUE;\r
652                 }\r
653 \r
654                 if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
655                 {\r
656                         xError = pdTRUE;\r
657                 }\r
658 \r
659 \r
660                 if( xError == pdFALSE )\r
661                 {\r
662                         ulSetBitCycles++;\r
663                 }\r
664 \r
665                 configASSERT( xError == pdFALSE );\r
666         }\r
667 }\r
668 /*-----------------------------------------------------------*/\r
669 \r
670 static void prvPreSyncSelectiveWakeTest( void )\r
671 {\r
672 EventBits_t uxPendBits, uxReturned;\r
673 \r
674         if( xTaskGetCurrentTaskHandle() == xSyncTask1 )\r
675         {\r
676                 uxPendBits = ebSELECTIVE_BITS_1;\r
677         }\r
678         else\r
679         {\r
680                 uxPendBits = ebSELECTIVE_BITS_2;\r
681         }\r
682 \r
683         for( ;; )\r
684         {\r
685                 vTaskSuspend( NULL );\r
686                 uxReturned = xEventGroupWaitBits( xEventBits, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );\r
687 \r
688                 if( uxReturned == ( EventBits_t ) 0 )\r
689                 {\r
690                         break;\r
691                 }\r
692         }\r
693 }\r
694 /*-----------------------------------------------------------*/\r
695 \r
696 static portBASE_TYPE prvTestSelectiveBits( void )\r
697 {\r
698 portBASE_TYPE xError = pdFALSE;\r
699 EventBits_t uxBit;\r
700 \r
701         /* Both tasks should start in the suspended state. */\r
702         if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
703         {\r
704                 xError = pdTRUE;\r
705         }\r
706 \r
707         if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
708         {\r
709                 xError = pdTRUE;\r
710         }\r
711 \r
712         /* Test each bit in the byte individually. */\r
713         for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 )\r
714         {\r
715                 /* Resume both tasks. */\r
716                 vTaskResume( xSyncTask1 );\r
717                 vTaskResume( xSyncTask2 );\r
718 \r
719                 /* Now both tasks should be blocked on the event group. */\r
720                 if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
721                 {\r
722                         xError = pdTRUE;\r
723                 }\r
724 \r
725                 if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
726                 {\r
727                         xError = pdTRUE;\r
728                 }\r
729 \r
730                 /* Set one bit. */\r
731                 xEventGroupSetBits( xEventBits, uxBit );\r
732 \r
733                 /* Is the bit set in the first set of selective bits?  If so the first\r
734                 sync task should have unblocked and returned to the suspended state. */\r
735                 if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )\r
736                 {\r
737                         /* Task should not have unblocked. */\r
738                         if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
739                         {\r
740                                 xError = pdTRUE;\r
741                         }\r
742                 }\r
743                 else\r
744                 {\r
745                         /* Task should have unblocked and returned to the suspended state. */\r
746                         if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
747                         {\r
748                                 xError = pdTRUE;\r
749                         }\r
750                 }\r
751 \r
752                 /* Same checks for the second sync task. */\r
753                 if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 )\r
754                 {\r
755                         /* Task should not have unblocked. */\r
756                         if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
757                         {\r
758                                 xError = pdTRUE;\r
759                         }\r
760                 }\r
761                 else\r
762                 {\r
763                         /* Task should have unblocked and returned to the suspended state. */\r
764                         if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
765                         {\r
766                                 xError = pdTRUE;\r
767                         }\r
768                 }\r
769         }\r
770 \r
771         /* Ensure both tasks are blocked on the event group again, then delete the\r
772         event group so the other tasks leave this portion of the test. */\r
773         vTaskResume( xSyncTask1 );\r
774         vTaskResume( xSyncTask2 );\r
775 \r
776         vEventGroupDelete( xEventBits );\r
777 \r
778         return xError;\r
779 }\r
780 /*-----------------------------------------------------------*/\r
781 \r
782 /* This is called to check that all the created tasks are still running. */\r
783 portBASE_TYPE xAreEventGroupTasksStillRunning( void )\r
784 {\r
785 static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;\r
786 portBASE_TYPE xStatus = pdPASS;\r
787 \r
788         /* Check the tasks are still cycling without finding any errors. */\r
789         if( ulPreviousSetBitCycles == ulSetBitCycles )\r
790         {\r
791                 xStatus = pdFAIL;\r
792         }\r
793         ulPreviousSetBitCycles = ulSetBitCycles;\r
794 \r
795         if( ulPreviousWaitBitCycles == ulWaitBitCycles )\r
796         {\r
797                 xStatus = pdFAIL;\r
798         }\r
799         ulPreviousWaitBitCycles = ulWaitBitCycles;\r
800 \r
801         return xStatus;\r
802 }\r
803 \r
804 \r
805 \r