/* A 5ms delay. */\r
#define ebSHORT_DELAY ( 5 / portTICK_RATE_MS )\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
/*-----------------------------------------------------------*/\r
\r
/*\r
*/\r
static portBASE_TYPE prvSingleTaskTests( void );\r
\r
+/*\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 prvTestSelectiveBits( void );\r
+static void prvPreSyncSelectiveWakeTest( void );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* Variables that are incremented by the tasks on each cycle provided no errors\r
\r
/*-----------------------------------------------------------*/\r
\r
-void vStartEventBitTasks( void )\r
+void vStartEventGroupTasks( void )\r
{\r
xTaskHandle xWaitBitsTaskHandle;\r
\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
passed in as the task parameter. */\r
uxSynchronisationBit = ( xEventBitsType ) pvParameters;\r
\r
+ /* A few tests are performed before entering the main demo loop. */\r
+ prvPreSyncSelectiveWakeTest();\r
+\r
for( ;; )\r
{\r
/* Wait until the 'set bit' task unsuspends this task. */\r
/* Avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
+ /* Create the event group ready for the initial tests. */\r
+ xEventBits = xEventGroupCreate();\r
+ configASSERT( xEventBits );\r
+\r
+ /* Perform the tests that only require a single task. */\r
xError = prvSingleTaskTests();\r
\r
+ if( xError == pdFALSE )\r
+ {\r
+ /* Perform the tests that block two tasks on different combinations of\r
+ bits, then set each bit in turn and check the correct tasks unblock at\r
+ the correct times. */\r
+ xError = prvTestSelectiveBits();\r
+ }\r
+\r
for( ;; )\r
{\r
+ /* Recreate the event group ready for the next cycle. */\r
+ xEventBits = xEventGroupCreate();\r
+ configASSERT( xEventBits );\r
+\r
/* Resume the other task. It will block, pending a single bit from\r
within ebCOMBINED_BITS. */\r
vTaskResume( xWaitBitsTaskHandle );\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
\r
+static void prvPreSyncSelectiveWakeTest( void )\r
+{\r
+xEventBitsType uxPendBits, uxReturned;\r
+\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
+ vTaskSuspend( NULL );\r
+ uxReturned = xEventGroupWaitBits( xEventBits, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );\r
+\r
+ if( uxReturned == ( xEventBitsType ) 0 )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portBASE_TYPE prvTestSelectiveBits( void )\r
+{\r
+portBASE_TYPE xError = pdFALSE;\r
+xEventBitsType uxBit;\r
+\r
+ /* Both 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
+ /* 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
+ /* Now both tasks should be blocked on the event group. */\r
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+ {\r
+ xError = pdTRUE;\r
+ }\r
+\r
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+ {\r
+ xError = pdTRUE;\r
+ }\r
+\r
+ /* Set one bit. */\r
+ xEventGroupSetBits( xEventBits, uxBit );\r
+\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
+ /* Task should not have unblocked. */\r
+ if( eTaskGetState( xSyncTask1 ) != eBlocked )\r
+ {\r
+ xError = pdTRUE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Task should have unblocked and returned to the suspended state. */\r
+ if( eTaskGetState( xSyncTask1 ) != eSuspended )\r
+ {\r
+ xError = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Same checks for the second sync task. */\r
+ if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 )\r
+ {\r
+ /* Task should not have unblocked. */\r
+ if( eTaskGetState( xSyncTask2 ) != eBlocked )\r
+ {\r
+ xError = pdTRUE;\r
+ }\r
+ }\r
+ else\r
+ {\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
+ /* 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
+ vEventGroupDelete( xEventBits );\r
+\r
+ return xError;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
/* This is called to check that all the created tasks are still running. */\r
-portBASE_TYPE xAreEventBitTasksStillRunning( void )\r
+portBASE_TYPE xAreEventGroupTasksStillRunning( void )\r
{\r
static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;\r
portBASE_TYPE xStatus = pdPASS;\r
\r
\r
#if configUSE_16_BIT_TICKS == 1\r
- #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U\r
- #define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x0200U\r
- #define taskWAIT_FOR_ALL_BITS 0x0400U\r
- #define taskEVENT_BITS_CONTROL_BYTES 0xff00U\r
+ #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U\r
+ #define taskUNBLOCKED_DUE_TO_BIT_SET 0x0200U\r
+ #define taskWAIT_FOR_ALL_BITS 0x0400U\r
+ #define taskEVENT_BITS_CONTROL_BYTES 0xff00U\r
#else\r
- #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL\r
- #define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x02000000UL\r
- #define taskWAIT_FOR_ALL_BITS 0x04000000UL\r
- #define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL\r
+ #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL\r
+ #define taskUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL\r
+ #define taskWAIT_FOR_ALL_BITS 0x04000000UL\r
+ #define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL\r
#endif\r
\r
typedef struct EventBitsDefinition\r
event list item, and they should now be retrieved then cleared. */\r
uxReturn = uxTaskResetEventItemValue();\r
\r
- if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET_BIT ) == ( xEventBitsType ) 0 )\r
+ if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET ) == ( xEventBitsType ) 0 )\r
{\r
/* The task timed out, just return the current event bit value. */\r
uxReturn = pxEventBits->uxEventBits;\r
event list item, and they should now be retrieved then cleared. */\r
uxReturn = uxTaskResetEventItemValue();\r
\r
- if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET_BIT ) == ( xEventBitsType ) 0 )\r
+ if( ( uxReturn & taskUNBLOCKED_DUE_TO_BIT_SET ) == ( xEventBitsType ) 0 )\r
{\r
/* The task timed out, just return the current event bit value. */\r
uxReturn = pxEventBits->uxEventBits;\r
{\r
pxNext = listGET_NEXT( pxListItem );\r
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );\r
+ xMatchFound = pdFALSE;\r
\r
/* Split the bits waited for from the control bits. */\r
uxControlBits = uxBitsWaitedFor & taskEVENT_BITS_CONTROL_BYTES;\r
\r
/* Store the actual event flag value in the task's event list\r
item before removing the task from the event list. The\r
- taskUNBLOCKED_DUE_TO_BIT_SET_BIT bit is set so the task knows\r
+ taskUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows\r
that is was unblocked due to its required bits matching, rather\r
than because it timed out. */\r
- ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | taskUNBLOCKED_DUE_TO_BIT_SET_BIT );\r
+ ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | taskUNBLOCKED_DUE_TO_BIT_SET );\r
}\r
\r
/* Move onto the next list item. Note pxListItem->pxNext is not\r
/* Unblock the task, returning 0 as the event list is being deleted\r
and cannot therefore have any bits set. */\r
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( xListItem * ) &( pxTasksWaitingForBits->xListEnd ) );\r
- ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, ( portTickType ) 0 );\r
+ ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, ( portTickType ) taskUNBLOCKED_DUE_TO_BIT_SET );\r
}\r
\r
vPortFree( pxEventBits );\r