diff --git a/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
index abbf06991..b7365e091 100644
--- a/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
+++ b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c
@@ -110,6 +110,11 @@ that synchronise with the xEventGroupSync() function. */
/* A 5ms delay. */
#define ebSHORT_DELAY ( 5 / portTICK_RATE_MS )
+/* Used in the selective bits test which checks no, one or both tasks blocked on
+event bits in a group are unblocked as appropriate as different bits get set. */
+#define ebSELECTIVE_BITS_1 0x03
+#define ebSELECTIVE_BITS_2 0x05
+
/*-----------------------------------------------------------*/
/*
@@ -137,6 +142,14 @@ static void prvSyncTask( void *pvParameters );
*/
static portBASE_TYPE prvSingleTaskTests( void );
+/*
+ * Functions used in a test that blocks two tasks on various different bits
+ * within an event group - then sets each bit in turn and checks that the
+ * correct tasks unblock at the correct times.
+ */
+static portBASE_TYPE prvTestSelectiveBits( void );
+static void prvPreSyncSelectiveWakeTest( void );
+
/*-----------------------------------------------------------*/
/* Variables that are incremented by the tasks on each cycle provided no errors
@@ -151,7 +164,7 @@ static xTaskHandle xSyncTask1 = NULL, xSyncTask2 = NULL;
/*-----------------------------------------------------------*/
-void vStartEventBitTasks( void )
+void vStartEventGroupTasks( void )
{
xTaskHandle xWaitBitsTaskHandle;
@@ -161,10 +174,6 @@ xTaskHandle xWaitBitsTaskHandle;
* 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 );
@@ -373,6 +382,9 @@ xEventBitsType uxSynchronisationBit, uxReturned;
passed in as the task parameter. */
uxSynchronisationBit = ( xEventBitsType ) pvParameters;
+ /* A few tests are performed before entering the main demo loop. */
+ prvPreSyncSelectiveWakeTest();
+
for( ;; )
{
/* Wait until the 'set bit' task unsuspends this task. */
@@ -540,10 +552,27 @@ xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;
/* Avoid compiler warnings. */
( void ) pvParameters;
+ /* Create the event group ready for the initial tests. */
+ xEventBits = xEventGroupCreate();
+ configASSERT( xEventBits );
+
+ /* Perform the tests that only require a single task. */
xError = prvSingleTaskTests();
+ if( xError == pdFALSE )
+ {
+ /* Perform the tests that block two tasks on different combinations of
+ bits, then set each bit in turn and check the correct tasks unblock at
+ the correct times. */
+ xError = prvTestSelectiveBits();
+ }
+
for( ;; )
{
+ /* Recreate the event group ready for the next cycle. */
+ xEventBits = xEventGroupCreate();
+ configASSERT( xEventBits );
+
/* Resume the other task. It will block, pending a single bit from
within ebCOMBINED_BITS. */
vTaskResume( xWaitBitsTaskHandle );
@@ -831,10 +860,6 @@ xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;
}
- /* Recreate the event group ready for the next cycle. */
- xEventBits = xEventGroupCreate();
- configASSERT( xEventBits );
-
if( xError == pdFALSE )
{
ulSetBitCycles++;
@@ -845,8 +870,120 @@ xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;
}
/*-----------------------------------------------------------*/
+static void prvPreSyncSelectiveWakeTest( void )
+{
+xEventBitsType uxPendBits, uxReturned;
+
+ if( xTaskGetCurrentTaskHandle() == xSyncTask1 )
+ {
+ uxPendBits = ebSELECTIVE_BITS_1;
+ }
+ else
+ {
+ uxPendBits = ebSELECTIVE_BITS_2;
+ }
+
+ for( ;; )
+ {
+ vTaskSuspend( NULL );
+ uxReturned = xEventGroupWaitBits( xEventBits, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );
+
+ if( uxReturned == ( xEventBitsType ) 0 )
+ {
+ break;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static portBASE_TYPE prvTestSelectiveBits( void )
+{
+portBASE_TYPE xError = pdFALSE;
+xEventBitsType uxBit;
+
+ /* Both tasks should start in the suspended state. */
+ if( eTaskGetState( xSyncTask1 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Test each bit in the byte individually. */
+ for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 )
+ {
+ /* Resume both tasks. */
+ vTaskResume( xSyncTask1 );
+ vTaskResume( xSyncTask2 );
+
+ /* Now both tasks should be blocked on the event group. */
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+
+ /* Set one bit. */
+ xEventGroupSetBits( xEventBits, uxBit );
+
+ /* Is the bit set in the first set of selective bits? If so the first
+ sync task should have unblocked and returned to the suspended state. */
+ if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )
+ {
+ /* Task should not have unblocked. */
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+ }
+ else
+ {
+ /* Task should have unblocked and returned to the suspended state. */
+ if( eTaskGetState( xSyncTask1 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+ }
+
+ /* Same checks for the second sync task. */
+ if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 )
+ {
+ /* Task should not have unblocked. */
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )
+ {
+ xError = pdTRUE;
+ }
+ }
+ else
+ {
+ /* Task should have unblocked and returned to the suspended state. */
+ if( eTaskGetState( xSyncTask2 ) != eSuspended )
+ {
+ xError = pdTRUE;
+ }
+ }
+ }
+
+ /* Ensure both tasks are blocked on the event group again, then delete the
+ event group so the other tasks leave this portion of the test. */
+ vTaskResume( xSyncTask1 );
+ vTaskResume( xSyncTask2 );
+
+ vEventGroupDelete( xEventBits );
+
+ return xError;
+}
+/*-----------------------------------------------------------*/
+
/* This is called to check that all the created tasks are still running. */
-portBASE_TYPE xAreEventBitTasksStillRunning( void )
+portBASE_TYPE xAreEventGroupTasksStillRunning( void )
{
static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;
portBASE_TYPE xStatus = pdPASS;
diff --git a/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h b/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h
index 27aad4219..b5e49564c 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h
+++ b/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h
@@ -132,6 +132,7 @@ to exclude the API function. */
#define INCLUDE_pcTaskGetTaskName 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
+#define INCLUDE_xTimerPendCallbackFromISR 1
/* Standard assert semantics. */
extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName );
diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj
index 8d25ac5fd..c5b25c845 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj
+++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj
@@ -131,6 +131,7 @@
+
@@ -138,6 +139,7 @@
+
diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters
index e4e21ab20..b897c343b 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters
+++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters
@@ -130,6 +130,12 @@
Demo App Source
+
+ Demo App Source\Common Demo Tasks
+
+
+ FreeRTOS Source\Source
+
diff --git a/FreeRTOS/Demo/WIN32-MSVC/main_full.c b/FreeRTOS/Demo/WIN32-MSVC/main_full.c
index 654de2ad0..62600fee4 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/main_full.c
+++ b/FreeRTOS/Demo/WIN32-MSVC/main_full.c
@@ -132,6 +132,7 @@
#include "dynamic.h"
#include "QueueSet.h"
#include "QueueOverwrite.h"
+#include "EventGroupsDemo.h"
/* Priorities at which the tasks are created. */
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
@@ -196,6 +197,7 @@ int main_full( void )
vStartQueueSetTasks();
vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
xTaskCreate( prvDemoQueueSpaceFunctions, ( signed char * ) "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+ vStartEventGroupTasks();
#if( configUSE_PREEMPTION != 0 )
{
@@ -250,7 +252,11 @@ const portTickType xCycleFrequency = 2500 / portTICK_RATE_MS;
}
#endif
- if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
+ if( xAreEventGroupTasksStillRunning() != pdTRUE )
+ {
+ pcStatusMessage = "Error: EventGroup";
+ }
+ else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
{
pcStatusMessage = "Error: IntMath";
}
diff --git a/FreeRTOS/Source/event_groups.c b/FreeRTOS/Source/event_groups.c
index eb186c191..a49d0a1f6 100644
--- a/FreeRTOS/Source/event_groups.c
+++ b/FreeRTOS/Source/event_groups.c
@@ -93,15 +93,15 @@ privileged Vs unprivileged linkage and placement. */
#if configUSE_16_BIT_TICKS == 1
- #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
- #define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x0200U
- #define taskWAIT_FOR_ALL_BITS 0x0400U
- #define taskEVENT_BITS_CONTROL_BYTES 0xff00U
+ #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
+ #define taskUNBLOCKED_DUE_TO_BIT_SET 0x0200U
+ #define taskWAIT_FOR_ALL_BITS 0x0400U
+ #define taskEVENT_BITS_CONTROL_BYTES 0xff00U
#else
- #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
- #define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x02000000UL
- #define taskWAIT_FOR_ALL_BITS 0x04000000UL
- #define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL
+ #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
+ #define taskUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
+ #define taskWAIT_FOR_ALL_BITS 0x04000000UL
+ #define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
typedef struct EventBitsDefinition
@@ -190,7 +190,7 @@ portBASE_TYPE xYieldedAlready;
event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
- if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET_BIT ) == ( xEventBitsType ) 0 )
+ if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET ) == ( xEventBitsType ) 0 )
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
@@ -288,7 +288,7 @@ xEventBitsType uxReturn, uxControlBits = 0;
event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
- if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET_BIT ) == ( xEventBitsType ) 0 )
+ if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET ) == ( xEventBitsType ) 0 )
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
@@ -356,6 +356,7 @@ portBASE_TYPE xMatchFound = pdFALSE;
{
pxNext = listGET_NEXT( pxListItem );
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
+ xMatchFound = pdFALSE;
/* Split the bits waited for from the control bits. */
uxControlBits = uxBitsWaitedFor & taskEVENT_BITS_CONTROL_BYTES;
@@ -389,10 +390,10 @@ portBASE_TYPE xMatchFound = pdFALSE;
/* Store the actual event flag value in the task's event list
item before removing the task from the event list. The
- taskUNBLOCKED_DUE_TO_BIT_SET_BIT bit is set so the task knows
+ taskUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather
than because it timed out. */
- ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | taskUNBLOCKED_DUE_TO_BIT_SET_BIT );
+ ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | taskUNBLOCKED_DUE_TO_BIT_SET );
}
/* Move onto the next list item. Note pxListItem->pxNext is not
@@ -423,7 +424,7 @@ const xList *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
/* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( xListItem * ) &( pxTasksWaitingForBits->xListEnd ) );
- ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, ( portTickType ) 0 );
+ ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, ( portTickType ) taskUNBLOCKED_DUE_TO_BIT_SET );
}
vPortFree( pxEventBits );