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