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. */
#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;

@ -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 );

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

@ -130,6 +130,12 @@
<ClCompile Include="main_blinky.c">
<Filter>Demo App Source</Filter>
</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>
<ClInclude Include="FreeRTOSConfig.h">

@ -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";
}

@ -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 );

Loading…
Cancel
Save