static void prvSyncTask( void *pvParameters ) { EventBits_t uxSynchronisationBit, uxReturned; /* A few tests that check the behaviour when two tasks are blocked on various different bits within an event group are performed before this task enters its infinite loop to carry out its main demo function. */ prvSelectiveBitsTestSlaveFunction(); /* The bit to use to indicate this task is at the synchronisation point is passed in as the task parameter. */ uxSynchronisationBit = ( EventBits_t ) pvParameters; for( ;; ) { /* Now this task takes part in a task synchronisation - sometimes known as a 'rendezvous'. Its execution pattern is controlled by the 'test master' task, which is responsible for taking this task out of the Suspended state when it is time to test the synchronisation behaviour. See: http://www.freertos.org/xEventGroupSync.html. */ vTaskSuspend( NULL ); /* Set the bit that indicates this task is at the synchronisation point. The first time this is done the 'test master' task has a lower priority than this task so this task will get to the sync point before the set bits task. */ uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */ ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */ portMAX_DELAY );/* The maximum time to wait for the sync condition to be met before giving up. */ /* A max delay was used, so this task should only exit the above function call when the sync condition is met. Check this is the case. */ configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS ); /* Remove compiler warning if configASSERT() is not defined. */ ( void ) uxReturned; /* Wait until the 'test master' task unsuspends this task again. */ vTaskSuspend( NULL ); /* Set the bit that indicates this task is at the synchronisation point again. This time the 'test master' task has a higher priority than this task so will get to the sync point before this task. */ uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY ); /* Again a max delay was used, so this task should only exit the above function call when the sync condition is met. Check this is the case. */ configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS ); /* Block on the event group again. This time the event group is going to be deleted while this task is blocked on it so it is expected that 0 be returned. */ uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY ); configASSERT( uxReturned == 0 ); } }
static void prvExerciseEventGroupAPI( void ) { EventGroupHandle_t xEventGroup; EventBits_t xBits; const EventBits_t xBitsToWaitFor = ( EventBits_t ) 0xff, xBitToClear = ( EventBits_t ) 0x01; /* Exercise some event group functions. */ xEventGroup = xEventGroupCreate(); configASSERT( xEventGroup ); /* No bits should be set. */ xBits = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdFALSE, mainDONT_BLOCK ); configASSERT( xBits == ( EventBits_t ) 0 ); /* Set bits and read back to ensure the bits were set. */ xEventGroupSetBits( xEventGroup, xBitsToWaitFor ); xBits = xEventGroupGetBits( xEventGroup ); configASSERT( xBits == xBitsToWaitFor ); /* Clear a bit and read back again using a different API function. */ xEventGroupClearBits( xEventGroup, xBitToClear ); xBits = xEventGroupSync( xEventGroup, 0x00, xBitsToWaitFor, mainDONT_BLOCK ); configASSERT( xBits == ( xBitsToWaitFor & ~xBitToClear ) ); /* Finished with the event group. */ vEventGroupDelete( xEventGroup ); }
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) { EventBits_t xReturn; BaseType_t xRunningPrivileged = xPortRaisePrivilege(); xReturn = xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ); vPortResetPrivilege( xRunningPrivileged ); return xReturn; }
static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ) { EventBits_t uxBits; /* The three tasks that take part in the synchronisation (rendezvous) are expected to be in the suspended state at the start of the test. */ if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) { xError = pdTRUE; } if( eTaskGetState( xSyncTask1 ) != eSuspended ) { xError = pdTRUE; } if( eTaskGetState( xSyncTask2 ) != eSuspended ) { xError = pdTRUE; } /* Try a synch with no other tasks involved. First set all the bits other than this task's bit. */ xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); /* Then wait on just one bit - the bit that is being set. */ uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ ebSET_BIT_TASK_SYNC_BIT,/* The bits to wait for - in this case it is just waiting for itself. */ portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ /* A sync with a max delay should only exit when all the synchronise bits are set...check that is the case. In this case there is only one sync bit anyway. */ if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT ) { xError = pdTRUE; } /* ...but now the sync bits should be clear again, leaving all the other bits set (as only one bit was being waited for). */ if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ) { xError = pdTRUE; } /* Clear all the bits to zero again. */ xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); if( xEventGroupGetBits( xEventGroup ) != 0 ) { xError = pdTRUE; } /* Unsuspend the other tasks then check they have executed up to the synchronisation point. */ vTaskResume( xTestSlaveTaskHandle ); vTaskResume( xSyncTask1 ); vTaskResume( xSyncTask2 ); if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) { xError = pdTRUE; } if( eTaskGetState( xSyncTask1 ) != eBlocked ) { xError = pdTRUE; } if( eTaskGetState( xSyncTask2 ) != eBlocked ) { xError = pdTRUE; } /* Set this task's sync bit. */ uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks that take part in the sync. */ portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ /* A sync with a max delay should only exit when all the synchronise bits are set...check that is the case. */ if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) { xError = pdTRUE; } /* ...but now the sync bits should be clear again. */ if( xEventGroupGetBits( xEventGroup ) != 0 ) { xError = pdTRUE; } /* The other tasks should now all be suspended again, ready for the next synchronisation. */ if( eTaskGetState( xTestSlaveTaskHandle ) != 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( xTestSlaveTaskHandle ); vTaskResume( xSyncTask1 ); vTaskResume( xSyncTask2 ); if( eTaskGetState( xTestSlaveTaskHandle ) != 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( xEventGroup, 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( xEventGroupGetBits( xEventGroup ) != 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( xTestSlaveTaskHandle ) != 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( xTestSlaveTaskHandle ) != eBlocked ) { xError = pdTRUE; } if( eTaskGetState( xSyncTask1 ) != eBlocked ) { xError = pdTRUE; } if( eTaskGetState( xSyncTask2 ) != eBlocked ) { xError = pdTRUE; } return xError; }
static void prvTestSlaveTask( void *pvParameters ) { EventBits_t uxReturned; BaseType_t xError = pdFALSE; /* Avoid compiler warnings. */ ( void ) pvParameters; for( ;; ) { /********************************************************************** * Part 1: This section is the counterpart to the * prvBitCombinationTestMasterFunction() function which is called by the * test master task. *********************************************************************** This task is controller by the 'test master' task (which is implemented by prvTestMasterTask()). Suspend until resumed by the 'test master' task. */ vTaskSuspend( NULL ); /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get set. Clear the bit on exit. */ uxReturned = xEventGroupWaitBits( xEventGroup, /* The event group that contains 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 ); /* Block indefinitely to wait for the condition to be met. */ /* The 'test master' task set all the bits defined by ebCOMBINED_BITS, only one of which was being waited for by this task. The return value shows the state of the event bits when the task was unblocked, however because the task was waiting for ebBIT_1 and 'clear on exit' was set to the current state of the event bits will have ebBIT_1 clear. */ 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 'test master' task sets ebBIT_1 - which was the bit cleared in the call to xEventGroupWaitBits() above. */ uxReturned = xEventGroupWaitBits( xEventGroup, 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 'test master' 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( xEventGroup, ebCOMBINED_BITS, /* The bits being waited on. */ pdTRUE, /* Clear the bits on exit. */ pdTRUE, /* All the bits must be set to unblock. */ portMAX_DELAY ); /* The 'test master' task set all the bits in the event group, so that is the value that should have been returned. The bits defined by ebCOMBINED_BITS will have been clear again in the current value though as 'clear on exit' was set to pdTRUE. */ if( uxReturned != ebALL_BITS ) { xError = pdTRUE; } /********************************************************************** * Part 2: This section is the counterpart to the * prvPerformTaskSyncTests() function which is called by the * test master task. *********************************************************************** Once again wait for the 'test master' task to unsuspend this task when it is time for the next test. */ vTaskSuspend( NULL ); /* Now peform a synchronisation with all the other tasks. At this point the 'test master' task has the lowest priority so will get to the sync point after all the other synchronising tasks. */ uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the sync. */ ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */ ebALL_SYNC_BITS, /* The bits to wait for. These bits are set by the other tasks taking part in the sync. */ portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */ /* 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. Read back the current value of the bits within the event group to check that is the case. Setting the bits to zero will return the bits previous value then leave all the bits clear. */ if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 ) { xError = pdTRUE; } /* Check the bits are indeed 0 now by simply reading then. */ if( xEventGroupGetBits( xEventGroup ) != 0 ) { xError = pdTRUE; } if( xError == pdFALSE ) { /* This task is still cycling without finding an error. */ ulTestSlaveCycles++; } vTaskSuspend( NULL ); /* This time sync when the 'test master' task has the highest priority at the point where it sets its sync bit - so this time the 'test master' task will get to the sync point before this task. */ uxReturned = xEventGroupSync( xEventGroup, 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( xEventGroup, 0x00 ) != 0 ) { xError = pdTRUE; } /* Block on the event group again. This time the event group is going to be deleted while this task is blocked on it, so it is expected that 0 will be returned. */ uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY ); if( uxReturned != 0 ) { xError = pdTRUE; } if( xError == pdFALSE ) { /* This task is still cycling without finding an error. */ ulTestSlaveCycles++; } configASSERT( xError == pdFALSE ); } }