GenQTest.c File Reference

#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "GenQTest.h"

Go to the source code of this file.

Defines

#define genqMUTEX_HIGH_PRIORITY   ( tskIDLE_PRIORITY + 3 )
#define genqMUTEX_LOW_PRIORITY   ( tskIDLE_PRIORITY )
#define genqMUTEX_MEDIUM_PRIORITY   ( tskIDLE_PRIORITY + 2 )
#define genqMUTEX_TEST_PRIORITY   ( tskIDLE_PRIORITY + 1 )
#define genqNO_BLOCK   ( 0 )
#define genqQUEUE_LENGTH   ( 5 )

Functions

static void prvHighPriorityMutexTask (void *pvParameters)
static void prvLowPriorityMutexTask (void *pvParameters)
static void prvMediumPriorityMutexTask (void *pvParameters)
static void prvSendFrontAndBackTest (void *pvParameters)
void vStartGenericQueueTasks (unsigned portBASE_TYPE uxPriority)
portBASE_TYPE xAreGenericQueueTasksStillRunning (void)

Variables

static volatile unsigned portLONG ulGuardedVariable = 0
static volatile unsigned portLONG ulLoopCounter = 0
static volatile unsigned portLONG ulLoopCounter2 = 0
static portBASE_TYPE xErrorDetected = pdFALSE
static xTaskHandle xHighPriorityMutexTask
static xTaskHandle xMediumPriorityMutexTask


Define Documentation

#define genqMUTEX_HIGH_PRIORITY   ( tskIDLE_PRIORITY + 3 )

Definition at line 82 of file GenQTest.c.

#define genqMUTEX_LOW_PRIORITY   ( tskIDLE_PRIORITY )

Definition at line 79 of file GenQTest.c.

#define genqMUTEX_MEDIUM_PRIORITY   ( tskIDLE_PRIORITY + 2 )

Definition at line 81 of file GenQTest.c.

#define genqMUTEX_TEST_PRIORITY   ( tskIDLE_PRIORITY + 1 )

Definition at line 80 of file GenQTest.c.

#define genqNO_BLOCK   ( 0 )

Definition at line 77 of file GenQTest.c.

#define genqQUEUE_LENGTH   ( 5 )

Definition at line 76 of file GenQTest.c.


Function Documentation

static void prvHighPriorityMutexTask ( void *  pvParameters  )  [static]

Definition at line 518 of file GenQTest.c.

References pdPASS, pdTRUE, portMAX_DELAY, vTaskSuspend(), xErrorDetected, xMutex, xSemaphoreGive, and xSemaphoreTake.

00519 {
00520 xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;
00521 
00522     for( ;; )
00523     {
00524         /* The high priority task starts by suspending itself.  The low
00525         priority task will unsuspend this task when required. */
00526         vTaskSuspend( NULL );
00527 
00528         /* When this task unsuspends all it does is attempt to obtain
00529         the mutex.  It should find the mutex is not available so a
00530         block time is specified. */
00531         if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )
00532         {
00533             xErrorDetected = pdTRUE;
00534         }
00535 
00536         /* When we eventually obtain the mutex we just give it back then
00537         return to suspend ready for the next test. */
00538         if( xSemaphoreGive( xMutex ) != pdPASS )
00539         {
00540             xErrorDetected = pdTRUE;
00541         }       
00542     }
00543 }

static void prvLowPriorityMutexTask ( void *  pvParameters  )  [static]

Definition at line 402 of file GenQTest.c.

References genqMUTEX_HIGH_PRIORITY, genqMUTEX_LOW_PRIORITY, genqMUTEX_TEST_PRIORITY, genqNO_BLOCK, pdPASS, pdTRUE, portCHAR, taskYIELD, ulGuardedVariable, ulLoopCounter2, uxTaskPriorityGet(), vPrintDisplayMessage(), vTaskPrioritySet(), vTaskResume(), xErrorDetected, xHighPriorityMutexTask, xMediumPriorityMutexTask, xMutex, xSemaphoreGive, and xSemaphoreTake.

00403 {
00404 xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;
00405 
00406     #ifdef USE_STDIO
00407     void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
00408     
00409         const portCHAR * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";
00410 
00411         /* Queue a message for printing to say the task has started. */
00412         vPrintDisplayMessage( &pcTaskStartMsg );
00413     #endif
00414 
00415     for( ;; )
00416     {
00417         /* Take the mutex.  It should be available now. */
00418         if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
00419         {
00420             xErrorDetected = pdTRUE;
00421         }
00422 
00423         /* Set our guarded variable to a known start value. */
00424         ulGuardedVariable = 0;
00425 
00426         /* Our priority should be as per that assigned when the task was
00427         created. */
00428         if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
00429         {
00430             xErrorDetected = pdTRUE;
00431         }
00432 
00433         /* Now unsuspend the high priority task.  This will attempt to take the
00434         mutex, and block when it finds it cannot obtain it. */
00435         vTaskResume( xHighPriorityMutexTask );
00436 
00437         /* We should now have inherited the prioritoy of the high priority task,
00438         as by now it will have attempted to get the mutex. */
00439         if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
00440         {
00441             xErrorDetected = pdTRUE;
00442         }
00443 
00444         /* We can attempt to set our priority to the test priority - between the
00445         idle priority and the medium/high test priorities, but our actual
00446         prioroity should remain at the high priority. */
00447         vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
00448         if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
00449         {
00450             xErrorDetected = pdTRUE;
00451         }
00452 
00453         /* Now unsuspend the medium priority task.  This should not run as our
00454         inherited priority is above that of the medium priority task. */
00455         vTaskResume( xMediumPriorityMutexTask );
00456 
00457         /* If the did run then it will have incremented our guarded variable. */
00458         if( ulGuardedVariable != 0 )
00459         {
00460             xErrorDetected = pdTRUE;
00461         }
00462 
00463         /* When we give back the semaphore our priority should be disinherited
00464         back to the priority to which we attempted to set ourselves.  This means
00465         that when the high priority task next blocks, the medium priority task
00466         should execute and increment the guarded variable.   When we next run
00467         both the high and medium priority tasks will have been suspended again. */
00468         if( xSemaphoreGive( xMutex ) != pdPASS )
00469         {
00470             xErrorDetected = pdTRUE;
00471         }
00472 
00473         /* Check that the guarded variable did indeed increment... */
00474         if( ulGuardedVariable != 1 )
00475         {
00476             xErrorDetected = pdTRUE;
00477         }
00478 
00479         /* ... and that our priority has been disinherited to
00480         genqMUTEX_TEST_PRIORITY. */
00481         if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
00482         {
00483             xErrorDetected = pdTRUE;
00484         }
00485 
00486         /* Set our priority back to our original priority ready for the next
00487         loop around this test. */
00488         vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
00489 
00490         /* Just to show we are still running. */
00491         ulLoopCounter2++;
00492 
00493         #if configUSE_PREEMPTION == 0
00494             taskYIELD();
00495         #endif      
00496     }
00497 }

static void prvMediumPriorityMutexTask ( void *  pvParameters  )  [static]

Definition at line 500 of file GenQTest.c.

References ulGuardedVariable, and vTaskSuspend().

00501 {
00502     ( void ) pvParameters;
00503 
00504     for( ;; )
00505     {
00506         /* The medium priority task starts by suspending itself.  The low
00507         priority task will unsuspend this task when required. */
00508         vTaskSuspend( NULL );
00509 
00510         /* When this task unsuspends all it does is increment the guarded
00511         variable, this is so the low priority task knows that it has
00512         executed. */
00513         ulGuardedVariable++;
00514     }
00515 }

static void prvSendFrontAndBackTest ( void *  pvParameters  )  [static]

Definition at line 174 of file GenQTest.c.

References errQUEUE_FULL, genqNO_BLOCK, genqQUEUE_LENGTH, pdPASS, pdTRUE, portCHAR, portLONG, taskYIELD, ulLoopCounter, uxQueueMessagesWaiting(), vPrintDisplayMessage(), xErrorDetected, xQueuePeek, xQueueReceive, xQueueSend, xQueueSendToBack, and xQueueSendToFront.

00175 {
00176 unsigned portLONG ulData, ulData2;
00177 xQueueHandle xQueue;
00178 
00179     #ifdef USE_STDIO
00180     void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
00181     
00182         const portCHAR * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n";
00183 
00184         /* Queue a message for printing to say the task has started. */
00185         vPrintDisplayMessage( &pcTaskStartMsg );
00186     #endif
00187 
00188     xQueue = ( xQueueHandle ) pvParameters;
00189 
00190     for( ;; )
00191     {
00192         /* The queue is empty, so sending an item to the back of the queue
00193         should have the same efect as sending it to the front of the queue.
00194 
00195         First send to the front and check everything is as expected. */
00196         xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );
00197 
00198         if( uxQueueMessagesWaiting( xQueue ) != 1 )
00199         {
00200             xErrorDetected = pdTRUE;
00201         }
00202 
00203         if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )
00204         {
00205             xErrorDetected = pdTRUE;
00206         }
00207 
00208         /* The data we sent to the queue should equal the data we just received
00209         from the queue. */
00210         if( ulLoopCounter != ulData )
00211         {
00212             xErrorDetected = pdTRUE;
00213         }
00214 
00215         /* Then do the same, sending the data to the back, checking everything
00216         is as expected. */
00217         if( uxQueueMessagesWaiting( xQueue ) != 0 )
00218         {
00219             xErrorDetected = pdTRUE;
00220         }
00221 
00222         xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );
00223 
00224         if( uxQueueMessagesWaiting( xQueue ) != 1 )
00225         {
00226             xErrorDetected = pdTRUE;
00227         }
00228 
00229         if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )
00230         {
00231             xErrorDetected = pdTRUE;
00232         }
00233 
00234         if( uxQueueMessagesWaiting( xQueue ) != 0 )
00235         {
00236             xErrorDetected = pdTRUE;
00237         }
00238 
00239         /* The data we sent to the queue should equal the data we just received
00240         from the queue. */
00241         if( ulLoopCounter != ulData )
00242         {
00243             xErrorDetected = pdTRUE;
00244         }
00245 
00246         #if configUSE_PREEMPTION == 0
00247             taskYIELD();
00248         #endif
00249 
00250 
00251 
00252         /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */
00253         for( ulData = 2; ulData < 5; ulData++ )
00254         {
00255             xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );
00256         }
00257 
00258         /* Now the order in the queue should be 2, 3, 4, with 2 being the first
00259         thing to be read out.  Now add 1 then 0 to the front of the queue. */
00260         if( uxQueueMessagesWaiting( xQueue ) != 3 )
00261         {
00262             xErrorDetected = pdTRUE;
00263         }
00264         ulData = 1;
00265         xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );
00266         ulData = 0;
00267         xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );
00268 
00269         /* Now the queue should be full, and when we read the data out we
00270         should receive 0, 1, 2, 3, 4. */
00271         if( uxQueueMessagesWaiting( xQueue ) != 5 )
00272         {
00273             xErrorDetected = pdTRUE;
00274         }
00275 
00276         if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
00277         {
00278             xErrorDetected = pdTRUE;
00279         }
00280 
00281         if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
00282         {
00283             xErrorDetected = pdTRUE;
00284         }
00285 
00286         #if configUSE_PREEMPTION == 0
00287             taskYIELD();
00288         #endif
00289 
00290         /* Check the data we read out is in the expected order. */
00291         for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )
00292         {
00293             /* Try peeking the data first. */
00294             if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
00295             {
00296                 xErrorDetected = pdTRUE;
00297             }
00298 
00299             if( ulData != ulData2 )
00300             {
00301                 xErrorDetected = pdTRUE;
00302             }
00303             
00304 
00305             /* Now try receiving the data for real.  The value should be the
00306             same.  Clobber the value first so we know we really received it. */
00307             ulData2 = ~ulData2;
00308             if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
00309             {
00310                 xErrorDetected = pdTRUE;
00311             }
00312 
00313             if( ulData != ulData2 )
00314             {
00315                 xErrorDetected = pdTRUE;
00316             }
00317         }
00318 
00319         /* The queue should now be empty again. */
00320         if( uxQueueMessagesWaiting( xQueue ) != 0 )
00321         {
00322             xErrorDetected = pdTRUE;
00323         }
00324 
00325         #if configUSE_PREEMPTION == 0
00326             taskYIELD();
00327         #endif
00328 
00329 
00330         /* Our queue is empty once more, add 10, 11 to the back. */
00331         ulData = 10;
00332         if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )
00333         {
00334             xErrorDetected = pdTRUE;
00335         }
00336         ulData = 11;
00337         if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )
00338         {
00339             xErrorDetected = pdTRUE;
00340         }
00341 
00342         if( uxQueueMessagesWaiting( xQueue ) != 2 )
00343         {
00344             xErrorDetected = pdTRUE;
00345         }
00346 
00347         /* Now we should have 10, 11 in the queue.  Add 7, 8, 9 to the
00348         front. */
00349         for( ulData = 9; ulData >= 7; ulData-- )
00350         {
00351             if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )
00352             {
00353                 xErrorDetected = pdTRUE;
00354             }
00355         }
00356 
00357         /* Now check that the queue is full, and that receiving data provides
00358         the expected sequence of 7, 8, 9, 10, 11. */
00359         if( uxQueueMessagesWaiting( xQueue ) != 5 )
00360         {
00361             xErrorDetected = pdTRUE;
00362         }
00363 
00364         if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
00365         {
00366             xErrorDetected = pdTRUE;
00367         }
00368 
00369         if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
00370         {
00371             xErrorDetected = pdTRUE;
00372         }
00373 
00374         #if configUSE_PREEMPTION == 0
00375             taskYIELD();
00376         #endif
00377 
00378         /* Check the data we read out is in the expected order. */
00379         for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )
00380         {
00381             if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
00382             {
00383                 xErrorDetected = pdTRUE;
00384             }
00385 
00386             if( ulData != ulData2 )
00387             {
00388                 xErrorDetected = pdTRUE;
00389             }
00390         }
00391 
00392         if( uxQueueMessagesWaiting( xQueue ) != 0 )
00393         {
00394             xErrorDetected = pdTRUE;
00395         }
00396 
00397         ulLoopCounter++;
00398     }
00399 }

void vStartGenericQueueTasks ( unsigned portBASE_TYPE  uxPriority  ) 

Definition at line 132 of file GenQTest.c.

References configMINIMAL_STACK_SIZE, genqMUTEX_HIGH_PRIORITY, genqMUTEX_LOW_PRIORITY, genqMUTEX_MEDIUM_PRIORITY, genqQUEUE_LENGTH, portCHAR, portLONG, prvHighPriorityMutexTask(), prvLowPriorityMutexTask(), prvMediumPriorityMutexTask(), prvSendFrontAndBackTest(), vQueueAddToRegistry, xHighPriorityMutexTask, xMediumPriorityMutexTask, xMutex, xQueueCreate(), xSemaphoreCreateMutex, and xTaskCreate.

00133 {
00134 xQueueHandle xQueue;
00135 xSemaphoreHandle xMutex;
00136 
00137     /* Create the queue that we are going to use for the
00138     prvSendFrontAndBackTest demo. */
00139     xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( unsigned portLONG ) );
00140 
00141     /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
00142     in use.  The queue registry is provided as a means for kernel aware 
00143     debuggers to locate queues and has no purpose if a kernel aware debugger
00144     is not being used.  The call to vQueueAddToRegistry() will be removed
00145     by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is 
00146     defined to be less than 1. */
00147     vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "Gen_Queue_Test" );
00148 
00149     /* Create the demo task and pass it the queue just created.  We are
00150     passing the queue handle by value so it does not matter that it is
00151     declared on the stack here. */
00152     xTaskCreate( prvSendFrontAndBackTest, ( signed portCHAR * )"GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );
00153 
00154     /* Create the mutex used by the prvMutexTest task. */
00155     xMutex = xSemaphoreCreateMutex();
00156 
00157     /* vQueueAddToRegistry() adds the mutex to the registry, if one is
00158     in use.  The registry is provided as a means for kernel aware 
00159     debuggers to locate mutexes and has no purpose if a kernel aware debugger
00160     is not being used.  The call to vQueueAddToRegistry() will be removed
00161     by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is 
00162     defined to be less than 1. */
00163     vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Gen_Queue_Mutex" );
00164 
00165     /* Create the mutex demo tasks and pass it the mutex just created.  We are
00166     passing the mutex handle by value so it does not matter that it is declared
00167     on the stack here. */
00168     xTaskCreate( prvLowPriorityMutexTask, ( signed portCHAR * )"MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
00169     xTaskCreate( prvMediumPriorityMutexTask, ( signed portCHAR * )"MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
00170     xTaskCreate( prvHighPriorityMutexTask, ( signed portCHAR * )"MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
00171 }

portBASE_TYPE xAreGenericQueueTasksStillRunning ( void   ) 

Definition at line 547 of file GenQTest.c.

References pdTRUE, portLONG, ulLoopCounter, ulLoopCounter2, and xErrorDetected.

00548 {
00549 static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
00550 
00551     /* If the demo task is still running then we expect the loopcounters to
00552     have incremented since this function was last called. */
00553     if( ulLastLoopCounter == ulLoopCounter )
00554     {
00555         xErrorDetected = pdTRUE;
00556     }
00557 
00558     if( ulLastLoopCounter2 == ulLoopCounter2 )
00559     {
00560         xErrorDetected = pdTRUE;
00561     }
00562 
00563     ulLastLoopCounter = ulLoopCounter;
00564     ulLastLoopCounter2 = ulLoopCounter2;    
00565 
00566     /* Errors detected in the task itself will have latched xErrorDetected
00567     to true. */
00568 
00569     return !xErrorDetected;
00570 }


Variable Documentation

volatile unsigned portLONG ulGuardedVariable = 0 [static]

Definition at line 124 of file GenQTest.c.

volatile unsigned portLONG ulLoopCounter = 0 [static]

Definition at line 120 of file GenQTest.c.

volatile unsigned portLONG ulLoopCounter2 = 0 [static]

Definition at line 121 of file GenQTest.c.

portBASE_TYPE xErrorDetected = pdFALSE [static]

Definition at line 116 of file GenQTest.c.

Definition at line 128 of file GenQTest.c.

Definition at line 128 of file GenQTest.c.


Generated on Thu Dec 17 20:02:01 2009 for AVR32 UC3 - FreeRTOS Real Time Kernel by  doxygen 1.5.5