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