summaryrefslogtreecommitdiff
path: root/FreeRTOS
diff options
context:
space:
mode:
authorRichard Barry <ribarry@amazon.com>2013-11-21 22:08:06 +0000
committerRichard Barry <ribarry@amazon.com>2013-11-21 22:08:06 +0000
commita22d5ff5a57ca4e4e42d4157ed39ef5a21cca578 (patch)
tree74ba8e96d5d2c80d325a7f0bd0f640139f0c9766 /FreeRTOS
parentf54f21b8f60a4cc36a871b595ab5924df0e1ab62 (diff)
downloadfreertos-git-a22d5ff5a57ca4e4e42d4157ed39ef5a21cca578.tar.gz
Add event groups test/demo tasks.
Diffstat (limited to 'FreeRTOS')
-rw-r--r--FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c871
-rw-r--r--FreeRTOS/Demo/Common/include/EventGroupsDemo.h81
2 files changed, 952 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
new file mode 100644
index 000000000..abbf06991
--- /dev/null
+++ b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
@@ -0,0 +1,871 @@
+/*
+ FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+
+/*
+ * This file contains fairly comprehensive checks on the behaviour of event
+ * groups. It is not intended to be a user friendly demonstration of the event
+ * groups API.
+ */
+
+
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "event_groups.h"
+
+/* Priorities used by the tasks. */
+#define ebSET_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY )
+#define ebWAIT_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
+
+/* Generic bit definitions. */
+#define ebBIT_0 ( 0x01UL )
+#define ebBIT_1 ( 0x02UL )
+#define ebBIT_2 ( 0x04UL )
+#define ebBIT_3 ( 0x08UL )
+#define ebBIT_4 ( 0x10UL )
+#define ebBIT_5 ( 0x20UL )
+#define ebBIT_6 ( 0x40UL )
+#define ebBIT_7 ( 0x80UL )
+
+/* Combinations of bits used in the tests. */
+#define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 )
+#define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )
+
+/* Associate a bit to each task. These bits are used to identify all the tasks
+that synchronise with the xEventGroupSync() function. */
+#define ebSET_BIT_TASK_SYNC_BIT ebBIT_0
+#define ebWAIT_BIT_TASK_SYNC_BIT ebBIT_1
+#define ebRENDESVOUS_TASK_1_SYNC_BIT ebBIT_2
+#define ebRENDESVOUS_TASK_2_SYNC_BIT ebBIT_3
+#define ebALL_SYNC_BITS ( ebSET_BIT_TASK_SYNC_BIT | ebWAIT_BIT_TASK_SYNC_BIT | ebRENDESVOUS_TASK_1_SYNC_BIT | ebRENDESVOUS_TASK_2_SYNC_BIT )
+
+/* A block time of zero simply means "don't block". */
+#define ebDONT_BLOCK ( 0 )
+
+/* A 5ms delay. */
+#define ebSHORT_DELAY ( 5 / portTICK_RATE_MS )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The primary task that manages and controls all the behavioural tests.
+ */
+static void prvSetBitsTask( void *pvParameters );
+
+/*
+ * The task that participates in most of the non 'single task' tests performed
+ * by prvSetBitsTask().
+ */
+static void prvWaitBitsTask( void *pvParameters );
+
+/*
+ * Two instances of prvSyncTask() are created. Their only purpose is to
+ * participate in synchronisations and test the behaviour when an event group on
+ * which they are blocked is deleted.
+ */
+static void prvSyncTask( void *pvParameters );
+
+/*
+ * Contains a set of behavioural tests that can be performed from a single task.
+ * This function is called by prvSetBitsTask() before prvSetBitsTasks() starts
+ * the tests that make use of the prvWaitBitsTask().
+ */
+static portBASE_TYPE prvSingleTaskTests( void );
+
+/*-----------------------------------------------------------*/
+
+/* Variables that are incremented by the tasks on each cycle provided no errors
+have been found. Used to detect an error or stall in the test cycling. */
+static volatile unsigned long ulSetBitCycles = 0, ulWaitBitCycles = 0;
+
+/* The event group used by all the tests. */
+static xEventGroupHandle xEventBits = NULL;
+
+/* Handles to the tasks that only take part in the synchronisation calls. */
+static xTaskHandle xSyncTask1 = NULL, xSyncTask2 = NULL;
+
+/*-----------------------------------------------------------*/
+
+void vStartEventBitTasks( void )
+{
+xTaskHandle xWaitBitsTaskHandle;
+
+ /*
+ * This file contains fairly comprehensive checks on the behaviour of event
+ * groups. It is not intended to be a user friendly demonstration of the
+ * event groups API.
+ */
+
+ /* Create the event bits that will be used by the tasks. */
+ xEventBits = xEventGroupCreate();
+ configASSERT( xEventBits );
+
+ xTaskCreate( prvWaitBitsTask, ( signed char * ) "WaitO", configMINIMAL_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xWaitBitsTaskHandle );
+ xTaskCreate( prvSetBitsTask, ( signed char * ) "SetB", configMINIMAL_STACK_SIZE, ( void * ) xWaitBitsTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL );
+ xTaskCreate( prvSyncTask, ( signed char * ) "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );
+ xTaskCreate( prvSyncTask, ( signed char * ) "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 );
+
+ /* If the last task was created then the others will have been too. */
+ configASSERT( xSyncTask2 );
+}
+/*-----------------------------------------------------------*/
+
+static portBASE_TYPE prvSingleTaskTests( void )
+{
+xEventBitsType uxReturned;
+portBASE_TYPE xError = pdFALSE, xHigherPriorityTaskWoken;
+portTickType xTimeOnEntering, xTimeOnExiting;
+
+ /* Check no bits are currently set. */
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event flags being tested. */
+ ebBIT_1, /* The bit being tested. */
+ pdFALSE, /* Don't clear the bit on exit. */
+ pdFALSE, /* Wait for a single bit, not all the bits. */
+ ebDONT_BLOCK ); /* Block time. */
+
+ if( uxReturned != 0x00 )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Set selected bits. */
+ xEventGroupSetBits( xEventBits, ebCOMBINED_BITS );
+
+ /* Wait on all the selected bits. This should return immediately even
+ though a block time is specified. */
+ uxReturned = xEventGroupWaitBits( xEventBits, ebCOMBINED_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
+
+ if( uxReturned != ebCOMBINED_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Now try waiting on all the selected bits plus a bit that is not set.
+ This should time out. */
+ xTimeOnEntering = xTaskGetTickCount();
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event flags being tested. */
+ ebCOMBINED_BITS | ebBIT_0, /* The bits being tested. */
+ pdFALSE, /* Don't clear the bits on exit. */
+ pdTRUE, /* Wait for all the bits to be set, not just a single bit. */
+ ebSHORT_DELAY ); /* Block time. */
+ xTimeOnExiting = xTaskGetTickCount();
+
+ if( ( xTimeOnExiting - xTimeOnEntering ) < ebSHORT_DELAY )
+ {
+ /* Did not block as expected. */
+ xError = pdTRUE;
+ }
+
+ if( uxReturned != ebCOMBINED_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* This time pass in the same bit combination, but wait for only a single
+ bit. This time it should not block even though one of the bits in the
+ combination is not set. */
+ xTimeOnEntering = xTaskGetTickCount();
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event flags being tested. */
+ ebCOMBINED_BITS | ebBIT_0, /* The bits being tested. */
+ pdFALSE, /* Don't clear the bits on exit. */
+ pdFALSE, /* Don't wait for all the bits to be set, a single bit is all that is required. */
+ ebSHORT_DELAY ); /* Block time. */
+ xTimeOnExiting = xTaskGetTickCount();
+
+ if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )
+ {
+ /* Blocked, but didn't expect to. */
+ xError = pdTRUE;
+ }
+
+ if( uxReturned != ebCOMBINED_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* Now set all the bits. */
+ xEventGroupSetBits( xEventBits, ebALL_BITS );
+
+ /* Read the bits back to ensure they are all set. Read back with a timeout
+ to ensure the task does not block (all the bits are already set), and leave
+ the bits set on exit. */
+ xTimeOnEntering = xTaskGetTickCount();
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event flags being tested. */
+ ebALL_BITS, /* The bits being tested. */
+ pdFALSE, /* Don't clear the bits on exit. */
+ pdTRUE, /* Wait for all the bits to be set. */
+ ebSHORT_DELAY );/* Block time. */
+ xTimeOnExiting = xTaskGetTickCount();
+
+ if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )
+ {
+ /* Blocked, but didn't expect to. */
+ xError = pdTRUE;
+ }
+
+ if( uxReturned != ebALL_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* Now wait for some bits to be set (which are all set), and clear the bits
+ on exit. Again this should not block. */
+ xTimeOnEntering = xTaskGetTickCount();
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event flags being tested. */
+ ebCOMBINED_BITS, /* The bits being tested, which are a subset of the bits now set. */
+ pdTRUE, /* Clear the bits on exit. */
+ pdTRUE, /* Wait for all the bits to be set (which they already are. */
+ ebSHORT_DELAY ); /* Block time. */
+ xTimeOnExiting = xTaskGetTickCount();
+
+ if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )
+ {
+ /* Blocked, but didn't expect to. */
+ xError = pdTRUE;
+ }
+
+ if( uxReturned != ebALL_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Now the bits set by the ebCOMBINED_BITS constant should be clear, but
+ all the other bits should be set. Call xEventGroupWaitBits() again, this time
+ waiting for any bit within ebALL_BITS, and clearing all bits on exit to
+ leave the event bits all clear again. */
+ xTimeOnEntering = xTaskGetTickCount();
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event flags being tested. */
+ ebALL_BITS, /* The bits being tested, which are a subset of the bits now set. */
+ pdTRUE, /* Clear the bits on exit. */
+ pdFALSE, /* Wait for any bit to be set. */
+ ebSHORT_DELAY ); /* Block time. */
+ xTimeOnExiting = xTaskGetTickCount();
+
+ if( ( xTimeOnExiting - xTimeOnEntering ) >= ebSHORT_DELAY )
+ {
+ /* Blocked, but didn't expect to. */
+ xError = pdTRUE;
+ }
+
+ /* The bits defined in ebCOMBINED_BITS were already cleared, so this time
+ only the remaining bits should have been set. */
+ if( uxReturned != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
+ {
+ xError = pdTRUE;
+ }
+
+
+
+ /* All the bits should be clear again as the last call to xEventGroupWaitBits()
+ had the "clear on exit" parameter set to pdTRUE. */
+ uxReturned = xEventGroupGetBits( xEventBits );
+
+ if( uxReturned != 0x00 )
+ {
+ /* Expected all bits to be clear. */
+ xError = pdTRUE;
+ }
+
+ /* Try the 'set from ISR' function, which will pend the set to the timer
+ daemon task. */
+ xHigherPriorityTaskWoken = pdFALSE;
+ if( xEventGroupSetBitsFromISR( xEventBits, ebBIT_3, &xHigherPriorityTaskWoken ) != pdPASS )
+ {
+ xError = pdTRUE;
+ }
+
+ if( xHigherPriorityTaskWoken == pdTRUE )
+ {
+ /* If the daemon task has a higher priority then a yield should be
+ performed to ensure it runs before the bits are tested. */
+ taskYIELD();
+ }
+
+ /* Is the bit set? */
+ uxReturned = xEventGroupGetBits( xEventBits );
+
+ if( uxReturned != ebBIT_3 )
+ {
+ /* Expected all bits to be clear. */
+ xError = pdTRUE;
+ }
+
+ /* Clear all bits again ready for infinite loop tests. */
+ xEventGroupClearBits( xEventBits, ebALL_BITS );
+
+ return xError;
+}
+/*-----------------------------------------------------------*/
+
+static void prvSyncTask( void *pvParameters )
+{
+xEventBitsType uxSynchronisationBit, uxReturned;
+
+ /* The bit to use to indicate this task is at the synchronisation point is
+ passed in as the task parameter. */
+ uxSynchronisationBit = ( xEventBitsType ) pvParameters;
+
+ for( ;; )
+ {
+ /* Wait until the 'set bit' task unsuspends this task. */
+ vTaskSuspend( NULL );
+
+ /* Set the bit that indicates this task is at the synchronisation
+ point. The first time this is done the 'set bit' task has a lower
+ priority than this task. */
+ uxReturned = xEventGroupSync( xEventBits, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );
+ configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
+
+ /* Wait until the 'set bit' task unsuspends this task again. */
+ vTaskSuspend( NULL );
+
+ /* Set the bit that indicates this task is at the synchronisation
+ point again. This time the 'set bit' task has a higher priority than
+ this task. */
+ uxReturned = xEventGroupSync( xEventBits, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );
+ configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
+
+ /* Block on the event group again. This time the event group is going
+ to be deleted, so 0 should be returned. */
+ uxReturned = xEventGroupWaitBits( xEventBits, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
+ configASSERT( uxReturned == 0 );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvWaitBitsTask( void *pvParameters )
+{
+xEventBitsType uxReturned;
+portBASE_TYPE xError = pdFALSE;
+
+ /* Avoid compiler warnings. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* This task is controller by the prvSetBitsTask(). Suspend until resumed
+ by prvSetBitsTask(). */
+ vTaskSuspend( NULL );
+
+ /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get
+ set. Clear the bit on exit. */
+ uxReturned = xEventGroupWaitBits( xEventBits, /* The event bits being queried. */
+ ebBIT_1, /* The bit to wait for. */
+ pdTRUE, /* Clear the bit on exit. */
+ pdTRUE, /* Wait for all the bits (only one in this case anyway. */
+ portMAX_DELAY );
+
+ /* Should unblock after the 'set bit' task has set all the bits in the
+ ebCOMBINED_BITS constant, therefore ebCOMBINED_BITS is what should have
+ been returned. */
+ if( uxReturned != ebCOMBINED_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Now call xEventGroupWaitBits() again, this time waiting for all the bits
+ in ebCOMBINED_BITS to be set. This call should block until the 'set
+ bits' task sets ebBIT_1 - which was the bit cleared in the call to
+ xEventGroupWaitBits() above. */
+ uxReturned = xEventGroupWaitBits( xEventBits,
+ ebCOMBINED_BITS, /* The bits being waited on. */
+ pdFALSE, /* Don't clear the bits on exit. */
+ pdTRUE, /* All the bits must be set to unblock. */
+ portMAX_DELAY );
+
+ /* Were all the bits set? */
+ if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Suspend again to wait for the 'set bit' task. */
+ vTaskSuspend( NULL );
+
+ /* Now call xEventGroupWaitBits() again, again waiting for all the bits in
+ ebCOMBINED_BITS to be set, but this time clearing the bits when the task
+ is unblocked. */
+ uxReturned = xEventGroupWaitBits( xEventBits,
+ ebCOMBINED_BITS, /* The bits being waited on. */
+ pdTRUE, /* Clear the bits on exit. */
+ pdTRUE, /* All the bits must be set to unblock. */
+ portMAX_DELAY );
+
+
+ if( uxReturned != ebALL_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ vTaskSuspend( NULL );
+
+ /* Now to synchronise with when 'set bit' task has the lowest
+ priority. */
+ uxReturned = xEventGroupSync( xEventBits, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
+
+ /* A sync with a max delay should only exit when all the synchronisation
+ bits are set... */
+ if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* ...but now the synchronisation bits should be clear again. */
+ if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )
+ {
+ xError = pdTRUE;
+ }
+
+ if( xError == pdFALSE )
+ {
+ /* This task is still cycling without finding an error. */
+ ulWaitBitCycles++;
+ }
+
+ vTaskSuspend( NULL );
+
+ /* This time sync when the 'set bit' task has the highest priority
+ at the point where it sets its sync bit. */
+ uxReturned = xEventGroupSync( xEventBits, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
+
+ /* A sync with a max delay should only exit when all the synchronisation
+ bits are set... */
+ if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* ...but now the sync bits should be clear again. */
+ if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Block on the event group again. This time the event group is going
+ to be deleted, so 0 should be returned. */
+ uxReturned = xEventGroupWaitBits( xEventBits, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
+
+ if( uxReturned != 0 )
+ {
+ xError = pdTRUE;
+ }
+
+ if( xError == pdFALSE )
+ {
+ /* This task is still cycling without finding an error. */
+ ulWaitBitCycles++;
+ }
+
+ configASSERT( xError == pdFALSE );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvSetBitsTask( void *pvParameters )
+{
+xEventBitsType uxBits;
+portBASE_TYPE xError;
+
+/* The handle to the other task is passed in as the task parameter. */
+xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;
+
+ /* Avoid compiler warnings. */
+ ( void ) pvParameters;
+
+ xError = prvSingleTaskTests();
+
+ for( ;; )
+ {
+ /* Resume the other task. It will block, pending a single bit from
+ within ebCOMBINED_BITS. */
+ vTaskResume( xWaitBitsTaskHandle );
+
+ /* Ensure the other task is blocked on the task. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Set all the bits in ebCOMBINED_BITS - the 'wait bits' task is only
+ blocked waiting for one of them. */
+ xEventGroupSetBits( xEventBits, ebCOMBINED_BITS );
+
+ /* The 'wait bits' task should now have executed, clearing ebBIT_1 (the
+ bit it was blocked on), then re-entered the Blocked state to wait for
+ all the other bits in ebCOMBINED_BITS to be set again. First check
+ ebBIT_1 is clear. */
+ uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
+
+ if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Ensure the other task is still in the blocked state. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Set all the bits other than ebBIT_1 - which is the bit that must be
+ set before the other task unblocks. */
+ xEventGroupSetBits( xEventBits, ebALL_BITS & ~ebBIT_1 );
+
+ /* Ensure all the expected bits are still set. */
+ uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
+
+ if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Ensure the other task is still in the blocked state. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Now also set ebBIT_1, which should unblock the other task, which will
+ then suspend itself. */
+ xEventGroupSetBits( xEventBits, ebBIT_1 );
+
+ /* Ensure the other task is suspended. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ /* The other task should not have cleared the bits - so all the bits
+ should still be set. */
+ if( xEventGroupSetBits( xEventBits, 0x00 ) != ebALL_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Clear ebBIT_1 again. */
+ if( xEventGroupClearBits( xEventBits, ebBIT_1 ) != ebALL_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Resume the other task - which will wait on all the ebCOMBINED_BITS
+ again - this time clearing the bits when it is unblocked. */
+ vTaskResume( xWaitBitsTaskHandle );
+
+ /* Ensure the other task is blocked once again. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Set the bit the other task is waiting for. */
+ xEventGroupSetBits( xEventBits, ebBIT_1 );
+
+ /* Ensure the other task is suspended once again. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ /* The other task should have cleared the bits in ebCOMBINED_BITS.
+ Clear the remaining bits. */
+ uxBits = xEventGroupWaitBits( xEventBits, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
+
+ if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Clear all bits ready for the sync with the other three tasks. The
+ value returned is the value prior to the bits being cleared. */
+ if( xEventGroupClearBits( xEventBits, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
+ {
+ xError = pdTRUE;
+ }
+
+ /* The bits should be clear now. */
+ if( xEventGroupGetBits( xEventBits ) != 0x00 )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Check the other three tasks are suspended. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Unsuspend the other tasks then check they have executed up to the
+ synchronisation point. */
+ vTaskResume( xWaitBitsTaskHandle );
+ vTaskResume( xSyncTask1 );
+ vTaskResume( xSyncTask2 );
+
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Set this task's sync bit. */
+ uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
+
+ /* A sync with a max delay should only exit when all the synchronise
+ bits are set... */
+ if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* ...but now the sync bits should be clear again. */
+ if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* The other tasks should now all be suspended again, ready for the next
+ synchronisation. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* Sync again - but this time set the last necessary bit as the
+ highest priority task, rather than the lowest priority task. Unsuspend
+ the other tasks then check they have executed up to the synchronisation
+ point. */
+ vTaskResume( xWaitBitsTaskHandle );
+ vTaskResume( xSyncTask1 );
+ vTaskResume( xSyncTask2 );
+
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Raise the priority of this task above that of the other tasks. */
+ vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 );
+
+ /* Set this task's sync bit. */
+ uxBits = xEventGroupSync( xEventBits, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
+
+ /* A sync with a max delay should only exit when all the synchronisation
+ bits are set... */
+ if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
+ {
+ xError = pdTRUE;
+ }
+
+ /* ...but now the sync bits should be clear again. */
+ if( xEventGroupSetBits( xEventBits, 0x00 ) != 0 )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* The other tasks should now all be in the ready state again, but not
+ executed yet as this task still has a higher relative priority. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eReady )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eReady )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eReady )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* Reset the priority of this task back to its original value. */
+ vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );
+
+ /* Now all the other tasks should have reblocked on the event bits
+ to test the behaviour when the event bits are deleted. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Delete the event group. */
+ vEventGroupDelete( xEventBits );
+
+ /* Now all the other tasks should have completed and suspended
+ themselves ready for the next go around the loop. */
+ if( eTaskGetState( xWaitBitsTaskHandle ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask1 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+
+ /* Recreate the event group ready for the next cycle. */
+ xEventBits = xEventGroupCreate();
+ configASSERT( xEventBits );
+
+ if( xError == pdFALSE )
+ {
+ ulSetBitCycles++;
+ }
+
+ configASSERT( xError == pdFALSE );
+ }
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreEventBitTasksStillRunning( void )
+{
+static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;
+portBASE_TYPE xStatus = pdPASS;
+
+ /* Check the tasks are still cycling without finding any errors. */
+ if( ulPreviousSetBitCycles == ulSetBitCycles )
+ {
+ xStatus = pdFAIL;
+ }
+ ulPreviousSetBitCycles = ulSetBitCycles;
+
+ if( ulPreviousWaitBitCycles == ulWaitBitCycles )
+ {
+ xStatus = pdFAIL;
+ }
+ ulPreviousWaitBitCycles = ulWaitBitCycles;
+
+ return xStatus;
+}
+
+
+
diff --git a/FreeRTOS/Demo/Common/include/EventGroupsDemo.h b/FreeRTOS/Demo/Common/include/EventGroupsDemo.h
new file mode 100644
index 000000000..390c83e8c
--- /dev/null
+++ b/FreeRTOS/Demo/Common/include/EventGroupsDemo.h
@@ -0,0 +1,81 @@
+/*
+ FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+
+/*
+ * This file contains fairly comprehensive checks on the behaviour of event
+ * groups. It is not intended to be a user friendly demonstration of the event
+ * groups API.
+ */
+
+#ifndef EVENT_GROUPS_DEMO_H
+#define EVENT_GROUPS_DEMO_H
+
+void vStartEventBitTasks( void );
+portBASE_TYPE xAreEventBitTasksStillRunning( void );
+
+#endif /* EVENT_GROUPS_DEMO_H */
+