Add additional event group tests - and update implementation as required by test results.

pull/4/head
Richard Barry 11 years ago
parent a22d5ff5a5
commit 9dc39ee2a7

@ -110,6 +110,11 @@ that synchronise with the xEventGroupSync() function. */
/* A 5ms delay. */ /* A 5ms delay. */
#define ebSHORT_DELAY ( 5 / portTICK_RATE_MS ) #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 ); 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 /* 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; xTaskHandle xWaitBitsTaskHandle;
@ -161,10 +174,6 @@ xTaskHandle xWaitBitsTaskHandle;
* event groups API. * 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( 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( 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_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );
@ -373,6 +382,9 @@ xEventBitsType uxSynchronisationBit, uxReturned;
passed in as the task parameter. */ passed in as the task parameter. */
uxSynchronisationBit = ( xEventBitsType ) pvParameters; uxSynchronisationBit = ( xEventBitsType ) pvParameters;
/* A few tests are performed before entering the main demo loop. */
prvPreSyncSelectiveWakeTest();
for( ;; ) for( ;; )
{ {
/* Wait until the 'set bit' task unsuspends this task. */ /* Wait until the 'set bit' task unsuspends this task. */
@ -540,10 +552,27 @@ xTaskHandle xWaitBitsTaskHandle = ( xTaskHandle ) pvParameters;
/* Avoid compiler warnings. */ /* Avoid compiler warnings. */
( void ) pvParameters; ( 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(); 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( ;; ) 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 /* Resume the other task. It will block, pending a single bit from
within ebCOMBINED_BITS. */ within ebCOMBINED_BITS. */
vTaskResume( xWaitBitsTaskHandle ); 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 ) if( xError == pdFALSE )
{ {
ulSetBitCycles++; 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. */ /* 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; static unsigned long ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0;
portBASE_TYPE xStatus = pdPASS; portBASE_TYPE xStatus = pdPASS;

@ -132,6 +132,7 @@ to exclude the API function. */
#define INCLUDE_pcTaskGetTaskName 1 #define INCLUDE_pcTaskGetTaskName 1
#define INCLUDE_eTaskGetState 1 #define INCLUDE_eTaskGetState 1
#define INCLUDE_xSemaphoreGetMutexHolder 1 #define INCLUDE_xSemaphoreGetMutexHolder 1
#define INCLUDE_xTimerPendCallbackFromISR 1
/* Standard assert semantics. */ /* Standard assert semantics. */
extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName );

@ -131,6 +131,7 @@
<ClCompile Include="..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-Trace\trcKernelPort.c" /> <ClCompile Include="..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-Trace\trcKernelPort.c" />
<ClCompile Include="..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-Trace\trcUser.c" /> <ClCompile Include="..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-Trace\trcUser.c" />
<ClCompile Include="..\..\Source\croutine.c" /> <ClCompile Include="..\..\Source\croutine.c" />
<ClCompile Include="..\..\Source\event_groups.c" />
<ClCompile Include="..\..\Source\portable\MemMang\heap_4.c" /> <ClCompile Include="..\..\Source\portable\MemMang\heap_4.c" />
<ClCompile Include="..\..\Source\timers.c" /> <ClCompile Include="..\..\Source\timers.c" />
<ClCompile Include="..\Common\Minimal\BlockQ.c" /> <ClCompile Include="..\Common\Minimal\BlockQ.c" />
@ -138,6 +139,7 @@
<ClCompile Include="..\Common\Minimal\countsem.c" /> <ClCompile Include="..\Common\Minimal\countsem.c" />
<ClCompile Include="..\Common\Minimal\death.c" /> <ClCompile Include="..\Common\Minimal\death.c" />
<ClCompile Include="..\Common\Minimal\dynamic.c" /> <ClCompile Include="..\Common\Minimal\dynamic.c" />
<ClCompile Include="..\Common\Minimal\EventGroupsDemo.c" />
<ClCompile Include="..\Common\Minimal\flop.c" /> <ClCompile Include="..\Common\Minimal\flop.c" />
<ClCompile Include="..\Common\Minimal\GenQTest.c" /> <ClCompile Include="..\Common\Minimal\GenQTest.c" />
<ClCompile Include="..\Common\Minimal\integer.c" /> <ClCompile Include="..\Common\Minimal\integer.c" />

@ -130,6 +130,12 @@
<ClCompile Include="main_blinky.c"> <ClCompile Include="main_blinky.c">
<Filter>Demo App Source</Filter> <Filter>Demo App Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Common\Minimal\EventGroupsDemo.c">
<Filter>Demo App Source\Common Demo Tasks</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\event_groups.c">
<Filter>FreeRTOS Source\Source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="FreeRTOSConfig.h"> <ClInclude Include="FreeRTOSConfig.h">

@ -132,6 +132,7 @@
#include "dynamic.h" #include "dynamic.h"
#include "QueueSet.h" #include "QueueSet.h"
#include "QueueOverwrite.h" #include "QueueOverwrite.h"
#include "EventGroupsDemo.h"
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
@ -196,6 +197,7 @@ int main_full( void )
vStartQueueSetTasks(); vStartQueueSetTasks();
vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
xTaskCreate( prvDemoQueueSpaceFunctions, ( signed char * ) "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); xTaskCreate( prvDemoQueueSpaceFunctions, ( signed char * ) "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
vStartEventGroupTasks();
#if( configUSE_PREEMPTION != 0 ) #if( configUSE_PREEMPTION != 0 )
{ {
@ -250,7 +252,11 @@ const portTickType xCycleFrequency = 2500 / portTICK_RATE_MS;
} }
#endif #endif
if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) if( xAreEventGroupTasksStillRunning() != pdTRUE )
{
pcStatusMessage = "Error: EventGroup";
}
else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: IntMath"; pcStatusMessage = "Error: IntMath";
} }

@ -94,12 +94,12 @@ privileged Vs unprivileged linkage and placement. */
#if configUSE_16_BIT_TICKS == 1 #if configUSE_16_BIT_TICKS == 1
#define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x0200U #define taskUNBLOCKED_DUE_TO_BIT_SET 0x0200U
#define taskWAIT_FOR_ALL_BITS 0x0400U #define taskWAIT_FOR_ALL_BITS 0x0400U
#define taskEVENT_BITS_CONTROL_BYTES 0xff00U #define taskEVENT_BITS_CONTROL_BYTES 0xff00U
#else #else
#define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL #define taskCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
#define taskUNBLOCKED_DUE_TO_BIT_SET_BIT 0x02000000UL #define taskUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
#define taskWAIT_FOR_ALL_BITS 0x04000000UL #define taskWAIT_FOR_ALL_BITS 0x04000000UL
#define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL #define taskEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif #endif
@ -190,7 +190,7 @@ portBASE_TYPE xYieldedAlready;
event list item, and they should now be retrieved then cleared. */ event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue(); 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. */ /* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
@ -288,7 +288,7 @@ xEventBitsType uxReturn, uxControlBits = 0;
event list item, and they should now be retrieved then cleared. */ event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue(); 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. */ /* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits; uxReturn = pxEventBits->uxEventBits;
@ -356,6 +356,7 @@ portBASE_TYPE xMatchFound = pdFALSE;
{ {
pxNext = listGET_NEXT( pxListItem ); pxNext = listGET_NEXT( pxListItem );
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
xMatchFound = pdFALSE;
/* Split the bits waited for from the control bits. */ /* Split the bits waited for from the control bits. */
uxControlBits = uxBitsWaitedFor & taskEVENT_BITS_CONTROL_BYTES; 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 /* Store the actual event flag value in the task's event list
item before removing the task from the event list. The 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 that is was unblocked due to its required bits matching, rather
than because it timed out. */ 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 /* 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 /* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */ and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( xListItem * ) &( pxTasksWaitingForBits->xListEnd ) ); 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 ); vPortFree( pxEventBits );

Loading…
Cancel
Save