From d1ee57ff8bbb9ac19354d410ec4077a4781691ca Mon Sep 17 00:00:00 2001 From: richardbarry Date: Mon, 2 Sep 2013 16:37:56 +0000 Subject: [PATCH] Make the QueueSet.c standard demo task a little friendlier to lower priority tasks. Allow the priority of the controlling task in the recmutex.c standard demo tasks to be overridden by a setting in FreeRTOSConfig.h. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2020 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Demo/Common/Minimal/QueueSet.c | 88 ++++++++++++++++++++----- FreeRTOS/Demo/Common/Minimal/recmutex.c | 23 +++++-- 2 files changed, 88 insertions(+), 23 deletions(-) diff --git a/FreeRTOS/Demo/Common/Minimal/QueueSet.c b/FreeRTOS/Demo/Common/Minimal/QueueSet.c index 01dcb2a6c..3d5b34c1f 100644 --- a/FreeRTOS/Demo/Common/Minimal/QueueSet.c +++ b/FreeRTOS/Demo/Common/Minimal/QueueSet.c @@ -109,11 +109,16 @@ in the range of 0xffff to ULONG_MAX. */ /* For test purposes the priority of the sending task is changed after every queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */ -#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 3 ) +#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 ) /* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */ #define queuesetISR_TX_PERIOD ( 100UL ) +/* A delay inserted when the Tx task changes its priority to be above the idle +task priority to ensure the idle priority tasks get some CPU time before the +next iteration of the queue set Tx task. */ +#define queuesetTX_LOOP_DELAY ( 200 / portTICK_RATE_MS ) + /* The allowable maximum deviation between a received value and the expected received value. A deviation will occur when data is received from a queue inside an ISR in between a task receiving from a queue and the task checking @@ -124,6 +129,13 @@ the received value. */ testing of limits easier (don't have to deal with wrapping values). */ #define queuesetIGNORED_BOUNDARY ( queuesetALLOWABLE_RX_DEVIATION * 2 ) +typedef enum +{ + eEqualPriority = 0, /* Tx and Rx tasks have the same priority. */ + eTxHigherPriority, /* The priority of the Tx task is above that of the Rx task. */ + eTxLowerPriority /* The priority of the Tx task is below that of the Rx task. */ +} eRelativePriorities; + /* * The task that periodically sends to the queue set. */ @@ -161,6 +173,11 @@ static void prvSetupTest( xTaskHandle xQueueSetSendingTask ); */ static portBASE_TYPE prvCheckReceivedValueWithinExpectedRange( unsigned long ulReceived, unsigned long ulExpectedReceived ); +/* + * Increase test coverage by occasionally change the priorities of the two tasks + * relative to each other. */ +static void prvChangeRelativePriorities( void ); + /* * Local pseudo random number seed and return functions. Used to avoid calls * to the standard library. @@ -203,17 +220,18 @@ static volatile unsigned long ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; /* Used by the pseudo random number generator. */ static unsigned long ulNextRand = 0; +/* The task handles are stored so their priorities can be changed. */ +xTaskHandle xQueueSetSendingTask, xQueueSetReceivingTask; + /*-----------------------------------------------------------*/ void vStartQueueSetTasks( void ) { -xTaskHandle xQueueSetSendingTask; - /* Create the two queues. The handle of the sending task is passed into the receiving task using the task parameter. The receiving task uses the handle to resume the sending task after it has created the queues. */ xTaskCreate( prvQueueSetSendingTask, ( signed char * ) "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask ); - xTaskCreate( prvQueueSetReceivingTask, ( signed char * ) "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, NULL ); + xTaskCreate( prvQueueSetReceivingTask, ( signed char * ) "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask ); /* It is important that the sending task does not attempt to write to a queue before the queue has been created. It is therefore placed into the @@ -276,7 +294,6 @@ static void prvQueueSetSendingTask( void *pvParameters ) { unsigned long ulTaskTxValue = 0, ulQueueToWriteTo; xQueueHandle xQueueInUse; -unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0; /* Remove compiler warning about the unused parameter. */ ( void ) pvParameters; @@ -312,19 +329,56 @@ unsigned portBASE_TYPE uxPriority = queuesetMEDIUM_PRIORITY, ulLoops = 0; ulTaskTxValue = 0; } - /* Occasionally change the task priority relative to the priority of - the receiving task. */ - ulLoops++; - if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS ) - { - ulLoops = 0; - uxPriority++; - if( uxPriority > queuesetHIGH_PRIORITY ) - { - uxPriority = queuesetLOW_PRIORITY; - } + /* Increase test coverage by occasionally change the priorities of the + two tasks relative to each other. */ + prvChangeRelativePriorities(); + } +} +/*-----------------------------------------------------------*/ - vTaskPrioritySet( NULL, uxPriority ); +static void prvChangeRelativePriorities( void ) +{ +static unsigned portBASE_TYPE ulLoops = 0; +static eRelativePriorities ePriorities = eEqualPriority; + + /* Occasionally change the task priority relative to the priority of + the receiving task. */ + ulLoops++; + if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS ) + { + ulLoops = 0; + + switch( ePriorities ) + { + case eEqualPriority: + /* Both tasks are running with medium priority. Now lower the + priority of the receiving task so the Tx task has the higher + relative priority. */ + vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY ); + ePriorities = eTxHigherPriority; + break; + + case eTxHigherPriority: + /* The Tx task is running with a higher priority than the Rx + task. Switch the priorities around so the Rx task has the + higher relative priority. */ + vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY ); + vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY ); + ePriorities = eTxLowerPriority; + break; + + case eTxLowerPriority: + /* The Tx task is running with a lower priority than the Rx + task. Make the priorities equal again. */ + vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY ); + ePriorities = eEqualPriority; + + /* When both tasks are using a non-idle priority the queue set + tasks will starve idle priority tasks of execution time - so + relax a bit before the next iteration to minimise the impact. */ + vTaskDelay( queuesetTX_LOOP_DELAY ); + + break; } } } diff --git a/FreeRTOS/Demo/Common/Minimal/recmutex.c b/FreeRTOS/Demo/Common/Minimal/recmutex.c index bce86e107..22bf1d1f2 100644 --- a/FreeRTOS/Demo/Common/Minimal/recmutex.c +++ b/FreeRTOS/Demo/Common/Minimal/recmutex.c @@ -106,8 +106,11 @@ /* Demo app include files. */ #include "recmutex.h" -/* Priorities assigned to the three tasks. */ -#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can +be overridden by a definition in FreeRTOSConfig.h. */ +#ifndef recmuCONTROLLING_TASK_PRIORITY + #define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#endif #define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 ) @@ -117,7 +120,7 @@ /* Misc. */ #define recmuSHORT_DELAY ( 20 / portTICK_RATE_MS ) #define recmuNO_DELAY ( ( portTickType ) 0 ) -#define recmuTHREE_TICK_DELAY ( ( portTickType ) 3 ) +#define recmuFIVE_TICK_DELAY ( ( portTickType ) 5 ) /* The three tasks as described at the top of this file. */ static void prvRecursiveMutexControllingTask( void *pvParameters ); @@ -191,7 +194,7 @@ unsigned portBASE_TYPE ux; long enough to ensure the polling task will execute again before the block time expires. If the block time does expire then the error flag will be set here. */ - if( xSemaphoreTakeRecursive( xMutex, recmuTHREE_TICK_DELAY ) != pdPASS ) + if( xSemaphoreTakeRecursive( xMutex, recmuFIVE_TICK_DELAY ) != pdPASS ) { xErrorOccurred = pdTRUE; } @@ -222,7 +225,7 @@ unsigned portBASE_TYPE ux; } /* Having given it back the same number of times as it was taken, we - should no longer be the mutex owner, so the next give sh ould fail. */ + should no longer be the mutex owner, so the next give should fail. */ if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) { xErrorOccurred = pdTRUE; @@ -232,7 +235,7 @@ unsigned portBASE_TYPE ux; stall can be detected. */ uxControllingCycles++; - /* Suspend ourselves to the blocking task can execute. */ + /* Suspend ourselves so the blocking task can execute. */ xControllingIsSuspended = pdTRUE; vTaskSuspend( NULL ); xControllingIsSuspended = pdFALSE; @@ -347,6 +350,7 @@ static void prvRecursiveMutexPollingTask( void *pvParameters ) #if( INCLUDE_uxTaskPriorityGet == 1 ) { + /* Check priority inherited. */ configASSERT( uxTaskPriorityGet( NULL ) == recmuCONTROLLING_TASK_PRIORITY ); } #endif /* INCLUDE_uxTaskPriorityGet */ @@ -363,6 +367,13 @@ static void prvRecursiveMutexPollingTask( void *pvParameters ) { xErrorOccurred = pdTRUE; } + + #if( INCLUDE_uxTaskPriorityGet == 1 ) + { + /* Check priority disinherited. */ + configASSERT( uxTaskPriorityGet( NULL ) == recmuPOLLING_TASK_PRIORITY ); + } + #endif /* INCLUDE_uxTaskPriorityGet */ } } -- 2.39.5