]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
Add some asserts into the common demo tasks to catch scenarios where the tasks are...
[freertos] / FreeRTOS / Demo / Common / Minimal / EventGroupsDemo.c
index abbf0699183dc71ef13d0444baa235223dbba8d4..21b2d7769da04b53297b599e5e105c6593da26ab 100644 (file)
@@ -1,76 +1,41 @@
 /*\r
-    FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
-    All rights reserved\r
-\r
-    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    FreeRTOS provides completely free yet professionally developed,    *\r
-     *    robust, strictly quality controlled, supported, and cross          *\r
-     *    platform software that has become a de facto standard.             *\r
-     *                                                                       *\r
-     *    Help yourself get started quickly and support the FreeRTOS         *\r
-     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
-     *                                                                       *\r
-     *    Thank you!                                                         *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    This file is part of the FreeRTOS distribution.\r
-\r
-    FreeRTOS is free software; you can redistribute it and/or modify it under\r
-    the terms of the GNU General Public License (version 2) as published by the\r
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
-\r
-    >>! NOTE: The modification to the GPL is included to allow you to distribute\r
-    >>! a combined work that includes FreeRTOS without being obliged to provide\r
-    >>! the source code for proprietary components outside of the FreeRTOS\r
-    >>! kernel.\r
-\r
-    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
-    FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
-    link: http://www.freertos.org/a00114.html\r
-\r
-    1 tab == 4 spaces!\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    Having a problem?  Start by reading the FAQ "My application does   *\r
-     *    not run, what could be wrong?"                                     *\r
-     *                                                                       *\r
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
-    license and Real Time Engineers Ltd. contact details.\r
-\r
-    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
-    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
-    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
-    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
-    licenses offer ticketed support, indemnification and middleware.\r
-\r
-    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
-    engineered and independently SIL3 certified version for use in safety and\r
-    mission critical applications that require provable dependability.\r
-\r
-    1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
 \r
 \r
 \r
 /*\r
- * This file contains fairly comprehensive checks on the behaviour of event\r
- * groups.  It is not intended to be a user friendly demonstration of the event\r
- * groups API.\r
- */\r
-\r
+* This file contains fairly comprehensive checks on the behaviour of event\r
+* groups.  It is not intended to be a user friendly demonstration of the\r
+* event groups API.\r
+*\r
+* NOTE:  The tests implemented in this file are informal 'sanity' tests\r
+* only and are not part of the module tests that make use of the\r
+* mtCOVERAGE_TEST_MARKER macro within the event groups implementation.\r
+*/\r
 \r
 \r
 /* Scheduler include files. */\r
 #include "task.h"\r
 #include "event_groups.h"\r
 \r
+/* Demo app includes. */\r
+#include "EventGroupsDemo.h"\r
+\r
+#if( INCLUDE_eTaskGetState != 1 )\r
+       #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.\r
+#endif\r
+\r
 /* Priorities used by the tasks. */\r
 #define ebSET_BIT_TASK_PRIORITY                ( tskIDLE_PRIORITY )\r
 #define ebWAIT_BIT_TASK_PRIORITY       ( tskIDLE_PRIORITY + 1 )\r
 \r
 /* Generic bit definitions. */\r
-#define ebBIT_0                ( 0x01UL )\r
-#define ebBIT_1                ( 0x02UL )\r
-#define ebBIT_2                ( 0x04UL )\r
-#define ebBIT_3                ( 0x08UL )\r
-#define ebBIT_4                ( 0x10UL )\r
-#define ebBIT_5                ( 0x20UL )\r
-#define ebBIT_6                ( 0x40UL )\r
-#define ebBIT_7                ( 0x80UL )\r
-\r
-/* Combinations of bits used in the tests. */\r
+#define ebBIT_0                ( 0x01 )\r
+#define ebBIT_1                ( 0x02 )\r
+#define ebBIT_2                ( 0x04 )\r
+#define ebBIT_3                ( 0x08 )\r
+#define ebBIT_4                ( 0x10 )\r
+#define ebBIT_5                ( 0x20 )\r
+#define ebBIT_6                ( 0x40 )\r
+#define ebBIT_7                ( 0x80 )\r
+\r
+/* Combinations of bits used in the demo. */\r
 #define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 )\r
 #define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )\r
 \r
@@ -106,340 +78,324 @@ that synchronise with the xEventGroupSync() function. */
 \r
 /* A block time of zero simply means "don't block". */\r
 #define ebDONT_BLOCK   ( 0 )\r
+#define ebONE_TICK             ( ( TickType_t ) 1 )\r
 \r
 /* A 5ms delay. */\r
-#define ebSHORT_DELAY  ( 5 / portTICK_RATE_MS )\r
+#define ebSHORT_DELAY  pdMS_TO_TICKS( ( TickType_t ) 5 )\r
+\r
+/* Used in the selective bits test which checks no, one or both tasks blocked on\r
+event bits in a group are unblocked as appropriate as different bits get set. */\r
+#define ebSELECTIVE_BITS_1             0x03\r
+#define ebSELECTIVE_BITS_2             0x05\r
+\r
+#ifndef ebRENDESVOUS_TEST_TASK_STACK_SIZE\r
+       #define ebRENDESVOUS_TEST_TASK_STACK_SIZE configMINIMAL_STACK_SIZE\r
+#endif\r
+\r
+#ifndef ebEVENT_GROUP_SET_BITS_TEST_TASK_STACK_SIZE\r
+       #define ebEVENT_GROUP_SET_BITS_TEST_TASK_STACK_SIZE     configMINIMAL_STACK_SIZE\r
+#endif\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
- * The primary task that manages and controls all the behavioural tests.\r
+ * NOTE:  The tests implemented in this function are informal 'sanity' tests\r
+ * only and are not part of the module tests that make use of the\r
+ * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.\r
+ *\r
+ * The master test task.  This task:\r
+ *\r
+ * 1) Calls prvSelectiveBitsTestMasterFunction() to test the behaviour when two\r
+ *    tasks are blocked on different bits in an event group.  The counterpart of\r
+ *    this test is implemented by the prvSelectiveBitsTestSlaveFunction()\r
+ *    function (which is called by the two tasks that block on the event group).\r
+ *\r
+ * 2) Calls prvBitCombinationTestMasterFunction() to test the behaviour when\r
+ *    just one task is blocked on various combinations of bits within an event\r
+ *    group.  The counterpart of this test is implemented within the 'test\r
+ *    slave' task.\r
+ *\r
+ * 3) Calls prvPerformTaskSyncTests() to test task synchronisation behaviour.\r
+ */\r
+static void prvTestMasterTask( void *pvParameters );\r
+\r
+/*\r
+ * A helper task that enables the 'test master' task to perform several\r
+ * behavioural tests.  See the comments above the prvTestMasterTask() prototype\r
+ * above.\r
+ */\r
+static void prvTestSlaveTask( void *pvParameters );\r
+\r
+/*\r
+ * The part of the test that is performed between the 'test master' task and the\r
+ * 'test slave' task to test the behaviour when the slave blocks on various\r
+ * event bit combinations.\r
  */\r
-static void prvSetBitsTask( void *pvParameters );\r
+static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );\r
 \r
 /*\r
- * The task that participates in most of the non 'single task' tests performed\r
- * by prvSetBitsTask().\r
+ * The part of the test that uses all the tasks to test the task synchronisation\r
+ * behaviour.\r
  */\r
-static void prvWaitBitsTask( void *pvParameters );\r
+static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );\r
 \r
 /*\r
- * Two instances of prvSyncTask() are created.  Their only purpose is to\r
- * participate in synchronisations and test the behaviour when an event group on\r
- * which they are blocked is deleted.\r
+ * Two instances of prvSyncTask() are created.  They start by calling\r
+ * prvSelectiveBitsTestSlaveFunction() to act as slaves when the test master is\r
+ * executing the prvSelectiveBitsTestMasterFunction() function.  They then loop\r
+ * to test the task synchronisation (rendezvous) behaviour.\r
  */\r
 static void prvSyncTask( void *pvParameters );\r
 \r
 /*\r
- * Contains a set of behavioural tests that can be performed from a single task.\r
- * This function is called by prvSetBitsTask() before prvSetBitsTasks() starts\r
- * the tests that make use of the prvWaitBitsTask().\r
+ * Functions used in a test that blocks two tasks on various different bits\r
+ * within an event group - then sets each bit in turn and checks that the\r
+ * correct tasks unblock at the correct times.\r
  */\r
-static portBASE_TYPE prvSingleTaskTests( void );\r
+static BaseType_t prvSelectiveBitsTestMasterFunction( void );\r
+static void prvSelectiveBitsTestSlaveFunction( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
 /* Variables that are incremented by the tasks on each cycle provided no errors\r
 have been found.  Used to detect an error or stall in the test cycling. */\r
-static volatile unsigned long ulSetBitCycles = 0, ulWaitBitCycles = 0;\r
+static volatile uint32_t ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0;\r
 \r
-/* The event group used by all the tests. */\r
-static xEventGroupHandle xEventBits = NULL;\r
+/* The event group used by all the task based tests. */\r
+static EventGroupHandle_t xEventGroup = NULL;\r
+\r
+/* The event group used by the interrupt based tests. */\r
+static EventGroupHandle_t xISREventGroup = NULL;\r
 \r
 /* Handles to the tasks that only take part in the synchronisation calls. */\r
-static xTaskHandle xSyncTask1 = NULL, xSyncTask2 = NULL;\r
+static TaskHandle_t xSyncTask1 = NULL, xSyncTask2 = NULL;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-void vStartEventBitTasks( void )\r
+void vStartEventGroupTasks( void )\r
 {\r
-xTaskHandle xWaitBitsTaskHandle;\r
+TaskHandle_t xTestSlaveTaskHandle;\r
 \r
        /*\r
         * This file contains fairly comprehensive checks on the behaviour of event\r
         * groups.  It is not intended to be a user friendly demonstration of the\r
         * event groups API.\r
+        *\r
+        * NOTE:  The tests implemented in this file are informal 'sanity' tests\r
+        * only and are not part of the module tests that make use of the\r
+        * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.\r
+        *\r
+        * Create the test tasks as described at the top of this file.\r
         */\r
-\r
-       /* Create the event bits that will be used by the tasks. */\r
-       xEventBits = xEventGroupCreate();\r
-       configASSERT( xEventBits );\r
-\r
-       xTaskCreate( prvWaitBitsTask, ( signed char * ) "WaitO", configMINIMAL_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xWaitBitsTaskHandle );\r
-       xTaskCreate( prvSetBitsTask, ( signed char * ) "SetB", configMINIMAL_STACK_SIZE, ( void * ) xWaitBitsTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL );\r
-       xTaskCreate( prvSyncTask, ( signed char * ) "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );\r
-       xTaskCreate( prvSyncTask, ( signed char * ) "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 );\r
+       xTaskCreate( prvTestSlaveTask, "WaitO", ebRENDESVOUS_TEST_TASK_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xTestSlaveTaskHandle );\r
+       xTaskCreate( prvTestMasterTask, "SetB", ebEVENT_GROUP_SET_BITS_TEST_TASK_STACK_SIZE, ( void * ) xTestSlaveTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL );\r
+       xTaskCreate( prvSyncTask, "Rndv", ebRENDESVOUS_TEST_TASK_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );\r
+       xTaskCreate( prvSyncTask, "Rndv", ebRENDESVOUS_TEST_TASK_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 );\r
 \r
        /* If the last task was created then the others will have been too. */\r
        configASSERT( xSyncTask2 );\r
+\r
+       /* Create the event group used by the ISR tests.  The event group used by\r
+       the tasks is created by the tasks themselves. */\r
+       xISREventGroup = xEventGroupCreate();\r
+       configASSERT( xISREventGroup );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static portBASE_TYPE prvSingleTaskTests( void )\r
+static void prvTestMasterTask( void *pvParameters )\r
 {\r
-xEventBitsType uxReturned;\r
-portBASE_TYPE xError = pdFALSE, xHigherPriorityTaskWoken;\r
-portTickType xTimeOnEntering, xTimeOnExiting;\r
-\r
-       /* Check no bits are currently set. */\r
-       uxReturned = xEventGroupWaitBits(       xEventBits,             /* The event flags being tested. */\r
-                                                                       ebBIT_1,                /* The bit being tested. */\r
-                                                                       pdFALSE,                /* Don't clear the bit on exit. */\r
-                                                                       pdFALSE,                /* Wait for a single bit, not all the bits. */\r
-                                                                       ebDONT_BLOCK ); /* Block time. */\r
-\r
-       if( uxReturned != 0x00 )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
-\r
-       /* Set selected bits. */\r
-       xEventGroupSetBits( xEventBits, ebCOMBINED_BITS );\r
-\r
-       /* Wait on all the selected bits.  This should return immediately even\r
-       though a block time is specified. */\r
-       uxReturned = xEventGroupWaitBits( xEventBits, ebCOMBINED_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
-\r
-       if( uxReturned != ebCOMBINED_BITS )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
-\r
-       /* Now try waiting on all the selected bits plus a bit that is not set.\r
-       This should time out. */\r
-       xTimeOnEntering = xTaskGetTickCount();\r
-       uxReturned = xEventGroupWaitBits(       xEventBits,                                     /* The event flags being tested. */\r
-                                                                       ebCOMBINED_BITS | ebBIT_0,      /* The bits being tested. */\r
-                                                                       pdFALSE,                                        /* Don't clear the bits on exit. */\r
-                                                                       pdTRUE,                                         /* Wait for all the bits to be set, not just a single bit. */\r
-                                                                       ebSHORT_DELAY );                        /* Block time. */\r
-       xTimeOnExiting = xTaskGetTickCount();\r
-\r
-       if( ( xTimeOnExiting - xTimeOnEntering ) < ebSHORT_DELAY )\r
-       {\r
-               /* Did not block as expected. */\r
-               xError = pdTRUE;\r
-       }\r
-\r
-       if( uxReturned != ebCOMBINED_BITS )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
-\r
-\r
-       /* This time pass in the same bit combination, but wait for only a single\r
-       bit.  This time it should not block even though one of the bits in the\r
-       combination is not set. */\r
-       xTimeOnEntering = xTaskGetTickCount();\r
-       uxReturned = xEventGroupWaitBits(       xEventBits,                                     /* The event flags being tested. */\r
-                                                                       ebCOMBINED_BITS | ebBIT_0,      /* The bits being tested. */\r
-                                                                       pdFALSE,                                        /* Don't clear the bits on exit. */\r
-                                                                       pdFALSE,                                        /* Don't wait for all the bits to be set, a single bit is all that is required. */\r
-                                                                       ebSHORT_DELAY );                        /* Block time. */\r
-       xTimeOnExiting = xTaskGetTickCount();\r
+BaseType_t xError;\r
 \r
-       if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )\r
-       {\r
-               /* Blocked, but didn't expect to. */\r
-               xError = pdTRUE;\r
-       }\r
-\r
-       if( uxReturned != ebCOMBINED_BITS )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
-\r
-\r
-       /* Now set all the bits. */\r
-       xEventGroupSetBits( xEventBits, ebALL_BITS );\r
-\r
-       /* Read the bits back to ensure they are all set.  Read back with a timeout\r
-       to ensure the task does not block (all the bits are already set), and leave\r
-       the bits set on exit. */\r
-       xTimeOnEntering = xTaskGetTickCount();\r
-       uxReturned = xEventGroupWaitBits(       xEventBits,             /* The event flags being tested. */\r
-                                                                       ebALL_BITS,             /* The bits being tested. */\r
-                                                                       pdFALSE,                /* Don't clear the bits on exit. */\r
-                                                                       pdTRUE,                 /* Wait for all the bits to be set. */\r
-                                                                       ebSHORT_DELAY );/* Block time. */\r
-       xTimeOnExiting = xTaskGetTickCount();\r
-\r
-       if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )\r
-       {\r
-               /* Blocked, but didn't expect to. */\r
-               xError = pdTRUE;\r
-       }\r
+/* The handle to the slave task is passed in as the task parameter. */\r
+TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters;\r
 \r
-       if( uxReturned != ebALL_BITS )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
-\r
-\r
-       /* Now wait for some bits to be set (which are all set), and clear the bits\r
-       on exit.  Again this should not block. */\r
-       xTimeOnEntering = xTaskGetTickCount();\r
-       uxReturned = xEventGroupWaitBits(       xEventBits,                     /* The event flags being tested. */\r
-                                                                       ebCOMBINED_BITS,        /* The bits being tested, which are a subset of the bits now set. */\r
-                                                                       pdTRUE,                         /* Clear the bits on exit. */\r
-                                                                       pdTRUE,                         /* Wait for all the bits to be set (which they already are. */\r
-                                                                       ebSHORT_DELAY );        /* Block time. */\r
-       xTimeOnExiting = xTaskGetTickCount();\r
-\r
-       if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )\r
-       {\r
-               /* Blocked, but didn't expect to. */\r
-               xError = pdTRUE;\r
-       }\r
-\r
-       if( uxReturned != ebALL_BITS )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
+       /* Avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
 \r
-       /* Now the bits set by the ebCOMBINED_BITS constant should be clear, but\r
-       all the other bits should be set.  Call xEventGroupWaitBits() again, this time\r
-       waiting for any bit within ebALL_BITS, and clearing all bits on exit to\r
-       leave the event bits all clear again. */\r
-       xTimeOnEntering = xTaskGetTickCount();\r
-       uxReturned = xEventGroupWaitBits(       xEventBits,                     /* The event flags being tested. */\r
-                                                                       ebALL_BITS,                     /* The bits being tested, which are a subset of the bits now set. */\r
-                                                                       pdTRUE,                         /* Clear the bits on exit. */\r
-                                                                       pdFALSE,                        /* Wait for any bit to be set. */\r
-                                                                       ebSHORT_DELAY );        /* Block time. */\r
-       xTimeOnExiting = xTaskGetTickCount();\r
+       /* Create the event group used by the tasks ready for the initial tests. */\r
+       xEventGroup = xEventGroupCreate();\r
+       configASSERT( xEventGroup );\r
 \r
-       if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )\r
-       {\r
-               /* Blocked, but didn't expect to. */\r
-               xError = pdTRUE;\r
-       }\r
+       /* Perform the tests that block two tasks on different combinations of bits,\r
+       then set each bit in turn and check the correct tasks unblock at the correct\r
+       times. */\r
+       xError = prvSelectiveBitsTestMasterFunction();\r
 \r
-       /* The bits defined in ebCOMBINED_BITS were already cleared, so this time\r
-       only the remaining bits should have been set. */\r
-       if( uxReturned != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
+       for( ;; )\r
        {\r
-               xError = pdTRUE;\r
-       }\r
+               /* Recreate the event group ready for the next cycle. */\r
+               xEventGroup = xEventGroupCreate();\r
+               configASSERT( xEventGroup );\r
 \r
+               /* Perform the tests that check the behaviour when a single task is\r
+               blocked on various combinations of event bits. */\r
+               xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle );\r
 \r
+               /* Perform the task synchronisation tests. */\r
+               xError = prvPerformTaskSyncTests( xError, xTestSlaveTaskHandle );\r
 \r
-       /* All the bits should be clear again as the last call to xEventGroupWaitBits()\r
-       had the "clear on exit" parameter set to pdTRUE. */\r
-       uxReturned = xEventGroupGetBits( xEventBits );\r
+               /* Delete the event group. */\r
+               vEventGroupDelete( xEventGroup );\r
 \r
-       if( uxReturned != 0x00 )\r
-       {\r
-               /* Expected all bits to be clear. */\r
-               xError = pdTRUE;\r
-       }\r
+               /* Now all the other tasks should have completed and suspended\r
+               themselves ready for the next go around the loop. */\r
+               if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
 \r
-       /* Try the 'set from ISR' function, which will pend the set to the timer\r
-       daemon task. */\r
-       xHigherPriorityTaskWoken = pdFALSE;\r
-       if( xEventGroupSetBitsFromISR( xEventBits, ebBIT_3, &xHigherPriorityTaskWoken ) != pdPASS )\r
-       {\r
-               xError = pdTRUE;\r
-       }\r
+               if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
 \r
-       if( xHigherPriorityTaskWoken == pdTRUE )\r
-       {\r
-               /* If the daemon task has a higher priority then a yield should be\r
-               performed to ensure it runs before the bits are tested. */\r
-               taskYIELD();\r
-       }\r
+               if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
 \r
-       /* Is the bit set? */\r
-       uxReturned = xEventGroupGetBits( xEventBits );\r
+               /* Only increment the cycle variable if no errors have been detected. */\r
+               if( xError == pdFALSE )\r
+               {\r
+                       ulTestMasterCycles++;\r
+               }\r
 \r
-       if( uxReturned != ebBIT_3 )\r
-       {\r
-               /* Expected all bits to be clear. */\r
-               xError = pdTRUE;\r
+               configASSERT( xError == pdFALSE );\r
        }\r
-\r
-       /* Clear all bits again ready for infinite loop tests. */\r
-       xEventGroupClearBits( xEventBits, ebALL_BITS );\r
-\r
-       return xError;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 static void prvSyncTask( void *pvParameters )\r
 {\r
-xEventBitsType uxSynchronisationBit, uxReturned;\r
+EventBits_t uxSynchronisationBit, uxReturned;\r
+\r
+       /* A few tests that check the behaviour when two tasks are blocked on\r
+       various different bits within an event group are performed before this task\r
+       enters its infinite loop to carry out its main demo function. */\r
+       prvSelectiveBitsTestSlaveFunction();\r
 \r
        /* The bit to use to indicate this task is at the synchronisation point is\r
        passed in as the task parameter. */\r
-       uxSynchronisationBit = ( xEventBitsType ) pvParameters;\r
+       uxSynchronisationBit = ( EventBits_t ) pvParameters;\r
 \r
        for( ;; )\r
        {\r
-               /* Wait until the 'set bit' task unsuspends this task. */\r
+               /* Now this task takes part in a task synchronisation - sometimes known\r
+               as a 'rendezvous'.  Its execution pattern is controlled by the 'test\r
+               master' task, which is responsible for taking this task out of the\r
+               Suspended state when it is time to test the synchronisation behaviour.\r
+               See: http://www.freertos.org/xEventGroupSync.html. */\r
                vTaskSuspend( NULL );\r
 \r
                /* Set the bit that indicates this task is at the synchronisation\r
-               point.  The first time this is done the 'set bit' task has a lower\r
-               priority than this task. */\r
-               uxReturned = xEventGroupSync( xEventBits, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );\r
+               point.  The first time this is done the 'test master' task has a lower\r
+               priority than this task so this task will get to the sync point before\r
+               the set bits task - test this by first calling xEventGroupSync() with\r
+               a zero block time, and a block time that is too short for the other\r
+               task, before calling again with a max delay - the first two calls should\r
+               return before the rendezvous completes, the third only after the\r
+               rendezvous is complete. */\r
+               uxReturned = xEventGroupSync( xEventGroup,      /* The event group used for the synchronisation. */\r
+                                                                         uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */\r
+                                                                         ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */\r
+                                                                         ebDONT_BLOCK ); /* The maximum time to wait for the sync condition to be met before giving up. */\r
+\r
+               /* No block time was specified, so as per the comments above, the\r
+               rendezvous is not expected to have completed yet. */\r
+               configASSERT( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS );\r
+\r
+               uxReturned = xEventGroupSync( xEventGroup,      /* The event group used for the synchronisation. */\r
+                                                                         uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */\r
+                                                                         ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks taking part in the sync. */\r
+                                                                         ebONE_TICK ); /* The maximum time to wait for the sync condition to be met before giving up. */\r
+\r
+               /* A short block time was specified, so as per the comments above, the\r
+               rendezvous is not expected to have completed yet. */\r
+               configASSERT( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS );\r
+\r
+               uxReturned = xEventGroupSync( xEventGroup,      /* The event group used for the synchronisation. */\r
+                                                                       uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */\r
+                                                                       ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */\r
+                                                                       portMAX_DELAY );/* The maximum time to wait for the sync condition to be met before giving up. */\r
+\r
+               /* A max delay was used, so this task should only exit the above\r
+               function call when the sync condition is met.  Check this is the\r
+               case. */\r
                configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
 \r
-               /* Wait until the 'set bit' task unsuspends this task again. */\r
+               /* Remove compiler warning if configASSERT() is not defined. */\r
+               ( void ) uxReturned;\r
+\r
+               /* Wait until the 'test master' task unsuspends this task again. */\r
                vTaskSuspend( NULL );\r
 \r
                /* Set the bit that indicates this task is at the synchronisation\r
-               point again.  This time the 'set bit' task has a higher priority than\r
-               this task. */\r
-               uxReturned = xEventGroupSync( xEventBits, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );\r
+               point again.  This time the 'test master' task has a higher priority\r
+               than this task so will get to the sync point before this task. */\r
+               uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );\r
+\r
+               /* Again a max delay was used, so this task should only exit the above\r
+               function call when the sync condition is met.  Check this is the\r
+               case. */\r
                configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
 \r
                /* Block on the event group again.  This time the event group is going\r
-               to be deleted, so 0 should be returned. */\r
-               uxReturned = xEventGroupWaitBits( xEventBits, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
+               to be deleted while this task is blocked on it so it is expected that 0\r
+               be returned. */\r
+               uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
                configASSERT( uxReturned == 0 );\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvWaitBitsTask( void *pvParameters )\r
+static void prvTestSlaveTask( void *pvParameters )\r
 {\r
-xEventBitsType uxReturned;\r
-portBASE_TYPE xError = pdFALSE;\r
+EventBits_t uxReturned;\r
+BaseType_t xError = pdFALSE;\r
 \r
        /* Avoid compiler warnings. */\r
        ( void ) pvParameters;\r
 \r
        for( ;; )\r
        {\r
-               /* This task is controller by the prvSetBitsTask().  Suspend until resumed\r
-               by prvSetBitsTask(). */\r
+               /**********************************************************************\r
+               * Part 1:  This section is the counterpart to the\r
+               * prvBitCombinationTestMasterFunction() function which is called by the\r
+               * test master task.\r
+               ***********************************************************************\r
+\r
+               This task is controller by the 'test master' task (which is\r
+               implemented by prvTestMasterTask()).  Suspend until resumed by the\r
+               'test master' task. */\r
                vTaskSuspend( NULL );\r
 \r
                /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get\r
                set.  Clear the bit on exit. */\r
-               uxReturned = xEventGroupWaitBits( xEventBits,   /* The event bits being queried. */\r
-                                                                        ebBIT_1,               /* The bit to wait for. */\r
-                                                                        pdTRUE,                /* Clear the bit on exit. */\r
-                                                                        pdTRUE,                /* Wait for all the bits (only one in this case anyway. */\r
-                                                                        portMAX_DELAY );\r
-\r
-               /* Should unblock after the 'set bit' task has set all the bits in the\r
-               ebCOMBINED_BITS constant, therefore ebCOMBINED_BITS is what should have\r
-               been returned. */\r
+               uxReturned = xEventGroupWaitBits( xEventGroup,  /* The event group that contains the event bits being queried. */\r
+                                                                                ebBIT_1,               /* The bit to wait for. */\r
+                                                                                pdTRUE,                /* Clear the bit on exit. */\r
+                                                                                pdTRUE,                /* Wait for all the bits (only one in this case anyway). */\r
+                                                                                portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */\r
+\r
+               /* The 'test master' task set all the bits defined by ebCOMBINED_BITS,\r
+               only one of which was being waited for by this task.  The return value\r
+               shows the state of the event bits when the task was unblocked, however\r
+               because the task was waiting for ebBIT_1 and 'clear on exit' was set to\r
+               the current state of the event bits will have ebBIT_1 clear.  */\r
                if( uxReturned != ebCOMBINED_BITS )\r
                {\r
                        xError = pdTRUE;\r
                }\r
 \r
-               /* Now call xEventGroupWaitBits() again, this time waiting for all the bits\r
-               in ebCOMBINED_BITS to be set.  This call should block until the 'set\r
-               bits' task sets ebBIT_1 - which was the bit cleared in the call to\r
-               xEventGroupWaitBits() above. */\r
-               uxReturned = xEventGroupWaitBits( xEventBits,\r
-                                                                        ebCOMBINED_BITS, /* The bits being waited on. */\r
-                                                                        pdFALSE,                 /* Don't clear the bits on exit. */\r
-                                                                        pdTRUE,                  /* All the bits must be set to unblock. */\r
-                                                                        portMAX_DELAY );\r
+               /* Now call xEventGroupWaitBits() again, this time waiting for all the\r
+               bits in ebCOMBINED_BITS to be set.  This call should block until the\r
+               'test master' task sets ebBIT_1 - which was the bit cleared in the call\r
+               to xEventGroupWaitBits() above. */\r
+               uxReturned = xEventGroupWaitBits( xEventGroup,\r
+                                                                                ebCOMBINED_BITS, /* The bits being waited on. */\r
+                                                                                pdFALSE,                 /* Don't clear the bits on exit. */\r
+                                                                                pdTRUE,                  /* All the bits must be set to unblock. */\r
+                                                                                portMAX_DELAY );\r
 \r
                /* Were all the bits set? */\r
                if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS )\r
@@ -447,29 +403,49 @@ portBASE_TYPE xError = pdFALSE;
                        xError = pdTRUE;\r
                }\r
 \r
-               /* Suspend again to wait for the 'set bit' task. */\r
+               /* Suspend again to wait for the 'test master' task. */\r
                vTaskSuspend( NULL );\r
 \r
-               /* Now call xEventGroupWaitBits() again, again waiting for all the bits in\r
-               ebCOMBINED_BITS to be set, but this time clearing the bits when the task\r
-               is unblocked. */\r
-               uxReturned = xEventGroupWaitBits( xEventBits,\r
+               /* Now call xEventGroupWaitBits() again, again waiting for all the bits\r
+               in ebCOMBINED_BITS to be set, but this time clearing the bits when the\r
+               task is unblocked. */\r
+               uxReturned = xEventGroupWaitBits( xEventGroup,\r
                                                                         ebCOMBINED_BITS, /* The bits being waited on. */\r
                                                                         pdTRUE,                  /* Clear the bits on exit. */\r
                                                                         pdTRUE,                  /* All the bits must be set to unblock. */\r
                                                                         portMAX_DELAY );\r
 \r
-\r
+               /* The 'test master' task set all the bits in the event group, so that\r
+               is the value that should have been returned.  The bits defined by\r
+               ebCOMBINED_BITS will have been clear again in the current value though\r
+               as 'clear on exit' was set to pdTRUE. */\r
                if( uxReturned != ebALL_BITS )\r
                {\r
                        xError = pdTRUE;\r
                }\r
 \r
+\r
+\r
+\r
+\r
+               /**********************************************************************\r
+               * Part 2:  This section is the counterpart to the\r
+               * prvPerformTaskSyncTests() function which is called by the\r
+               * test master task.\r
+               ***********************************************************************\r
+\r
+\r
+               Once again wait for the 'test master' task to unsuspend this task\r
+               when it is time for the next test. */\r
                vTaskSuspend( NULL );\r
 \r
-               /* Now to synchronise with when 'set bit' task has the lowest\r
-               priority. */\r
-               uxReturned = xEventGroupSync( xEventBits, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
+               /* Now peform a synchronisation with all the other tasks.  At this point\r
+               the 'test master' task has the lowest priority so will get to the sync\r
+               point after all the other synchronising tasks. */\r
+               uxReturned = xEventGroupSync( xEventGroup,              /* The event group used for the sync. */\r
+                                                                       ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */\r
+                                                                       ebALL_SYNC_BITS,        /* The bits to wait for.  These bits are set by the other tasks taking part in the sync. */\r
+                                                                       portMAX_DELAY );        /* The maximum time to wait for the sync condition to be met before giving up. */\r
 \r
                /* A sync with a max delay should only exit when all the synchronisation\r
                bits are set... */\r
@@ -478,8 +454,17 @@ portBASE_TYPE xError = pdFALSE;
                        xError = pdTRUE;\r
                }\r
 \r
-               /* ...but now the synchronisation bits should be clear again. */\r
-               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
+               /* ...but now the synchronisation bits should be clear again.  Read back\r
+               the current value of the bits within the event group to check that is\r
+               the case.  Setting the bits to zero will return the bits previous value\r
+               then leave all the bits clear. */\r
+               if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               /* Check the bits are indeed 0 now by simply reading then. */\r
+               if( xEventGroupGetBits( xEventGroup ) != 0 )\r
                {\r
                        xError = pdTRUE;\r
                }\r
@@ -487,14 +472,15 @@ portBASE_TYPE xError = pdFALSE;
                if( xError == pdFALSE )\r
                {\r
                        /* This task is still cycling without finding an error. */\r
-                       ulWaitBitCycles++;\r
+                       ulTestSlaveCycles++;\r
                }\r
 \r
                vTaskSuspend( NULL );\r
 \r
-               /* This time sync when the 'set bit' task has the highest priority\r
-               at the point where it sets its sync bit. */\r
-               uxReturned = xEventGroupSync( xEventBits, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
+               /* This time sync when the 'test master' task has the highest priority\r
+               at the point where it sets its sync bit - so this time the 'test master'\r
+               task will get to the sync point before this task. */\r
+               uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
 \r
                /* A sync with a max delay should only exit when all the synchronisation\r
                bits are set... */\r
@@ -504,14 +490,15 @@ portBASE_TYPE xError = pdFALSE;
                }\r
 \r
                /* ...but now the sync bits should be clear again. */\r
-               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
+               if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )\r
                {\r
                        xError = pdTRUE;\r
                }\r
 \r
                /* Block on the event group again.  This time the event group is going\r
-               to be deleted, so 0 should be returned. */\r
-               uxReturned = xEventGroupWaitBits( xEventBits, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
+               to be deleted while this task is blocked on it, so it is expected that 0\r
+               will be returned. */\r
+               uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );\r
 \r
                if( uxReturned != 0 )\r
                {\r
@@ -521,7 +508,7 @@ portBASE_TYPE xError = pdFALSE;
                if( xError == pdFALSE )\r
                {\r
                        /* This task is still cycling without finding an error. */\r
-                       ulWaitBitCycles++;\r
+                       ulTestSlaveCycles++;\r
                }\r
 \r
                configASSERT( xError == pdFALSE );\r
@@ -529,219 +516,390 @@ portBASE_TYPE xError = pdFALSE;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvSetBitsTask( void *pvParameters )\r
+static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )\r
 {\r
-xEventBitsType uxBits;\r
-portBASE_TYPE xError;\r
+EventBits_t uxBits;\r
 \r
-/* The handle to the other task is passed in as the task parameter. */\r
-xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;\r
+       /* The three tasks that take part in the synchronisation (rendezvous) are\r
+       expected to be in the suspended state at the start of the test. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-       /* Avoid compiler warnings. */\r
-       ( void ) pvParameters;\r
+       if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-       xError = prvSingleTaskTests();\r
+       /* Try a synch with no other tasks involved.  First set all the bits other\r
+       than this task's bit. */\r
+       xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );\r
 \r
-       for( ;; )\r
+       /* Then wait on just one bit - the bit that is being set. */\r
+       uxBits = xEventGroupSync( xEventGroup,                  /* The event group used for the synchronisation. */\r
+                                                       ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */\r
+                                                       ebSET_BIT_TASK_SYNC_BIT,/* The bits to wait for - in this case it is just waiting for itself. */\r
+                                                       portMAX_DELAY );                /* The maximum time to wait for the sync condition to be met. */\r
+\r
+       /* A sync with a max delay should only exit when all the synchronise\r
+       bits are set...check that is the case.  In this case there is only one\r
+       sync bit anyway. */\r
+       if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT )\r
        {\r
-               /* Resume the other task.  It will block, pending a single bit from\r
-               within ebCOMBINED_BITS. */\r
-               vTaskResume( xWaitBitsTaskHandle );\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Ensure the other task is blocked on the task. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* ...but now the sync bits should be clear again, leaving all the other\r
+       bits set (as only one bit was being waited for). */\r
+       if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Set all the bits in ebCOMBINED_BITS - the 'wait bits' task is only\r
-               blocked waiting for one of them. */\r
-               xEventGroupSetBits( xEventBits, ebCOMBINED_BITS );\r
+       /* Clear all the bits to zero again. */\r
+       xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );\r
+       if( xEventGroupGetBits( xEventGroup ) != 0 )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* The 'wait bits' task should now have executed, clearing ebBIT_1 (the\r
-               bit it was blocked on), then re-entered the Blocked state to wait for\r
-               all the other bits in ebCOMBINED_BITS to be set again.  First check\r
-               ebBIT_1 is clear. */\r
-               uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
+       /* Unsuspend the other tasks then check they have executed up to the\r
+       synchronisation point. */\r
+       vTaskResume( xTestSlaveTaskHandle );\r
+       vTaskResume( xSyncTask1 );\r
+       vTaskResume( xSyncTask2 );\r
 \r
-               if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Ensure the other task is still in the blocked state. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Set all the bits other than ebBIT_1 - which is the bit that must be\r
-               set before the other task unblocks. */\r
-               xEventGroupSetBits( xEventBits, ebALL_BITS & ~ebBIT_1 );\r
+       if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Ensure all the expected bits are still set. */\r
-               uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
+       /* Set this task's sync bit. */\r
+       uxBits = xEventGroupSync( xEventGroup,                  /* The event group used for the synchronisation. */\r
+                                                       ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */\r
+                                                       ebALL_SYNC_BITS,                /* The bits to wait for - these bits are set by the other tasks that take part in the sync. */\r
+                                                       portMAX_DELAY );                /* The maximum time to wait for the sync condition to be met. */\r
 \r
-               if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* A sync with a max delay should only exit when all the synchronise\r
+       bits are set...check that is the case. */\r
+       if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Ensure the other task is still in the blocked state. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* ...but now the sync bits should be clear again. */\r
+       if( xEventGroupGetBits( xEventGroup ) != 0 )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Now also set ebBIT_1, which should unblock the other task, which will\r
-               then suspend itself. */\r
-               xEventGroupSetBits( xEventBits, ebBIT_1 );\r
 \r
-               /* Ensure the other task is suspended. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* The other tasks should now all be suspended again, ready for the next\r
+       synchronisation. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* The other task should not have cleared the bits - so all the bits\r
-               should still be set. */\r
-               if( xEventGroupSetBits( xEventBits, 0x00 ) != ebALL_BITS )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Clear ebBIT_1 again. */\r
-               if( xEventGroupClearBits( xEventBits, ebBIT_1 ) != ebALL_BITS )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Resume the other task - which will wait on all the ebCOMBINED_BITS\r
-               again - this time clearing the bits when it is unblocked. */\r
-               vTaskResume( xWaitBitsTaskHandle );\r
 \r
-               /* Ensure the other task is blocked once again. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Sync again - but this time set the last necessary bit as the\r
+       highest priority task, rather than the lowest priority task.  Unsuspend\r
+       the other tasks then check they have executed up to the synchronisation\r
+       point. */\r
+       vTaskResume( xTestSlaveTaskHandle );\r
+       vTaskResume( xSyncTask1 );\r
+       vTaskResume( xSyncTask2 );\r
 \r
-               /* Set the bit the other task is waiting for. */\r
-               xEventGroupSetBits( xEventBits, ebBIT_1 );\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Ensure the other task is suspended once again. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* The other task should have cleared the bits in ebCOMBINED_BITS.\r
-               Clear the remaining bits. */\r
-               uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
+       if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Raise the priority of this task above that of the other tasks. */\r
+       vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 );\r
 \r
-               /* Clear all bits ready for the sync with the other three tasks.  The\r
-               value returned is the value prior to the bits being cleared. */\r
-               if( xEventGroupClearBits( xEventBits, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Set this task's sync bit. */\r
+       uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
 \r
-               /* The bits should be clear now. */\r
-               if( xEventGroupGetBits( xEventBits ) != 0x00 )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* A sync with a max delay should only exit when all the synchronisation\r
+       bits are set... */\r
+       if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Check the other three tasks are suspended. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* ...but now the sync bits should be clear again. */\r
+       if( xEventGroupGetBits( xEventGroup ) != 0 )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
 \r
-               if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* The other tasks should now all be in the ready state again, but not\r
+       executed yet as this task still has a higher relative priority. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eReady )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Unsuspend the other tasks then check they have executed up to the\r
-               synchronisation point. */\r
-               vTaskResume( xWaitBitsTaskHandle );\r
-               vTaskResume( xSyncTask1 );\r
-               vTaskResume( xSyncTask2 );\r
+       if( eTaskGetState( xSyncTask1 ) != eReady )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask2 ) != eReady )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
 \r
-               if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Reset the priority of this task back to its original value. */\r
+       vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );\r
 \r
-               /* Set this task's sync bit. */\r
-               uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
+       /* Now all the other tasks should have reblocked on the event bits\r
+       to test the behaviour when the event bits are deleted. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* A sync with a max delay should only exit when all the synchronise\r
-               bits are set... */\r
-               if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* ...but now the sync bits should be clear again. */\r
-               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
+       return xError;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-               /* The other tasks should now all be suspended again, ready for the next\r
-               synchronisation. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )\r
+{\r
+EventBits_t uxBits;\r
 \r
-               if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Resume the other task.  It will block, pending a single bit from\r
+       within ebCOMBINED_BITS. */\r
+       vTaskResume( xTestSlaveTaskHandle );\r
 \r
-               if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+       /* Ensure the other task is blocked on the task. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only\r
+       blocked waiting for one of them. */\r
+       xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS );\r
+\r
+       /* The 'test slave' task should now have executed, clearing ebBIT_1 (the\r
+       bit it was blocked on), then re-entered the Blocked state to wait for\r
+       all the other bits in ebCOMBINED_BITS to be set again.  First check\r
+       ebBIT_1 is clear. */\r
+       uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
+\r
+       if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Ensure the other task is still in the blocked state. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Set all the bits other than ebBIT_1 - which is the bit that must be\r
+       set before the other task unblocks. */\r
+       xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 );\r
+\r
+       /* Ensure all the expected bits are still set. */\r
+       uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
+\r
+       if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Ensure the other task is still in the blocked state. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Now also set ebBIT_1, which should unblock the other task, which will\r
+       then suspend itself. */\r
+       xEventGroupSetBits( xEventGroup, ebBIT_1 );\r
+\r
+       /* Ensure the other task is suspended. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* The other task should not have cleared the bits - so all the bits\r
+       should still be set. */\r
+       if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Clear ebBIT_1 again. */\r
+       if( xEventGroupClearBits( xEventGroup, ebBIT_1 ) != ebALL_BITS )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Resume the other task - which will wait on all the ebCOMBINED_BITS\r
+       again - this time clearing the bits when it is unblocked. */\r
+       vTaskResume( xTestSlaveTaskHandle );\r
+\r
+       /* Ensure the other task is blocked once again. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Set the bit the other task is waiting for. */\r
+       xEventGroupSetBits( xEventGroup, ebBIT_1 );\r
+\r
+       /* Ensure the other task is suspended once again. */\r
+       if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* The other task should have cleared the bits in ebCOMBINED_BITS.\r
+       Clear the remaining bits. */\r
+       uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );\r
+\r
+       if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* Clear all bits ready for the sync with the other three tasks.  The\r
+       value returned is the value prior to the bits being cleared. */\r
+       if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       /* The bits should be clear now. */\r
+       if( xEventGroupGetBits( xEventGroup ) != 0x00 )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+       return xError;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSelectiveBitsTestSlaveFunction( void )\r
+{\r
+EventBits_t uxPendBits, uxReturned;\r
+\r
+       /* Used in a test that blocks two tasks on various different bits within an\r
+       event group - then sets each bit in turn and checks that the correct tasks\r
+       unblock at the correct times.\r
+\r
+       This function is called by two different tasks - each of which will use a\r
+       different bit.  Check the task handle to see which task the function was\r
+       called by. */\r
+       if( xTaskGetCurrentTaskHandle() == xSyncTask1 )\r
+       {\r
+               uxPendBits = ebSELECTIVE_BITS_1;\r
+       }\r
+       else\r
+       {\r
+               uxPendBits = ebSELECTIVE_BITS_2;\r
+       }\r
+\r
+       for( ;; )\r
+       {\r
+               /* Wait until it is time to perform the next cycle of the test.  The\r
+               task is unsuspended by the tests implemented in the\r
+               prvSelectiveBitsTestMasterFunction() function. */\r
+               vTaskSuspend( NULL );\r
+               uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );\r
+\r
+               if( uxReturned == ( EventBits_t ) 0 )\r
                {\r
-                       xError = pdTRUE;\r
+                       break;\r
                }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvSelectiveBitsTestMasterFunction( void )\r
+{\r
+BaseType_t xError = pdFALSE;\r
+EventBits_t uxBit;\r
+\r
+       /* Used in a test that blocks two tasks on various different bits within an\r
+       event group - then sets each bit in turn and checks that the correct tasks\r
+       unblock at the correct times.  The two other tasks (xSyncTask1 and\r
+       xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in\r
+       this test.\r
+\r
+       Both other tasks should start in the suspended state. */\r
+       if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
+       if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+       {\r
+               xError = pdTRUE;\r
+       }\r
 \r
-               /* Sync again - but this time set the last necessary bit as the\r
-               highest priority task, rather than the lowest priority task.  Unsuspend\r
-               the other tasks then check they have executed up to the synchronisation\r
-               point. */\r
-               vTaskResume( xWaitBitsTaskHandle );\r
+       /* Test each bit in the byte individually. */\r
+       for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 )\r
+       {\r
+               /* Resume both tasks. */\r
                vTaskResume( xSyncTask1 );\r
                vTaskResume( xSyncTask2 );\r
 \r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
-\r
+               /* Now both tasks should be blocked on the event group. */\r
                if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
                {\r
                        xError = pdTRUE;\r
@@ -752,117 +910,158 @@ xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;
                        xError = pdTRUE;\r
                }\r
 \r
-               /* Raise the priority of this task above that of the other tasks. */\r
-               vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 );\r
-\r
-               /* Set this task's sync bit. */\r
-               uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\r
+               /* Set one bit. */\r
+               xEventGroupSetBits( xEventGroup, uxBit );\r
 \r
-               /* A sync with a max delay should only exit when all the synchronisation\r
-               bits are set... */\r
-               if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
+               /* Is the bit set in the first set of selective bits?  If so the first\r
+               sync task should have unblocked and returned to the suspended state. */\r
+               if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )\r
                {\r
-                       xError = pdTRUE;\r
+                       /* Task should not have unblocked. */\r
+                       if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+                       {\r
+                               xError = pdTRUE;\r
+                       }\r
                }\r
-\r
-               /* ...but now the sync bits should be clear again. */\r
-               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
+               else\r
                {\r
-                       xError = pdTRUE;\r
+                       /* Task should have unblocked and returned to the suspended state. */\r
+                       if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+                       {\r
+                               xError = pdTRUE;\r
+                       }\r
                }\r
 \r
-\r
-               /* The other tasks should now all be in the ready state again, but not\r
-               executed yet as this task still has a higher relative priority. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eReady )\r
+               /* Same checks for the second sync task. */\r
+               if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 )\r
                {\r
-                       xError = pdTRUE;\r
+                       /* Task should not have unblocked. */\r
+                       if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+                       {\r
+                               xError = pdTRUE;\r
+                       }\r
                }\r
-\r
-               if( eTaskGetState( xSyncTask1 ) != eReady )\r
+               else\r
                {\r
-                       xError = pdTRUE;\r
+                       /* Task should have unblocked and returned to the suspended state. */\r
+                       if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+                       {\r
+                               xError = pdTRUE;\r
+                       }\r
                }\r
+       }\r
 \r
-               if( eTaskGetState( xSyncTask2 ) != eReady )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Ensure both tasks are blocked on the event group again, then delete the\r
+       event group so the other tasks leave this portion of the test. */\r
+       vTaskResume( xSyncTask1 );\r
+       vTaskResume( xSyncTask2 );\r
 \r
+       /* Deleting the event group is the signal that the two other tasks should\r
+       leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main\r
+       part of their functionality. */\r
+       vEventGroupDelete( xEventGroup );\r
 \r
-               /* Reset the priority of this task back to its original value. */\r
-               vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );\r
+       return xError;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-               /* Now all the other tasks should have reblocked on the event bits\r
-               to test the behaviour when the event bits are deleted. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+void vPeriodicEventGroupsProcessing( void )\r
+{\r
+static BaseType_t xCallCount = 0, xISRTestError = pdFALSE;\r
+const BaseType_t xSetBitCount = 100, xGetBitsCount = 200, xClearBitsCount = 300;\r
+const EventBits_t uxBitsToSet = 0x12U;\r
+EventBits_t uxReturned;\r
+BaseType_t xMessagePosted;\r
 \r
-               if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Called periodically from the tick hook to exercise the "FromISR"\r
+       functions. */\r
 \r
-               if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
-               {\r
-                       xError = pdTRUE;\r
-               }\r
+       /* Check the even group tasks were actually created. */\r
+       configASSERT( xISREventGroup );\r
 \r
-               /* Delete the event group. */\r
-               vEventGroupDelete( xEventBits );\r
+       xCallCount++;\r
 \r
-               /* Now all the other tasks should have completed and suspended\r
-               themselves ready for the next go around the loop. */\r
-               if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )\r
+       if( xCallCount == xSetBitCount )\r
+       {\r
+               /* All the event bits should start clear. */\r
+               uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );\r
+               if( uxReturned != 0x00 )\r
                {\r
-                       xError = pdTRUE;\r
+                       xISRTestError = pdTRUE;\r
                }\r
-\r
-               if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+               else\r
                {\r
-                       xError = pdTRUE;\r
+                       /* Set the bits.  This is called from the tick hook so it is not\r
+                       necessary to use the last parameter to ensure a context switch\r
+                       occurs immediately. */\r
+                       xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL );\r
+                       if( xMessagePosted != pdPASS )\r
+                       {\r
+                               xISRTestError = pdTRUE;\r
+                       }\r
                }\r
-\r
-               if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+       }\r
+       else if( xCallCount == xGetBitsCount )\r
+       {\r
+               /* Check the bits were set as expected. */\r
+               uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );\r
+               if( uxReturned != uxBitsToSet )\r
                {\r
-                       xError = pdTRUE;\r
+                       xISRTestError = pdTRUE;\r
                }\r
+       }\r
+       else if( xCallCount == xClearBitsCount )\r
+       {\r
+               /* Clear the bits again. */\r
+               uxReturned = ( EventBits_t ) xEventGroupClearBitsFromISR( xISREventGroup, uxBitsToSet );\r
 \r
+               /* Check the message was posted. */\r
+               if( uxReturned != pdPASS )\r
+               {\r
+                       xISRTestError = pdTRUE;\r
+               }\r
 \r
-               /* Recreate the event group ready for the next cycle. */\r
-               xEventBits = xEventGroupCreate();\r
-               configASSERT( xEventBits );\r
+               /* Go back to the start. */\r
+               xCallCount = 0;\r
 \r
-               if( xError == pdFALSE )\r
+               /* If no errors have been detected then increment the count of test\r
+               cycles. */\r
+               if( xISRTestError == pdFALSE )\r
                {\r
-                       ulSetBitCycles++;\r
+                       ulISRCycles++;\r
                }\r
-\r
-               configASSERT( xError == pdFALSE );\r
+       }\r
+       else\r
+       {\r
+               /* Nothing else to do. */\r
        }\r
 }\r
-/*-----------------------------------------------------------*/\r
 \r
+/*-----------------------------------------------------------*/\r
 /* This is called to check that all the created tasks are still running. */\r
-portBASE_TYPE xAreEventBitTasksStillRunning( void )\r
+BaseType_t xAreEventGroupTasksStillRunning( void )\r
 {\r
-static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;\r
-portBASE_TYPE xStatus = pdPASS;\r
+static uint32_t ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0, ulPreviousISRCycles = 0;\r
+BaseType_t xStatus = pdPASS;\r
 \r
        /* Check the tasks are still cycling without finding any errors. */\r
-       if( ulPreviousSetBitCycles == ulSetBitCycles )\r
+       if( ulPreviousSetBitCycles == ulTestMasterCycles )\r
+       {\r
+               xStatus = pdFAIL;\r
+       }\r
+       ulPreviousSetBitCycles = ulTestMasterCycles;\r
+\r
+       if( ulPreviousWaitBitCycles == ulTestSlaveCycles )\r
        {\r
                xStatus = pdFAIL;\r
        }\r
-       ulPreviousSetBitCycles = ulSetBitCycles;\r
+       ulPreviousWaitBitCycles = ulTestSlaveCycles;\r
 \r
-       if( ulPreviousWaitBitCycles == ulWaitBitCycles )\r
+       if( ulPreviousISRCycles == ulISRCycles )\r
        {\r
                xStatus = pdFAIL;\r
        }\r
-       ulPreviousWaitBitCycles = ulWaitBitCycles;\r
+       ulPreviousISRCycles = ulISRCycles;\r
 \r
        return xStatus;\r
 }\r