#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 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.
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 }
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.
xTaskHandle xSecondary [static] |
Definition at line 91 of file blocktim.c.
volatile portBASE_TYPE xSecondaryCycles = 0 [static] |
Definition at line 94 of file blocktim.c.
xQueueHandle xTestQueue [static] |
Definition at line 87 of file blocktim.c.