]> git.sur5r.net Git - freertos/commitdiff
Add event groups test/demo tasks.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 21 Nov 2013 22:08:06 +0000 (22:08 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 21 Nov 2013 22:08:06 +0000 (22:08 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2113 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c [new file with mode: 0644]
FreeRTOS/Demo/Common/include/EventGroupsDemo.h [new file with mode: 0644]

diff --git a/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
new file mode 100644 (file)
index 0000000..abbf069
--- /dev/null
@@ -0,0 +1,871 @@
+/*\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
+\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
+\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "event_groups.h"\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 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
+/* Associate a bit to each task.  These bits are used to identify all the tasks\r
+that synchronise with the xEventGroupSync() function. */\r
+#define ebSET_BIT_TASK_SYNC_BIT                        ebBIT_0\r
+#define ebWAIT_BIT_TASK_SYNC_BIT               ebBIT_1\r
+#define ebRENDESVOUS_TASK_1_SYNC_BIT   ebBIT_2\r
+#define ebRENDESVOUS_TASK_2_SYNC_BIT   ebBIT_3\r
+#define ebALL_SYNC_BITS ( ebSET_BIT_TASK_SYNC_BIT | ebWAIT_BIT_TASK_SYNC_BIT | ebRENDESVOUS_TASK_1_SYNC_BIT | ebRENDESVOUS_TASK_2_SYNC_BIT )\r
+\r
+/* A block time of zero simply means "don't block". */\r
+#define ebDONT_BLOCK   ( 0 )\r
+\r
+/* A 5ms delay. */\r
+#define ebSHORT_DELAY  ( 5 / portTICK_RATE_MS )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The primary task that manages and controls all the behavioural tests.\r
+ */\r
+static void prvSetBitsTask( void *pvParameters );\r
+\r
+/*\r
+ * The task that participates in most of the non 'single task' tests performed\r
+ * by prvSetBitsTask().\r
+ */\r
+static void prvWaitBitsTask( void *pvParameters );\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
+ */\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
+ */\r
+static portBASE_TYPE prvSingleTaskTests( 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
+\r
+/* The event group used by all the tests. */\r
+static xEventGroupHandle xEventBits = NULL;\r
+\r
+/* Handles to the tasks that only take part in the synchronisation calls. */\r
+static xTaskHandle xSyncTask1 = NULL, xSyncTask2 = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartEventBitTasks( void )\r
+{\r
+xTaskHandle xWaitBitsTaskHandle;\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
+\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
+\r
+       /* If the last task was created then the others will have been too. */\r
+       configASSERT( xSyncTask2 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portBASE_TYPE prvSingleTaskTests( void )\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
+\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
+\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
+\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
+\r
+       if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )\r
+       {\r
+               /* Blocked, but didn't expect to. */\r
+               xError = pdTRUE;\r
+       }\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
+       {\r
+               xError = pdTRUE;\r
+       }\r
+\r
+\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
+\r
+       if( uxReturned != 0x00 )\r
+       {\r
+               /* Expected all bits to be clear. */\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
+\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
+\r
+       /* Is the bit set? */\r
+       uxReturned = xEventGroupGetBits( xEventBits );\r
+\r
+       if( uxReturned != ebBIT_3 )\r
+       {\r
+               /* Expected all bits to be clear. */\r
+               xError = pdTRUE;\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
+\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
+\r
+       for( ;; )\r
+       {\r
+               /* Wait until the 'set bit' task unsuspends this task. */\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
+               configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );\r
+\r
+               /* Wait until the 'set bit' 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
+               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
+               configASSERT( uxReturned == 0 );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvWaitBitsTask( void *pvParameters )\r
+{\r
+xEventBitsType uxReturned;\r
+portBASE_TYPE 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
+               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
+               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
+\r
+               /* Were all the bits set? */\r
+               if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               /* Suspend again to wait for the 'set bit' 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
+                                                                        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
+               if( uxReturned != ebALL_BITS )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\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
+\r
+               /* A sync with a max delay should only exit when all the synchronisation\r
+               bits are set... */\r
+               if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               /* ...but now the synchronisation bits should be clear again. */\r
+               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( xError == pdFALSE )\r
+               {\r
+                       /* This task is still cycling without finding an error. */\r
+                       ulWaitBitCycles++;\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
+\r
+               /* A sync with a max delay should only exit when all the synchronisation\r
+               bits are set... */\r
+               if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )\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
+\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
+\r
+               if( uxReturned != 0 )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( xError == pdFALSE )\r
+               {\r
+                       /* This task is still cycling without finding an error. */\r
+                       ulWaitBitCycles++;\r
+               }\r
+\r
+               configASSERT( xError == pdFALSE );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetBitsTask( void *pvParameters )\r
+{\r
+xEventBitsType uxBits;\r
+portBASE_TYPE xError;\r
+\r
+/* The handle to the other task is passed in as the task parameter. */\r
+xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;\r
+\r
+       /* Avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       xError = prvSingleTaskTests();\r
+\r
+       for( ;; )\r
+       {\r
+               /* Resume the other task.  It will block, pending a single bit from\r
+               within ebCOMBINED_BITS. */\r
+               vTaskResume( xWaitBitsTaskHandle );\r
+\r
+               /* Ensure the other task is blocked on the task. */\r
+               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\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
+\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
+\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( xWaitBitsTaskHandle ) != 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
+\r
+               /* Ensure all the expected bits are still set. */\r
+               uxBits = xEventGroupWaitBits( xEventBits, 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( xWaitBitsTaskHandle ) != 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( xEventBits, ebBIT_1 );\r
+\r
+               /* Ensure the other task is suspended. */\r
+               if( eTaskGetState( xWaitBitsTaskHandle ) != 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
+\r
+               /* Clear ebBIT_1 again. */\r
+               if( xEventGroupClearBits( xEventBits, 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( xWaitBitsTaskHandle );\r
+\r
+               /* Ensure the other task is blocked once again. */\r
+               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               /* Set the bit the other task is waiting for. */\r
+               xEventGroupSetBits( xEventBits, ebBIT_1 );\r
+\r
+               /* Ensure the other task is suspended once again. */\r
+               if( eTaskGetState( xWaitBitsTaskHandle ) != 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( xEventBits, 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( xEventBits, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               /* The bits should be clear now. */\r
+               if( xEventGroupGetBits( xEventBits ) != 0x00 )\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
+\r
+               if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( eTaskGetState( xSyncTask2 ) != eSuspended )\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
+\r
+               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\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
+\r
+               /* Set this task's sync bit. */\r
+               uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );\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
+\r
+               /* ...but now the sync bits should be clear again. */\r
+               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
+               {\r
+                       xError = pdTRUE;\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
+\r
+               if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( eTaskGetState( xSyncTask2 ) != eSuspended )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\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
+               vTaskResume( xSyncTask1 );\r
+               vTaskResume( xSyncTask2 );\r
+\r
+               if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )\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
+\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
+\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
+               /* ...but now the sync bits should be clear again. */\r
+               if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )\r
+               {\r
+                       xError = pdTRUE;\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
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( eTaskGetState( xSyncTask1 ) != eReady )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( eTaskGetState( xSyncTask2 ) != eReady )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+\r
+               /* Reset the priority of this task back to its original value. */\r
+               vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );\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
+\r
+               if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+               {\r
+                       xError = pdTRUE;\r
+               }\r
+\r
+               /* Delete the event group. */\r
+               vEventGroupDelete( xEventBits );\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
+               {\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
+\r
+\r
+               /* Recreate the event group ready for the next cycle. */\r
+               xEventBits = xEventGroupCreate();\r
+               configASSERT( xEventBits );\r
+\r
+               if( xError == pdFALSE )\r
+               {\r
+                       ulSetBitCycles++;\r
+               }\r
+\r
+               configASSERT( xError == pdFALSE );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+portBASE_TYPE xAreEventBitTasksStillRunning( void )\r
+{\r
+static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;\r
+portBASE_TYPE xStatus = pdPASS;\r
+\r
+       /* Check the tasks are still cycling without finding any errors. */\r
+       if( ulPreviousSetBitCycles == ulSetBitCycles )\r
+       {\r
+               xStatus = pdFAIL;\r
+       }\r
+       ulPreviousSetBitCycles = ulSetBitCycles;\r
+\r
+       if( ulPreviousWaitBitCycles == ulWaitBitCycles )\r
+       {\r
+               xStatus = pdFAIL;\r
+       }\r
+       ulPreviousWaitBitCycles = ulWaitBitCycles;\r
+\r
+       return xStatus;\r
+}\r
+\r
+\r
+\r
diff --git a/FreeRTOS/Demo/Common/include/EventGroupsDemo.h b/FreeRTOS/Demo/Common/include/EventGroupsDemo.h
new file mode 100644 (file)
index 0000000..390c83e
--- /dev/null
@@ -0,0 +1,81 @@
+/*\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
+\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
+#ifndef EVENT_GROUPS_DEMO_H\r
+#define EVENT_GROUPS_DEMO_H\r
+\r
+void vStartEventBitTasks( void );\r
+portBASE_TYPE xAreEventBitTasksStillRunning( void );\r
+\r
+#endif /* EVENT_GROUPS_DEMO_H */\r
+\r