AltQTest.c File Reference

#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "AltQTest.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 vStartAltGenericQueueTasks (unsigned portBASE_TYPE uxPriority)
portBASE_TYPE xAreAltGenericQueueTasksStillRunning (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 )

#define genqMUTEX_LOW_PRIORITY   ( tskIDLE_PRIORITY )

#define genqMUTEX_MEDIUM_PRIORITY   ( tskIDLE_PRIORITY + 2 )

Definition at line 79 of file AltQTest.c.

Referenced by vStartAltGenericQueueTasks(), and vStartGenericQueueTasks().

#define genqMUTEX_TEST_PRIORITY   ( tskIDLE_PRIORITY + 1 )

Definition at line 78 of file AltQTest.c.

Referenced by prvLowPriorityMutexTask().

#define genqNO_BLOCK   ( 0 )

Definition at line 75 of file AltQTest.c.

Referenced by prvLowPriorityMutexTask(), and prvSendFrontAndBackTest().

#define genqQUEUE_LENGTH   ( 5 )


Function Documentation

static void prvHighPriorityMutexTask ( void *  pvParameters  )  [static]

Definition at line 519 of file AltQTest.c.

References pdPASS, pdTRUE, portMAX_DELAY, vTaskSuspend(), xErrorDetected, xMutex, xSemaphoreAltGive, and xSemaphoreAltTake.

Referenced by vStartAltGenericQueueTasks(), and vStartGenericQueueTasks().

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

static void prvLowPriorityMutexTask ( void *  pvParameters  )  [static]

Definition at line 400 of file AltQTest.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, xSemaphoreAltGive, and xSemaphoreAltTake.

Referenced by vStartAltGenericQueueTasks(), and vStartGenericQueueTasks().

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

static void prvMediumPriorityMutexTask ( void *  pvParameters  )  [static]

Definition at line 501 of file AltQTest.c.

References ulGuardedVariable, and vTaskSuspend().

Referenced by vStartAltGenericQueueTasks(), and vStartGenericQueueTasks().

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

static void prvSendFrontAndBackTest ( void *  pvParameters  )  [static]

Definition at line 172 of file AltQTest.c.

References errQUEUE_FULL, genqNO_BLOCK, genqQUEUE_LENGTH, pdPASS, pdTRUE, portCHAR, portLONG, taskYIELD, ulLoopCounter, uxQueueMessagesWaiting(), vPrintDisplayMessage(), xErrorDetected, xQueueAltPeek, xQueueAltReceive, xQueueAltSendToBack, and xQueueAltSendToFront.

Referenced by vStartAltGenericQueueTasks(), and vStartGenericQueueTasks().

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

void vStartAltGenericQueueTasks ( unsigned portBASE_TYPE  uxPriority  ) 

Definition at line 130 of file AltQTest.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.

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

portBASE_TYPE xAreAltGenericQueueTasksStillRunning ( void   ) 

Definition at line 550 of file AltQTest.c.

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

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


Variable Documentation

volatile unsigned portLONG ulGuardedVariable = 0 [static]

Definition at line 122 of file AltQTest.c.

Referenced by prvLowPriorityMutexTask(), and prvMediumPriorityMutexTask().

volatile unsigned portLONG ulLoopCounter = 0 [static]

volatile unsigned portLONG ulLoopCounter2 = 0 [static]

portBASE_TYPE xErrorDetected = pdFALSE [static]


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