AltBlock.c File Reference

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "AltBlock.h"

Go to the source code of this file.

Defines

#define bktALLOWABLE_MARGIN   ( 12 )
#define bktDONT_BLOCK   ( ( portTickType ) 0 )
#define bktPRIMARY_BLOCK_TIME   ( 10 )
#define bktPRIMARY_PRIORITY   ( 3 )
#define bktQUEUE_LENGTH   ( 5 )
#define bktRUN_INDICATOR   ( ( unsigned portBASE_TYPE ) 0x55 )
#define bktSECONDARY_PRIORITY   ( 2 )
#define bktSHORT_WAIT   ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )
#define bktTIME_TO_BLOCK   ( 175 )

Functions

void vCreateAltBlockTimeTasks (void)
static void vPrimaryBlockTimeTestTask (void *pvParameters)
static void vSecondaryBlockTimeTestTask (void *pvParameters)
portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning (void)

Variables

static portBASE_TYPE xErrorOccurred = pdFALSE
static portBASE_TYPE xPrimaryCycles = 0
static volatile unsigned
portBASE_TYPE 
xRunIndicator
static xTaskHandle xSecondary
static portBASE_TYPE xSecondaryCycles = 0
static xQueueHandle xTestQueue


Define Documentation

#define bktALLOWABLE_MARGIN   ( 12 )

Definition at line 78 of file AltBlock.c.

Referenced by vPrimaryBlockTimeTestTask(), and vSecondaryBlockTimeTestTask().

#define bktDONT_BLOCK   ( ( portTickType ) 0 )

Definition at line 80 of file AltBlock.c.

Referenced by vPrimaryBlockTimeTestTask().

#define bktPRIMARY_BLOCK_TIME   ( 10 )

Definition at line 77 of file AltBlock.c.

Referenced by vPrimaryBlockTimeTestTask().

#define bktPRIMARY_PRIORITY   ( 3 )

#define bktQUEUE_LENGTH   ( 5 )

#define bktRUN_INDICATOR   ( ( unsigned portBASE_TYPE ) 0x55 )

Definition at line 81 of file AltBlock.c.

Referenced by vPrimaryBlockTimeTestTask(), and vSecondaryBlockTimeTestTask().

#define bktSECONDARY_PRIORITY   ( 2 )

#define bktSHORT_WAIT   ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )

Definition at line 76 of file AltBlock.c.

Referenced by vPrimaryBlockTimeTestTask().

#define bktTIME_TO_BLOCK   ( 175 )

Definition at line 79 of file AltBlock.c.

Referenced by vSecondaryBlockTimeTestTask().


Function Documentation

void vCreateAltBlockTimeTasks ( void   ) 

Definition at line 104 of file AltBlock.c.

References bktPRIMARY_PRIORITY, bktQUEUE_LENGTH, bktSECONDARY_PRIORITY, configMINIMAL_STACK_SIZE, portBASE_TYPE, portCHAR, vPrimaryBlockTimeTestTask(), vQueueAddToRegistry, vSecondaryBlockTimeTestTask(), xQueueCreate(), xSecondary, xTaskCreate, and xTestQueue.

00105 {
00106     /* Create the queue on which the two tasks block. */
00107     xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );
00108 
00109     /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
00110     in use.  The queue registry is provided as a means for kernel aware 
00111     debuggers to locate queues and has no purpose if a kernel aware debugger
00112     is not being used.  The call to vQueueAddToRegistry() will be removed
00113     by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is 
00114     defined to be less than 1. */
00115     vQueueAddToRegistry( xTestQueue, ( signed portCHAR * ) "AltBlockQueue" );
00116 
00117 
00118     /* Create the two test tasks. */
00119     xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
00120     xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
00121 }

static void vPrimaryBlockTimeTestTask ( void *  pvParameters  )  [static]

Definition at line 124 of file AltBlock.c.

References bktALLOWABLE_MARGIN, bktDONT_BLOCK, bktPRIMARY_BLOCK_TIME, bktPRIMARY_PRIORITY, bktQUEUE_LENGTH, bktRUN_INDICATOR, bktSECONDARY_PRIORITY, bktSHORT_WAIT, errQUEUE_EMPTY, errQUEUE_FULL, pdPASS, pdTRUE, portBASE_TYPE, portCHAR, portENTER_CRITICAL, portEXIT_CRITICAL, taskYIELD, vPrintDisplayMessage(), vTaskDelay(), vTaskPrioritySet(), vTaskResume(), xErrorOccurred, xPrimaryCycles, xQueueAltReceive, xQueueAltSendToBack, xRunIndicator, xSecondary, xTaskGetTickCount(), and xTestQueue.

Referenced by vCreateAltBlockTimeTasks(), and vCreateBlockTimeTasks().

00125 {
00126 portBASE_TYPE xItem, xData;
00127 portTickType xTimeWhenBlocking;
00128 portTickType xTimeToBlock, xBlockedTime;
00129 
00130     #ifdef USE_STDIO
00131     void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
00132     
00133         const portCHAR * const pcTaskStartMsg = "Alt primary block time test started.\r\n";
00134 
00135         /* Queue a message for printing to say the task has started. */
00136         vPrintDisplayMessage( &pcTaskStartMsg );
00137     #endif
00138 
00139     ( void ) pvParameters;
00140 
00141     for( ;; )
00142     {
00143         /*********************************************************************
00144         Test 1
00145 
00146         Simple block time wakeup test on queue receives. */
00147         for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
00148         {
00149             /* The queue is empty. Attempt to read from the queue using a block
00150             time.  When we wake, ensure the delta in time is as expected. */
00151             xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
00152 
00153             /* A critical section is used to minimise the jitter in the time
00154             measurements. */
00155             portENTER_CRITICAL();
00156             {
00157                 xTimeWhenBlocking = xTaskGetTickCount();
00158                 
00159                 /* We should unblock after xTimeToBlock having not received
00160                 anything on the queue. */
00161                 if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
00162                 {
00163                     xErrorOccurred = pdTRUE;
00164                 }
00165 
00166                 /* How long were we blocked for? */
00167                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
00168             }
00169             portEXIT_CRITICAL();
00170 
00171             if( xBlockedTime < xTimeToBlock )
00172             {
00173                 /* Should not have blocked for less than we requested. */
00174                 xErrorOccurred = pdTRUE;
00175             }
00176 
00177             if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
00178             {
00179                 /* Should not have blocked for longer than we requested,
00180                 although we would not necessarily run as soon as we were
00181                 unblocked so a margin is allowed. */
00182                 xErrorOccurred = pdTRUE;
00183             }
00184         }
00185 
00186 
00187         #if configUSE_PREEMPTION == 0
00188             taskYIELD();
00189         #endif
00190 
00191 
00192         /*********************************************************************
00193         Test 2
00194 
00195         Simple block time wakeup test on queue sends.
00196 
00197         First fill the queue.  It should be empty so all sends should pass. */
00198         for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
00199         {
00200             if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
00201             {
00202                 xErrorOccurred = pdTRUE;
00203             }
00204         }
00205 
00206         for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
00207         {
00208             /* The queue is full. Attempt to write to the queue using a block
00209             time.  When we wake, ensure the delta in time is as expected. */
00210             xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
00211 
00212             portENTER_CRITICAL();
00213             {
00214                 xTimeWhenBlocking = xTaskGetTickCount();
00215                 
00216                 /* We should unblock after xTimeToBlock having not received
00217                 anything on the queue. */
00218                 if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
00219                 {
00220                     xErrorOccurred = pdTRUE;
00221                 }
00222 
00223                 /* How long were we blocked for? */
00224                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
00225             }
00226             portEXIT_CRITICAL();
00227 
00228             if( xBlockedTime < xTimeToBlock )
00229             {
00230                 /* Should not have blocked for less than we requested. */
00231                 xErrorOccurred = pdTRUE;
00232             }
00233 
00234             if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
00235             {
00236                 /* Should not have blocked for longer than we requested,
00237                 although we would not necessarily run as soon as we were
00238                 unblocked so a margin is allowed. */
00239                 xErrorOccurred = pdTRUE;
00240             }
00241         }
00242 
00243         #if configUSE_PREEMPTION == 0
00244             taskYIELD();
00245         #endif
00246 
00247         
00248         /*********************************************************************
00249         Test 3
00250 
00251         Wake the other task, it will block attempting to post to the queue.
00252         When we read from the queue the other task will wake, but before it
00253         can run we will post to the queue again.  When the other task runs it
00254         will find the queue still full, even though it was woken.  It should
00255         recognise that its block time has not expired and return to block for
00256         the remains of its block time.
00257 
00258         Wake the other task so it blocks attempting to post to the already
00259         full queue. */
00260         xRunIndicator = 0;
00261         vTaskResume( xSecondary );
00262 
00263         /* We need to wait a little to ensure the other task executes. */
00264         while( xRunIndicator != bktRUN_INDICATOR )
00265         {
00266             /* The other task has not yet executed. */
00267             vTaskDelay( bktSHORT_WAIT );
00268         }
00269         /* Make sure the other task is blocked on the queue. */
00270         vTaskDelay( bktSHORT_WAIT );
00271         xRunIndicator = 0;
00272 
00273         for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
00274         {
00275             /* Now when we make space on the queue the other task should wake
00276             but not execute as this task has higher priority. */                
00277             if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
00278             {
00279                 xErrorOccurred = pdTRUE;
00280             }
00281 
00282             /* Now fill the queue again before the other task gets a chance to
00283             execute.  If the other task had executed we would find the queue
00284             full ourselves, and the other task have set xRunIndicator. */
00285             if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
00286             {
00287                 xErrorOccurred = pdTRUE;
00288             }
00289 
00290             if( xRunIndicator == bktRUN_INDICATOR )
00291             {
00292                 /* The other task should not have executed. */
00293                 xErrorOccurred = pdTRUE;
00294             }
00295 
00296             /* Raise the priority of the other task so it executes and blocks
00297             on the queue again. */
00298             vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
00299 
00300             /* The other task should now have re-blocked without exiting the
00301             queue function. */
00302             if( xRunIndicator == bktRUN_INDICATOR )
00303             {
00304                 /* The other task should not have executed outside of the
00305                 queue function. */
00306                 xErrorOccurred = pdTRUE;
00307             }
00308 
00309             /* Set the priority back down. */
00310             vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );          
00311         }
00312 
00313         /* Let the other task timeout.  When it unblockes it will check that it
00314         unblocked at the correct time, then suspend itself. */
00315         while( xRunIndicator != bktRUN_INDICATOR )
00316         {
00317             vTaskDelay( bktSHORT_WAIT );
00318         }
00319         vTaskDelay( bktSHORT_WAIT );
00320         xRunIndicator = 0;
00321 
00322         #if configUSE_PREEMPTION == 0
00323             taskYIELD();
00324         #endif
00325 
00326         /*********************************************************************
00327         Test 4
00328 
00329         As per test 3 - but with the send and receive the other way around.
00330         The other task blocks attempting to read from the queue.
00331 
00332         Empty the queue.  We should find that it is full. */
00333         for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
00334         {
00335             if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
00336             {
00337                 xErrorOccurred = pdTRUE;
00338             }
00339         }
00340         
00341         /* Wake the other task so it blocks attempting to read from  the
00342         already empty queue. */
00343         vTaskResume( xSecondary );
00344 
00345         /* We need to wait a little to ensure the other task executes. */
00346         while( xRunIndicator != bktRUN_INDICATOR )
00347         {
00348             vTaskDelay( bktSHORT_WAIT );
00349         }
00350         vTaskDelay( bktSHORT_WAIT );
00351         xRunIndicator = 0;
00352 
00353         for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
00354         {
00355             /* Now when we place an item on the queue the other task should
00356             wake but not execute as this task has higher priority. */               
00357             if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
00358             {
00359                 xErrorOccurred = pdTRUE;
00360             }
00361 
00362             /* Now empty the queue again before the other task gets a chance to
00363             execute.  If the other task had executed we would find the queue
00364             empty ourselves, and the other task would be suspended. */
00365             if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
00366             {
00367                 xErrorOccurred = pdTRUE;
00368             }
00369 
00370             if( xRunIndicator == bktRUN_INDICATOR )
00371             {
00372                 /* The other task should not have executed. */
00373                 xErrorOccurred = pdTRUE;
00374             }
00375 
00376             /* Raise the priority of the other task so it executes and blocks
00377             on the queue again. */
00378             vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
00379 
00380             /* The other task should now have re-blocked without exiting the
00381             queue function. */
00382             if( xRunIndicator == bktRUN_INDICATOR )
00383             {
00384                 /* The other task should not have executed outside of the
00385                 queue function. */
00386                 xErrorOccurred = pdTRUE;
00387             }
00388             vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );          
00389         }
00390 
00391         /* Let the other task timeout.  When it unblockes it will check that it
00392         unblocked at the correct time, then suspend itself. */
00393         while( xRunIndicator != bktRUN_INDICATOR )
00394         {
00395             vTaskDelay( bktSHORT_WAIT );
00396         }
00397         vTaskDelay( bktSHORT_WAIT );
00398 
00399         xPrimaryCycles++;
00400     }
00401 }

static void vSecondaryBlockTimeTestTask ( void *  pvParameters  )  [static]

Definition at line 404 of file AltBlock.c.

References bktALLOWABLE_MARGIN, bktRUN_INDICATOR, bktTIME_TO_BLOCK, errQUEUE_EMPTY, errQUEUE_FULL, pdTRUE, portBASE_TYPE, portCHAR, portENTER_CRITICAL, portEXIT_CRITICAL, vPrintDisplayMessage(), vTaskSuspend(), xErrorOccurred, xQueueAltReceive, xQueueAltSendToBack, xRunIndicator, xSecondaryCycles, xTaskGetTickCount(), and xTestQueue.

Referenced by vCreateAltBlockTimeTasks(), and vCreateBlockTimeTasks().

00405 {
00406 portTickType xTimeWhenBlocking, xBlockedTime;
00407 portBASE_TYPE xData;
00408 
00409     #ifdef USE_STDIO
00410     void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
00411     
00412         const portCHAR * const pcTaskStartMsg = "Alt secondary block time test started.\r\n";
00413 
00414         /* Queue a message for printing to say the task has started. */
00415         vPrintDisplayMessage( &pcTaskStartMsg );
00416     #endif
00417 
00418     ( void ) pvParameters;
00419 
00420     for( ;; )
00421     {
00422         /*********************************************************************
00423         Test 1 and 2
00424 
00425         This task does does not participate in these tests. */
00426         vTaskSuspend( NULL );
00427 
00428         /*********************************************************************
00429         Test 3
00430 
00431         The first thing we do is attempt to read from the queue.  It should be
00432         full so we block.  Note the time before we block so we can check the
00433         wake time is as per that expected. */
00434         portENTER_CRITICAL();
00435         {
00436             xTimeWhenBlocking = xTaskGetTickCount();
00437             
00438             /* We should unblock after bktTIME_TO_BLOCK having not received
00439             anything on the queue. */
00440             xData = 0;
00441             xRunIndicator = bktRUN_INDICATOR;
00442             if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
00443             {
00444                 xErrorOccurred = pdTRUE;
00445             }
00446 
00447             /* How long were we inside the send function? */
00448             xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
00449         }
00450         portEXIT_CRITICAL();
00451 
00452         /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
00453         if( xBlockedTime < bktTIME_TO_BLOCK )
00454         {
00455             xErrorOccurred = pdTRUE;
00456         }
00457 
00458         /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
00459         either.  A margin is permitted as we would not necessarily run as
00460         soon as we unblocked. */
00461         if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
00462         {
00463             xErrorOccurred = pdTRUE;
00464         }
00465 
00466         /* Suspend ready for test 3. */
00467         xRunIndicator = bktRUN_INDICATOR;
00468         vTaskSuspend( NULL );
00469 
00470         /*********************************************************************
00471         Test 4
00472 
00473         As per test three, but with the send and receive reversed. */
00474         portENTER_CRITICAL();
00475         {
00476             xTimeWhenBlocking = xTaskGetTickCount();
00477             
00478             /* We should unblock after bktTIME_TO_BLOCK having not received
00479             anything on the queue. */
00480             xRunIndicator = bktRUN_INDICATOR;
00481             if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
00482             {
00483                 xErrorOccurred = pdTRUE;
00484             }
00485 
00486             xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
00487         }
00488         portEXIT_CRITICAL();
00489 
00490         /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
00491         if( xBlockedTime < bktTIME_TO_BLOCK )
00492         {
00493             xErrorOccurred = pdTRUE;
00494         }
00495 
00496         /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
00497         either.  A margin is permitted as we would not necessarily run as soon
00498         as we unblocked. */
00499         if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
00500         {
00501             xErrorOccurred = pdTRUE;
00502         }
00503 
00504         xRunIndicator = bktRUN_INDICATOR;
00505 
00506         xSecondaryCycles++;
00507     }
00508 }

portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning ( void   ) 

Definition at line 511 of file AltBlock.c.

References pdFAIL, pdPASS, pdTRUE, portBASE_TYPE, xErrorOccurred, xPrimaryCycles, and xSecondaryCycles.

00512 {
00513 static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
00514 portBASE_TYPE xReturn = pdPASS;
00515 
00516     /* Have both tasks performed at least one cycle since this function was
00517     last called? */
00518     if( xPrimaryCycles == xLastPrimaryCycleCount )
00519     {
00520         xReturn = pdFAIL;
00521     }
00522 
00523     if( xSecondaryCycles == xLastSecondaryCycleCount )
00524     {
00525         xReturn = pdFAIL;
00526     }
00527 
00528     if( xErrorOccurred == pdTRUE )
00529     {
00530         xReturn = pdFAIL;
00531     }
00532 
00533     xLastSecondaryCycleCount = xSecondaryCycles;
00534     xLastPrimaryCycleCount = xPrimaryCycles;
00535 
00536     return xReturn;
00537 }


Variable Documentation

portBASE_TYPE xErrorOccurred = pdFALSE [static]

portBASE_TYPE xPrimaryCycles = 0 [static]

volatile unsigned portBASE_TYPE xRunIndicator [static]

Definition at line 96 of file AltBlock.c.

Referenced by vPrimaryBlockTimeTestTask(), and vSecondaryBlockTimeTestTask().

portBASE_TYPE xSecondaryCycles = 0 [static]


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