From: richardbarry Date: Fri, 22 Nov 2013 10:58:25 +0000 (+0000) Subject: Add additional event group tests - and update implementation as required by test... X-Git-Tag: V8.0.0rc1~47 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=3648e56851ef15544a807bff8a8ba0a2f4a49f52;p=freertos Add additional event group tests - and update implementation as required by test results. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2114 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- 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 );