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