#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 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.
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 }
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.
xTaskHandle xHighPriorityMutexTask [static] |
Definition at line 128 of file GenQTest.c.
xTaskHandle xMediumPriorityMutexTask [static] |
Definition at line 128 of file GenQTest.c.