]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
616a4c48f903a5307d16358049b762821f53b09a
[freertos] / FreeRTOS / Demo / Common / Minimal / EventGroupsDemo.c
1 /*\r
2     FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 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\r
71 * event groups API.\r
72 *\r
73 * NOTE:  The tests implemented in this file are informal 'sanity' tests \r
74 * only and are not part of the module tests that make use of the \r
75 * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.\r
76 */\r
77 \r
78 \r
79 /* Scheduler include files. */\r
80 #include "FreeRTOS.h"\r
81 #include "task.h"\r
82 #include "event_groups.h"\r
83 \r
84 /* Demo app includes. */\r
85 #include "EventGroupsDemo.h"\r
86 \r
87 /* Priorities used by the tasks. */\r
88 #define ebSET_BIT_TASK_PRIORITY         ( tskIDLE_PRIORITY )\r
89 #define ebWAIT_BIT_TASK_PRIORITY        ( tskIDLE_PRIORITY + 1 )\r
90 \r
91 /* Generic bit definitions. */\r
92 #define ebBIT_0         ( 0x01UL )\r
93 #define ebBIT_1         ( 0x02UL )\r
94 #define ebBIT_2         ( 0x04UL )\r
95 #define ebBIT_3         ( 0x08UL )\r
96 #define ebBIT_4         ( 0x10UL )\r
97 #define ebBIT_5         ( 0x20UL )\r
98 #define ebBIT_6         ( 0x40UL )\r
99 #define ebBIT_7         ( 0x80UL )\r
100 \r
101 /* Combinations of bits used in the demo. */\r
102 #define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 )\r
103 #define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )\r
104 \r
105 /* Associate a bit to each task.  These bits are used to identify all the tasks\r
106 that synchronise with the xEventGroupSync() function. */\r
107 #define ebSET_BIT_TASK_SYNC_BIT                 ebBIT_0\r
108 #define ebWAIT_BIT_TASK_SYNC_BIT                ebBIT_1\r
109 #define ebRENDESVOUS_TASK_1_SYNC_BIT    ebBIT_2\r
110 #define ebRENDESVOUS_TASK_2_SYNC_BIT    ebBIT_3\r
111 #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
112 \r
113 /* A block time of zero simply means "don't block". */\r
114 #define ebDONT_BLOCK    ( 0 )\r
115 \r
116 /* A 5ms delay. */\r
117 #define ebSHORT_DELAY   ( 5 / portTICK_PERIOD_MS )\r
118 \r
119 /* Used in the selective bits test which checks no, one or both tasks blocked on\r
120 event bits in a group are unblocked as appropriate as different bits get set. */\r
121 #define ebSELECTIVE_BITS_1              0x03\r
122 #define ebSELECTIVE_BITS_2              0x05\r
123 \r
124 /*-----------------------------------------------------------*/\r
125 \r
126 /*\r
127  * NOTE:  The tests implemented in this function are informal 'sanity' tests \r
128  * only and are not part of the module tests that make use of the \r
129  * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.\r
130  *\r
131  * The master test task.  This task:\r
132  *\r
133  * 1) Calls prvSelectiveBitsTestMasterFunction() to test the behaviour when two \r
134  *    tasks are blocked on different bits in an event group.  The counterpart of \r
135  *    this test is implemented by the prvSelectiveBitsTestSlaveFunction() \r
136  *    function (which is called by the two tasks that block on the event group).\r
137  *\r
138  * 2) Calls prvBitCombinationTestMasterFunction() to test the behaviour when\r
139  *    just one task is blocked on various combinations of bits within an event \r
140  *    group.  The counterpart of this test is implemented within the 'test \r
141  *    slave' task.\r
142  *\r
143  * 3) Calls prvPerformTaskSyncTests() to test task synchronisation behaviour.\r
144  */\r
145 static void prvTestMasterTask( void *pvParameters );\r
146 \r
147 /*\r
148  * A helper task that enables the 'test master' task to perform several \r
149  * behavioural tests.  See the comments above the prvTestMasterTask() prototype\r
150  * above.\r
151  */\r
152 static void prvTestSlaveTask( void *pvParameters );\r
153 \r
154 /*\r
155  * The part of the test that is performed between the 'test master' task and the\r
156  * 'test slave' task to test the behaviour when the slave blocks on various\r
157  * event bit combinations.\r
158  */\r
159 static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );\r
160 \r
161 /*\r
162  * The part of the test that uses all the tasks to test the task synchronisation\r
163  * behaviour.\r
164  */\r
165 static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );\r
166 \r
167 /*\r
168  * Two instances of prvSyncTask() are created.  They start by calling \r
169  * prvSelectiveBitsTestSlaveFunction() to act as slaves when the test master is\r
170  * executing the prvSelectiveBitsTestMasterFunction() function.  They then loop\r
171  * to test the task synchronisation (rendezvous) behaviour.\r
172  */\r
173 static void prvSyncTask( void *pvParameters );\r
174 \r
175 /*\r
176  * Functions used in a test that blocks two tasks on various different bits\r
177  * within an event group - then sets each bit in turn and checks that the \r
178  * correct tasks unblock at the correct times.\r
179  */\r
180 static BaseType_t prvSelectiveBitsTestMasterFunction( void );\r
181 static void prvSelectiveBitsTestSlaveFunction( void );\r
182 \r
183 /*-----------------------------------------------------------*/\r
184 \r
185 /* Variables that are incremented by the tasks on each cycle provided no errors\r
186 have been found.  Used to detect an error or stall in the test cycling. */\r
187 static volatile unsigned long ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0;\r
188 \r
189 /* The event group used by all the task based tests. */\r
190 static EventGroupHandle_t xEventGroup = NULL;\r
191 \r
192 /* The event group used by the interrupt based tests. */\r
193 static EventGroupHandle_t xISREventGroup = NULL;\r
194 \r
195 /* Handles to the tasks that only take part in the synchronisation calls. */\r
196 static TaskHandle_t xSyncTask1 = NULL, xSyncTask2 = NULL;\r
197 \r
198 /*-----------------------------------------------------------*/\r
199 \r
200 void vStartEventGroupTasks( void )\r
201 {\r
202 TaskHandle_t xTestSlaveTaskHandle;\r
203 \r
204         /*\r
205          * This file contains fairly comprehensive checks on the behaviour of event\r
206          * groups.  It is not intended to be a user friendly demonstration of the\r
207          * event groups API.\r
208          *\r
209          * NOTE:  The tests implemented in this file are informal 'sanity' tests \r
210          * only and are not part of the module tests that make use of the \r
211          * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.\r
212          *\r
213          * Create the test tasks as described at the top of this file.\r
214          */\r
215         xTaskCreate( prvTestSlaveTask, "WaitO", configMINIMAL_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xTestSlaveTaskHandle );\r
216         xTaskCreate( prvTestMasterTask, "SetB", configMINIMAL_STACK_SIZE, ( void * ) xTestSlaveTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL );\r
217         xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );\r
218         xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 );\r
219 \r
220         /* If the last task was created then the others will have been too. */\r
221         configASSERT( xSyncTask2 );\r
222 \r
223         /* Create the event group used by the ISR tests.  The event group used by\r
224         the tasks is created by the tasks themselves. */\r
225         xISREventGroup = xEventGroupCreate();\r
226         configASSERT( xISREventGroup );\r
227 }\r
228 /*-----------------------------------------------------------*/\r
229 \r
230 static void prvTestMasterTask( void *pvParameters )\r
231 {\r
232 BaseType_t xError;\r
233 \r
234 /* The handle to the slave task is passed in as the task parameter. */\r
235 TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters;\r
236 \r
237         /* Avoid compiler warnings. */\r
238         ( void ) pvParameters;\r
239 \r
240         /* Create the event group used by the tasks ready for the initial tests. */\r
241         xEventGroup = xEventGroupCreate();\r
242         configASSERT( xEventGroup );\r
243 \r
244         /* Perform the tests that block two tasks on different combinations of bits, \r
245         then set each bit in turn and check the correct tasks unblock at the correct \r
246         times. */\r
247         xError = prvSelectiveBitsTestMasterFunction();\r
248 \r
249         for( ;; )\r
250         {\r
251                 /* Recreate the event group ready for the next cycle. */\r
252                 xEventGroup = xEventGroupCreate();\r
253                 configASSERT( xEventGroup );\r
254 \r
255                 /* Perform the tests that check the behaviour when a single task is\r
256                 blocked on various combinations of event bits. */\r
257                 xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle );\r
258 \r
259                 /* Perform the task synchronisation tests. */\r
260                 xError = prvPerformTaskSyncTests( xError, xTestSlaveTaskHandle );\r
261 \r
262                 /* Delete the event group. */\r
263                 vEventGroupDelete( xEventGroup );\r
264 \r
265                 /* Now all the other tasks should have completed and suspended\r
266                 themselves ready for the next go around the loop. */\r
267                 if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
268                 {\r
269                         xError = pdTRUE;\r
270                 }\r
271 \r
272                 if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
273                 {\r
274                         xError = pdTRUE;\r
275                 }\r
276 \r
277                 if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
278                 {\r
279                         xError = pdTRUE;\r
280                 }\r
281 \r
282                 /* Only increment the cycle variable if no errors have been detected. */\r
283                 if( xError == pdFALSE )\r
284                 {\r
285                         ulTestMasterCycles++;\r
286                 }\r
287 \r
288                 configASSERT( xError == pdFALSE );\r
289         }\r
290 }\r
291 /*-----------------------------------------------------------*/\r
292 \r
293 static void prvSyncTask( void *pvParameters )\r
294 {\r
295 EventBits_t uxSynchronisationBit, uxReturned;\r
296 \r
297         /* A few tests that check the behaviour when two tasks are blocked on \r
298         various different bits within an event group are performed before this task\r
299         enters its infinite loop to carry out its main demo function. */\r
300         prvSelectiveBitsTestSlaveFunction();\r
301 \r
302         /* The bit to use to indicate this task is at the synchronisation point is\r
303         passed in as the task parameter. */\r
304         uxSynchronisationBit = ( EventBits_t ) pvParameters;\r
305 \r
306         for( ;; )\r
307         {\r
308                 /* Now this task takes part in a task synchronisation - sometimes known \r
309                 as a 'rendezvous'.  Its execution pattern is controlled by the 'test \r
310                 master' task, which is responsible for taking this task out of the \r
311                 Suspended state when it is time to test the synchronisation behaviour.  \r
312                 See: http://www.freertos.org/xEventGroupSync.html. */\r
313                 vTaskSuspend( NULL );\r
314 \r
315                 /* Set the bit that indicates this task is at the synchronisation\r
316                 point.  The first time this is done the 'test master' task has a lower\r
317                 priority than this task so this task will get to the sync point before\r
318                 the set bits task. */\r
319                 uxReturned = xEventGroupSync( xEventGroup,      /* The event group used for the synchronisation. */\r
320                                                                         uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */\r
321                                                                         ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */\r
322                                                                         portMAX_DELAY );/* The maximum time to wait for the sync condition to be met before giving up. */\r
323 \r
324                 /* A max delay was used, so this task should only exit the above\r
325                 function call when the sync condition is met.  Check this is the \r
326                 case. */\r
327                 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
328 \r
329                 /* Remove compiler warning if configASSERT() is not defined. */\r
330                 ( void ) uxReturned;\r
331 \r
332                 /* Wait until the 'test master' task unsuspends this task again. */\r
333                 vTaskSuspend( NULL );\r
334 \r
335                 /* Set the bit that indicates this task is at the synchronisation\r
336                 point again.  This time the 'test master' task has a higher priority \r
337                 than this task so will get to the sync point before this task. */\r
338                 uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );\r
339 \r
340                 /* Again a max delay was used, so this task should only exit the above\r
341                 function call when the sync condition is met.  Check this is the \r
342                 case. */\r
343                 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
344 \r
345                 /* Block on the event group again.  This time the event group is going\r
346                 to be deleted while this task is blocked on it so it is expected that 0 \r
347                 be returned. */\r
348                 uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
349                 configASSERT( uxReturned == 0 );\r
350         }\r
351 }\r
352 /*-----------------------------------------------------------*/\r
353 \r
354 static void prvTestSlaveTask( void *pvParameters )\r
355 {\r
356 EventBits_t uxReturned;\r
357 BaseType_t xError = pdFALSE;\r
358 \r
359         /* Avoid compiler warnings. */\r
360         ( void ) pvParameters;\r
361 \r
362         for( ;; )\r
363         {\r
364                 /**********************************************************************\r
365                 * Part 1:  This section is the counterpart to the \r
366                 * prvBitCombinationTestMasterFunction() function which is called by the\r
367                 * test master task.\r
368                 ***********************************************************************\r
369 \r
370                 This task is controller by the 'test master' task (which is\r
371                 implemented by prvTestMasterTask()).  Suspend until resumed by the \r
372                 'test master' task. */\r
373                 vTaskSuspend( NULL );\r
374 \r
375                 /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get\r
376                 set.  Clear the bit on exit. */\r
377                 uxReturned = xEventGroupWaitBits( xEventGroup,  /* The event group that contains the event bits being queried. */\r
378                                                                                  ebBIT_1,               /* The bit to wait for. */\r
379                                                                                  pdTRUE,                /* Clear the bit on exit. */\r
380                                                                                  pdTRUE,                /* Wait for all the bits (only one in this case anyway). */\r
381                                                                                  portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */\r
382 \r
383                 /* The 'test master' task set all the bits defined by ebCOMBINED_BITS, \r
384                 only one of which was being waited for by this task.  The return value\r
385                 shows the state of the event bits when the task was unblocked, however\r
386                 because the task was waiting for ebBIT_1 and 'clear on exit' was set to \r
387                 the current state of the event bits will have ebBIT_1 clear.  */\r
388                 if( uxReturned != ebCOMBINED_BITS )\r
389                 {\r
390                         xError = pdTRUE;\r
391                 }\r
392 \r
393                 /* Now call xEventGroupWaitBits() again, this time waiting for all the \r
394                 bits in ebCOMBINED_BITS to be set.  This call should block until the \r
395                 'test master' task sets ebBIT_1 - which was the bit cleared in the call \r
396                 to xEventGroupWaitBits() above. */\r
397                 uxReturned = xEventGroupWaitBits( xEventGroup,\r
398                                                                                  ebCOMBINED_BITS, /* The bits being waited on. */\r
399                                                                                  pdFALSE,                 /* Don't clear the bits on exit. */\r
400                                                                                  pdTRUE,                  /* All the bits must be set to unblock. */\r
401                                                                                  portMAX_DELAY );\r
402 \r
403                 /* Were all the bits set? */\r
404                 if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS )\r
405                 {\r
406                         xError = pdTRUE;\r
407                 }\r
408 \r
409                 /* Suspend again to wait for the 'test master' task. */\r
410                 vTaskSuspend( NULL );\r
411 \r
412                 /* Now call xEventGroupWaitBits() again, again waiting for all the bits \r
413                 in ebCOMBINED_BITS to be set, but this time clearing the bits when the \r
414                 task is unblocked. */\r
415                 uxReturned = xEventGroupWaitBits( xEventGroup,\r
416                                                                          ebCOMBINED_BITS, /* The bits being waited on. */\r
417                                                                          pdTRUE,                  /* Clear the bits on exit. */\r
418                                                                          pdTRUE,                  /* All the bits must be set to unblock. */\r
419                                                                          portMAX_DELAY );\r
420 \r
421                 /* The 'test master' task set all the bits in the event group, so that \r
422                 is the value that should have been returned.  The bits defined by\r
423                 ebCOMBINED_BITS will have been clear again in the current value though\r
424                 as 'clear on exit' was set to pdTRUE. */\r
425                 if( uxReturned != ebALL_BITS )\r
426                 {\r
427                         xError = pdTRUE;\r
428                 }\r
429 \r
430 \r
431 \r
432 \r
433 \r
434                 /**********************************************************************\r
435                 * Part 2:  This section is the counterpart to the \r
436                 * prvPerformTaskSyncTests() function which is called by the\r
437                 * test master task.\r
438                 ***********************************************************************\r
439 \r
440 \r
441                 Once again wait for the 'test master' task to unsuspend this task\r
442                 when it is time for the next test. */\r
443                 vTaskSuspend( NULL );\r
444 \r
445                 /* Now peform a synchronisation with all the other tasks.  At this point\r
446                 the 'test master' task has the lowest priority so will get to the sync \r
447                 point after all the other synchronising tasks. */\r
448                 uxReturned = xEventGroupSync( xEventGroup,              /* The event group used for the sync. */\r
449                                                                         ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */\r
450                                                                         ebALL_SYNC_BITS,        /* The bits to wait for.  These bits are set by the other tasks taking part in the sync. */\r
451                                                                         portMAX_DELAY );        /* The maximum time to wait for the sync condition to be met before giving up. */\r
452 \r
453                 /* A sync with a max delay should only exit when all the synchronisation\r
454                 bits are set... */\r
455                 if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
456                 {\r
457                         xError = pdTRUE;\r
458                 }\r
459 \r
460                 /* ...but now the synchronisation bits should be clear again.  Read back\r
461                 the current value of the bits within the event group to check that is\r
462                 the case.  Setting the bits to zero will return the bits previous value\r
463                 then leave all the bits clear. */\r
464                 if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )\r
465                 {\r
466                         xError = pdTRUE;\r
467                 }\r
468 \r
469                 /* Check the bits are indeed 0 now by simply reading then. */\r
470                 if( xEventGroupGetBits( xEventGroup ) != 0 )\r
471                 {\r
472                         xError = pdTRUE;\r
473                 }\r
474 \r
475                 if( xError == pdFALSE )\r
476                 {\r
477                         /* This task is still cycling without finding an error. */\r
478                         ulTestSlaveCycles++;\r
479                 }\r
480 \r
481                 vTaskSuspend( NULL );\r
482 \r
483                 /* This time sync when the 'test master' task has the highest priority\r
484                 at the point where it sets its sync bit - so this time the 'test master' \r
485                 task will get to the sync point before this task. */\r
486                 uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
487 \r
488                 /* A sync with a max delay should only exit when all the synchronisation\r
489                 bits are set... */\r
490                 if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
491                 {\r
492                         xError = pdTRUE;\r
493                 }\r
494 \r
495                 /* ...but now the sync bits should be clear again. */\r
496                 if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )\r
497                 {\r
498                         xError = pdTRUE;\r
499                 }\r
500 \r
501                 /* Block on the event group again.  This time the event group is going\r
502                 to be deleted while this task is blocked on it, so it is expected that 0 \r
503                 will be returned. */\r
504                 uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
505 \r
506                 if( uxReturned != 0 )\r
507                 {\r
508                         xError = pdTRUE;\r
509                 }\r
510 \r
511                 if( xError == pdFALSE )\r
512                 {\r
513                         /* This task is still cycling without finding an error. */\r
514                         ulTestSlaveCycles++;\r
515                 }\r
516 \r
517                 configASSERT( xError == pdFALSE );\r
518         }\r
519 }\r
520 /*-----------------------------------------------------------*/\r
521 \r
522 static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )\r
523 {\r
524 EventBits_t uxBits;\r
525 \r
526         /* The three tasks that take part in the synchronisation (rendezvous) are\r
527         expected to be in the suspended state at the start of the test. */\r
528         if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
529         {\r
530                 xError = pdTRUE;\r
531         }\r
532 \r
533         if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
534         {\r
535                 xError = pdTRUE;\r
536         }\r
537 \r
538         if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
539         {\r
540                 xError = pdTRUE;\r
541         }\r
542 \r
543         /* Unsuspend the other tasks then check they have executed up to the\r
544         synchronisation point. */\r
545         vTaskResume( xTestSlaveTaskHandle );\r
546         vTaskResume( xSyncTask1 );\r
547         vTaskResume( xSyncTask2 );\r
548 \r
549         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
550         {\r
551                 xError = pdTRUE;\r
552         }\r
553 \r
554         if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
555         {\r
556                 xError = pdTRUE;\r
557         }\r
558 \r
559         if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
560         {\r
561                 xError = pdTRUE;\r
562         }\r
563 \r
564         /* Set this task's sync bit. */\r
565         uxBits = xEventGroupSync( xEventGroup,                  /* The event group used for the synchronisation. */\r
566                                                         ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */\r
567                                                         ebALL_SYNC_BITS,                /* The bits to wait for - these bits are set by the other tasks that take part in the sync. */\r
568                                                         portMAX_DELAY );                /* The maximum time to wait for the sync condition to be met. */\r
569 \r
570         /* A sync with a max delay should only exit when all the synchronise\r
571         bits are set...check that is the case. */\r
572         if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
573         {\r
574                 xError = pdTRUE;\r
575         }\r
576 \r
577         /* ...but now the sync bits should be clear again. */\r
578         if( xEventGroupGetBits( xEventGroup ) != 0 )\r
579         {\r
580                 xError = pdTRUE;\r
581         }\r
582 \r
583 \r
584         /* The other tasks should now all be suspended again, ready for the next\r
585         synchronisation. */\r
586         if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
587         {\r
588                 xError = pdTRUE;\r
589         }\r
590 \r
591         if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
592         {\r
593                 xError = pdTRUE;\r
594         }\r
595 \r
596         if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
597         {\r
598                 xError = pdTRUE;\r
599         }\r
600 \r
601 \r
602         /* Sync again - but this time set the last necessary bit as the\r
603         highest priority task, rather than the lowest priority task.  Unsuspend\r
604         the other tasks then check they have executed up to the synchronisation\r
605         point. */\r
606         vTaskResume( xTestSlaveTaskHandle );\r
607         vTaskResume( xSyncTask1 );\r
608         vTaskResume( xSyncTask2 );\r
609 \r
610         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
611         {\r
612                 xError = pdTRUE;\r
613         }\r
614 \r
615         if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
616         {\r
617                 xError = pdTRUE;\r
618         }\r
619 \r
620         if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
621         {\r
622                 xError = pdTRUE;\r
623         }\r
624 \r
625         /* Raise the priority of this task above that of the other tasks. */\r
626         vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 );\r
627 \r
628         /* Set this task's sync bit. */\r
629         uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
630 \r
631         /* A sync with a max delay should only exit when all the synchronisation\r
632         bits are set... */\r
633         if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
634         {\r
635                 xError = pdTRUE;\r
636         }\r
637 \r
638         /* ...but now the sync bits should be clear again. */\r
639         if( xEventGroupGetBits( xEventGroup ) != 0 )\r
640         {\r
641                 xError = pdTRUE;\r
642         }\r
643 \r
644 \r
645         /* The other tasks should now all be in the ready state again, but not\r
646         executed yet as this task still has a higher relative priority. */\r
647         if( eTaskGetState( xTestSlaveTaskHandle ) != eReady )\r
648         {\r
649                 xError = pdTRUE;\r
650         }\r
651 \r
652         if( eTaskGetState( xSyncTask1 ) != eReady )\r
653         {\r
654                 xError = pdTRUE;\r
655         }\r
656 \r
657         if( eTaskGetState( xSyncTask2 ) != eReady )\r
658         {\r
659                 xError = pdTRUE;\r
660         }\r
661 \r
662 \r
663         /* Reset the priority of this task back to its original value. */\r
664         vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );\r
665 \r
666         /* Now all the other tasks should have reblocked on the event bits\r
667         to test the behaviour when the event bits are deleted. */\r
668         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
669         {\r
670                 xError = pdTRUE;\r
671         }\r
672 \r
673         if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
674         {\r
675                 xError = pdTRUE;\r
676         }\r
677 \r
678         if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
679         {\r
680                 xError = pdTRUE;\r
681         }\r
682 \r
683         return xError;\r
684 }\r
685 /*-----------------------------------------------------------*/\r
686 \r
687 static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )\r
688 {\r
689 EventBits_t uxBits;\r
690 \r
691         /* Resume the other task.  It will block, pending a single bit from\r
692         within ebCOMBINED_BITS. */\r
693         vTaskResume( xTestSlaveTaskHandle );\r
694 \r
695         /* Ensure the other task is blocked on the task. */\r
696         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
697         {\r
698                 xError = pdTRUE;\r
699         }\r
700 \r
701         /* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only\r
702         blocked waiting for one of them. */\r
703         xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS );\r
704 \r
705         /* The 'test slave' task should now have executed, clearing ebBIT_1 (the\r
706         bit it was blocked on), then re-entered the Blocked state to wait for\r
707         all the other bits in ebCOMBINED_BITS to be set again.  First check\r
708         ebBIT_1 is clear. */\r
709         uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
710 \r
711         if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )\r
712         {\r
713                 xError = pdTRUE;\r
714         }\r
715 \r
716         /* Ensure the other task is still in the blocked state. */\r
717         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
718         {\r
719                 xError = pdTRUE;\r
720         }\r
721 \r
722         /* Set all the bits other than ebBIT_1 - which is the bit that must be\r
723         set before the other task unblocks. */\r
724         xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 );\r
725 \r
726         /* Ensure all the expected bits are still set. */\r
727         uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
728 \r
729         if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) )\r
730         {\r
731                 xError = pdTRUE;\r
732         }\r
733 \r
734         /* Ensure the other task is still in the blocked state. */\r
735         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
736         {\r
737                 xError = pdTRUE;\r
738         }\r
739 \r
740         /* Now also set ebBIT_1, which should unblock the other task, which will\r
741         then suspend itself. */\r
742         xEventGroupSetBits( xEventGroup, ebBIT_1 );\r
743 \r
744         /* Ensure the other task is suspended. */\r
745         if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
746         {\r
747                 xError = pdTRUE;\r
748         }\r
749 \r
750         /* The other task should not have cleared the bits - so all the bits\r
751         should still be set. */\r
752         if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS )\r
753         {\r
754                 xError = pdTRUE;\r
755         }\r
756 \r
757         /* Clear ebBIT_1 again. */\r
758         if( xEventGroupClearBits( xEventGroup, ebBIT_1 ) != ebALL_BITS )\r
759         {\r
760                 xError = pdTRUE;\r
761         }\r
762 \r
763         /* Resume the other task - which will wait on all the ebCOMBINED_BITS\r
764         again - this time clearing the bits when it is unblocked. */\r
765         vTaskResume( xTestSlaveTaskHandle );\r
766 \r
767         /* Ensure the other task is blocked once again. */\r
768         if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
769         {\r
770                 xError = pdTRUE;\r
771         }\r
772 \r
773         /* Set the bit the other task is waiting for. */\r
774         xEventGroupSetBits( xEventGroup, ebBIT_1 );\r
775 \r
776         /* Ensure the other task is suspended once again. */\r
777         if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
778         {\r
779                 xError = pdTRUE;\r
780         }\r
781 \r
782         /* The other task should have cleared the bits in ebCOMBINED_BITS.\r
783         Clear the remaining bits. */\r
784         uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
785 \r
786         if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
787         {\r
788                 xError = pdTRUE;\r
789         }\r
790 \r
791         /* Clear all bits ready for the sync with the other three tasks.  The\r
792         value returned is the value prior to the bits being cleared. */\r
793         if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
794         {\r
795                 xError = pdTRUE;\r
796         }\r
797 \r
798         /* The bits should be clear now. */\r
799         if( xEventGroupGetBits( xEventGroup ) != 0x00 )\r
800         {\r
801                 xError = pdTRUE;\r
802         }\r
803 \r
804         return xError;\r
805 }\r
806 /*-----------------------------------------------------------*/\r
807 \r
808 static void prvSelectiveBitsTestSlaveFunction( void )\r
809 {\r
810 EventBits_t uxPendBits, uxReturned;\r
811 \r
812         /* Used in a test that blocks two tasks on various different bits within an \r
813         event group - then sets each bit in turn and checks that the correct tasks \r
814         unblock at the correct times.\r
815 \r
816         This function is called by two different tasks - each of which will use a\r
817         different bit.  Check the task handle to see which task the function was\r
818         called by. */\r
819         if( xTaskGetCurrentTaskHandle() == xSyncTask1 )\r
820         {\r
821                 uxPendBits = ebSELECTIVE_BITS_1;\r
822         }\r
823         else\r
824         {\r
825                 uxPendBits = ebSELECTIVE_BITS_2;\r
826         }\r
827 \r
828         for( ;; )\r
829         {\r
830                 /* Wait until it is time to perform the next cycle of the test.  The\r
831                 task is unsuspended by the tests implemented in the \r
832                 prvSelectiveBitsTestMasterFunction() function. */\r
833                 vTaskSuspend( NULL );\r
834                 uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );\r
835 \r
836                 if( uxReturned == ( EventBits_t ) 0 )\r
837                 {\r
838                         break;\r
839                 }\r
840         }\r
841 }\r
842 /*-----------------------------------------------------------*/\r
843 \r
844 static BaseType_t prvSelectiveBitsTestMasterFunction( void )\r
845 {\r
846 BaseType_t xError = pdFALSE;\r
847 EventBits_t uxBit;\r
848 \r
849         /* Used in a test that blocks two tasks on various different bits within an \r
850         event group - then sets each bit in turn and checks that the correct tasks \r
851         unblock at the correct times.  The two other tasks (xSyncTask1 and \r
852         xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in\r
853         this test.\r
854 \r
855         Both other tasks should start in the suspended state. */\r
856         if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
857         {\r
858                 xError = pdTRUE;\r
859         }\r
860 \r
861         if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
862         {\r
863                 xError = pdTRUE;\r
864         }\r
865 \r
866         /* Test each bit in the byte individually. */\r
867         for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 )\r
868         {\r
869                 /* Resume both tasks. */\r
870                 vTaskResume( xSyncTask1 );\r
871                 vTaskResume( xSyncTask2 );\r
872 \r
873                 /* Now both tasks should be blocked on the event group. */\r
874                 if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
875                 {\r
876                         xError = pdTRUE;\r
877                 }\r
878 \r
879                 if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
880                 {\r
881                         xError = pdTRUE;\r
882                 }\r
883 \r
884                 /* Set one bit. */\r
885                 xEventGroupSetBits( xEventGroup, uxBit );\r
886 \r
887                 /* Is the bit set in the first set of selective bits?  If so the first\r
888                 sync task should have unblocked and returned to the suspended state. */\r
889                 if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )\r
890                 {\r
891                         /* Task should not have unblocked. */\r
892                         if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
893                         {\r
894                                 xError = pdTRUE;\r
895                         }\r
896                 }\r
897                 else\r
898                 {\r
899                         /* Task should have unblocked and returned to the suspended state. */\r
900                         if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
901                         {\r
902                                 xError = pdTRUE;\r
903                         }\r
904                 }\r
905 \r
906                 /* Same checks for the second sync task. */\r
907                 if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 )\r
908                 {\r
909                         /* Task should not have unblocked. */\r
910                         if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
911                         {\r
912                                 xError = pdTRUE;\r
913                         }\r
914                 }\r
915                 else\r
916                 {\r
917                         /* Task should have unblocked and returned to the suspended state. */\r
918                         if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
919                         {\r
920                                 xError = pdTRUE;\r
921                         }\r
922                 }\r
923         }\r
924 \r
925         /* Ensure both tasks are blocked on the event group again, then delete the\r
926         event group so the other tasks leave this portion of the test. */\r
927         vTaskResume( xSyncTask1 );\r
928         vTaskResume( xSyncTask2 );\r
929 \r
930         /* Deleting the event group is the signal that the two other tasks should\r
931         leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main\r
932         part of their functionality. */\r
933         vEventGroupDelete( xEventGroup );\r
934 \r
935         return xError;\r
936 }\r
937 /*-----------------------------------------------------------*/\r
938 \r
939 void vPeriodicEventGroupsProcessing( void )\r
940 {\r
941 static BaseType_t xCallCount = 0, xISRTestError = pdFALSE;\r
942 const BaseType_t xSetBitCount = 100, xGetBitsCount = 200, xClearBitsCount = 300;\r
943 const EventBits_t uxBitsToSet = 0x12U;\r
944 EventBits_t uxReturned;\r
945 BaseType_t xMessagePosted;\r
946 \r
947         /* Called periodically from the tick hook to exercise the "FromISR" \r
948         functions. */\r
949 \r
950         xCallCount++;\r
951 \r
952         if( xCallCount == xSetBitCount )\r
953         {\r
954                 /* All the event bits should start clear. */\r
955                 uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );\r
956                 if( uxReturned != 0x00 )\r
957                 {\r
958                         xISRTestError = pdTRUE;\r
959                 }\r
960                 else\r
961                 {\r
962                         /* Set the bits.  This is called from the tick hook so it is not\r
963                         necessary to use the last parameter to ensure a context switch\r
964                         occurs immediately. */\r
965                         xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL );\r
966                         if( xMessagePosted != pdPASS )\r
967                         {\r
968                                 xISRTestError = pdTRUE;\r
969                         }\r
970                 }\r
971         }\r
972         else if( xCallCount == xGetBitsCount )\r
973         {\r
974                 /* Check the bits were set as expected. */\r
975                 uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );\r
976                 if( uxReturned != uxBitsToSet )\r
977                 {\r
978                         xISRTestError = pdTRUE;\r
979                 }\r
980         }\r
981         else if( xCallCount == xClearBitsCount )\r
982         {\r
983                 /* Clear the bits again. */\r
984                 uxReturned = xEventGroupClearBitsFromISR( xISREventGroup, uxBitsToSet );\r
985 \r
986                 /* The returned value should be the value before the bits were cleaed.*/\r
987                 if( uxReturned != uxBitsToSet )\r
988                 {\r
989                         xISRTestError = pdTRUE;\r
990                 }\r
991 \r
992                 /* Go back to the start. */\r
993                 xCallCount = 0;\r
994 \r
995                 /* If no errors have been detected then increment the count of test\r
996                 cycles. */\r
997                 if( xISRTestError == pdFALSE )\r
998                 {\r
999                         ulISRCycles++;\r
1000                 }\r
1001         }\r
1002         else\r
1003         {\r
1004                 /* Nothing else to do. */\r
1005         }\r
1006 }\r
1007 \r
1008 /*-----------------------------------------------------------*/\r
1009 /* This is called to check that all the created tasks are still running. */\r
1010 BaseType_t xAreEventGroupTasksStillRunning( void )\r
1011 {\r
1012 static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0, ulPreviousISRCycles = 0;\r
1013 BaseType_t xStatus = pdPASS;\r
1014 \r
1015         /* Check the tasks are still cycling without finding any errors. */\r
1016         if( ulPreviousSetBitCycles == ulTestMasterCycles )\r
1017         {\r
1018                 xStatus = pdFAIL;\r
1019         }\r
1020         ulPreviousSetBitCycles = ulTestMasterCycles;\r
1021 \r
1022         if( ulPreviousWaitBitCycles == ulTestSlaveCycles )\r
1023         {\r
1024                 xStatus = pdFAIL;\r
1025         }\r
1026         ulPreviousWaitBitCycles = ulTestSlaveCycles;\r
1027 \r
1028         if( ulPreviousISRCycles == ulISRCycles )\r
1029         {\r
1030                 xStatus = pdFAIL;\r
1031         }\r
1032         ulPreviousISRCycles = ulISRCycles;\r
1033 \r
1034         return xStatus;\r
1035 }\r
1036 \r
1037 \r
1038 \r