blocktim.c File Reference

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

Go to the source code of this file.

Defines

#define bktALLOWABLE_MARGIN   ( 15 )
#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 vCreateBlockTimeTasks (void)
static void vPrimaryBlockTimeTestTask (void *pvParameters)
static void vSecondaryBlockTimeTestTask (void *pvParameters)
portBASE_TYPE xAreBlockTimeTestTasksStillRunning (void)

Variables

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


Define Documentation

#define bktALLOWABLE_MARGIN   ( 15 )

Definition at line 81 of file blocktim.c.

#define bktDONT_BLOCK   ( ( portTickType ) 0 )

Definition at line 83 of file blocktim.c.

#define bktPRIMARY_BLOCK_TIME   ( 10 )

Definition at line 80 of file blocktim.c.

#define bktPRIMARY_PRIORITY   ( 3 )

Definition at line 70 of file blocktim.c.

#define bktQUEUE_LENGTH   ( 5 )

Definition at line 78 of file blocktim.c.

#define bktRUN_INDICATOR   ( ( unsigned portBASE_TYPE ) 0x55 )

Definition at line 84 of file blocktim.c.

#define bktSECONDARY_PRIORITY   ( 2 )

Definition at line 74 of file blocktim.c.

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

Definition at line 79 of file blocktim.c.

#define bktTIME_TO_BLOCK   ( 175 )

Definition at line 82 of file blocktim.c.


Function Documentation

void vCreateBlockTimeTasks ( void   ) 

Definition at line 107 of file blocktim.c.

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

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

static void vPrimaryBlockTimeTestTask ( void *  pvParameters  )  [static]

Definition at line 126 of file blocktim.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, taskYIELD, vTaskDelay(), vTaskPrioritySet(), vTaskResume(), xErrorOccurred, xPrimaryCycles, xQueueReceive, xQueueSend, xRunIndicator, xSecondary, xTaskGetTickCount(), and xTestQueue.

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

static void vSecondaryBlockTimeTestTask ( void *  pvParameters  )  [static]

Definition at line 377 of file blocktim.c.

References bktALLOWABLE_MARGIN, bktRUN_INDICATOR, bktTIME_TO_BLOCK, errQUEUE_EMPTY, errQUEUE_FULL, pdTRUE, portBASE_TYPE, vTaskSuspend(), xErrorOccurred, xQueueReceive, xQueueSend, xRunIndicator, xSecondaryCycles, xTaskGetTickCount(), and xTestQueue.

00378 {
00379 portTickType xTimeWhenBlocking, xBlockedTime;
00380 portBASE_TYPE xData;
00381 
00382     ( void ) pvParameters;
00383 
00384     for( ;; )
00385     {
00386         /*********************************************************************
00387         Test 1 and 2
00388 
00389         This task does does not participate in these tests. */
00390         vTaskSuspend( NULL );
00391 
00392         /*********************************************************************
00393         Test 3
00394 
00395         The first thing we do is attempt to read from the queue.  It should be
00396         full so we block.  Note the time before we block so we can check the
00397         wake time is as per that expected. */
00398         xTimeWhenBlocking = xTaskGetTickCount();
00399 
00400         /* We should unblock after bktTIME_TO_BLOCK having not sent
00401         anything to the queue. */
00402         xData = 0;
00403         xRunIndicator = bktRUN_INDICATOR;
00404         if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
00405         {
00406             xErrorOccurred = pdTRUE;
00407         }
00408 
00409         /* How long were we inside the send function? */
00410         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
00411 
00412         /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
00413         if( xBlockedTime < bktTIME_TO_BLOCK )
00414         {
00415             xErrorOccurred = pdTRUE;
00416         }
00417 
00418         /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
00419         either.  A margin is permitted as we would not necessarily run as
00420         soon as we unblocked. */
00421         if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
00422         {
00423             xErrorOccurred = pdTRUE;
00424         }
00425 
00426         /* Suspend ready for test 3. */
00427         xRunIndicator = bktRUN_INDICATOR;
00428         vTaskSuspend( NULL );
00429 
00430         /*********************************************************************
00431         Test 4
00432 
00433         As per test three, but with the send and receive reversed. */
00434         xTimeWhenBlocking = xTaskGetTickCount();
00435 
00436         /* We should unblock after bktTIME_TO_BLOCK having not received
00437         anything on the queue. */
00438         xRunIndicator = bktRUN_INDICATOR;
00439         if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
00440         {
00441             xErrorOccurred = pdTRUE;
00442         }
00443 
00444         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
00445 
00446         /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
00447         if( xBlockedTime < bktTIME_TO_BLOCK )
00448         {
00449             xErrorOccurred = pdTRUE;
00450         }
00451 
00452         /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
00453         either.  A margin is permitted as we would not necessarily run as soon
00454         as we unblocked. */
00455         if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
00456         {
00457             xErrorOccurred = pdTRUE;
00458         }
00459 
00460         xRunIndicator = bktRUN_INDICATOR;
00461 
00462         xSecondaryCycles++;
00463     }
00464 }

portBASE_TYPE xAreBlockTimeTestTasksStillRunning ( void   ) 

Definition at line 467 of file blocktim.c.

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

00468 {
00469 static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
00470 portBASE_TYPE xReturn = pdPASS;
00471 
00472     /* Have both tasks performed at least one cycle since this function was
00473     last called? */
00474     if( xPrimaryCycles == xLastPrimaryCycleCount )
00475     {
00476         xReturn = pdFAIL;
00477     }
00478 
00479     if( xSecondaryCycles == xLastSecondaryCycleCount )
00480     {
00481         xReturn = pdFAIL;
00482     }
00483 
00484     if( xErrorOccurred == pdTRUE )
00485     {
00486         xReturn = pdFAIL;
00487     }
00488 
00489     xLastSecondaryCycleCount = xSecondaryCycles;
00490     xLastPrimaryCycleCount = xPrimaryCycles;
00491 
00492     return xReturn;
00493 }


Variable Documentation

volatile portBASE_TYPE xErrorOccurred = pdFALSE [static]

Definition at line 95 of file blocktim.c.

volatile portBASE_TYPE xPrimaryCycles = 0 [static]

Definition at line 94 of file blocktim.c.

volatile unsigned portBASE_TYPE xRunIndicator [static]

Definition at line 99 of file blocktim.c.

Definition at line 91 of file blocktim.c.

volatile portBASE_TYPE xSecondaryCycles = 0 [static]

Definition at line 94 of file blocktim.c.

Definition at line 87 of file blocktim.c.


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