00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include <string.h>
00071
00072
00073 #include "FreeRTOS.h"
00074 #include "queue.h"
00075 #include "task.h"
00076
00077
00078 #include "IntQueue.h"
00079 #include "IntQueueTimer.h"
00080
00081
00082 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
00083 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
00084
00085
00086
00087 #define intqNUM_VALUES_TO_LOG ( 200 )
00088 #define intqSHORT_DELAY ( 75 )
00089
00090
00091
00092
00093
00094
00095 #define intqVALUE_OVERRUN ( 50 )
00096
00097
00098
00099 #define intqONE_TICK_DELAY ( 1 )
00100
00101
00102
00103
00104 #define intqHIGH_PRIORITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 )
00105 #define intqHIGH_PRIORITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 )
00106 #define intqLOW_PRIORITY_TASK ( ( unsigned portBASE_TYPE ) 3 )
00107 #define intqFIRST_INTERRUPT ( ( unsigned portBASE_TYPE ) 4 )
00108 #define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 )
00109 #define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 )
00110
00111
00112
00113 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
00114
00115
00116
00117 #define timerNORMALLY_EMPTY_TX() \
00118 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
00119 { \
00120 unsigned portBASE_TYPE uxSavedInterruptStatus; \
00121 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
00122 { \
00123 uxValueForNormallyEmptyQueue++; \
00124 xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \
00125 } \
00126 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
00127 } \
00128
00129
00130
00131 #define timerNORMALLY_FULL_TX() \
00132 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
00133 { \
00134 unsigned portBASE_TYPE uxSavedInterruptStatus; \
00135 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
00136 { \
00137 uxValueForNormallyFullQueue++; \
00138 xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \
00139 } \
00140 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
00141 } \
00142
00143
00144
00145 #define timerNORMALLY_EMPTY_RX() \
00146 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
00147 { \
00148 prvQueueAccessLogError( __LINE__ ); \
00149 } \
00150 else \
00151 { \
00152 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
00153 }
00154
00155
00156
00157 #define timerNORMALLY_FULL_RX() \
00158 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
00159 { \
00160 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
00161 } \
00162
00163
00164
00165
00166
00167 static xQueueHandle xNormallyEmptyQueue, xNormallyFullQueue;
00168
00169
00170 static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
00171
00172
00173
00174 static portBASE_TYPE xErrorStatus = pdPASS;
00175 static unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;
00176
00177
00178 static portBASE_TYPE xWasSuspended = pdFALSE;
00179
00180
00181
00182 volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
00183
00184
00185 xTaskHandle xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
00186
00187
00188
00189
00190
00191 static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
00192 static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
00193
00194
00195 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
00196 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
00197 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
00198 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
00199 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
00200
00201
00202
00203 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
00204 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
00205
00206
00207 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine );
00208
00209
00210
00211 void vStartInterruptQueueTasks( void )
00212 {
00213
00214 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
00215 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
00216 xTaskCreate( prvLowerPriorityNormallyEmptyTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
00217 xTaskCreate( prv1stHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
00218 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
00219 xTaskCreate( prvLowerPriorityNormallyFullTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
00220
00221
00222
00223 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
00224 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
00225
00226
00227
00228
00229
00230
00231
00232 vQueueAddToRegistry( xNormallyFullQueue, ( signed portCHAR * ) "NormallyFull" );
00233 vQueueAddToRegistry( xNormallyEmptyQueue, ( signed portCHAR * ) "NormallyEmpty" );
00234 }
00235
00236
00237 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
00238 {
00239 if( uxValue < intqNUM_VALUES_TO_LOG )
00240 {
00241
00242
00243 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
00244 {
00245 prvQueueAccessLogError( __LINE__ );
00246 }
00247
00248
00249 ucNormallyFullReceivedValues[ uxValue ] = uxSource;
00250 }
00251 }
00252
00253
00254 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
00255 {
00256 if( uxValue < intqNUM_VALUES_TO_LOG )
00257 {
00258
00259
00260 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
00261 {
00262 prvQueueAccessLogError( __LINE__ );
00263 }
00264
00265
00266 ucNormallyEmptyReceivedValues[ uxValue ] = uxSource;
00267 }
00268 }
00269
00270
00271 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
00272 {
00273
00274 xErrorLine = uxLine;
00275 xErrorStatus = pdFAIL;
00276 }
00277
00278
00279 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
00280 {
00281 unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxErrorCount1 = 0, uxErrorCount2 = 0;
00282
00283
00284
00285
00286 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
00287 {
00288 vInitialiseTimerForIntQueueTest();
00289 }
00290
00291 for( ;; )
00292 {
00293
00294
00295 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
00296 {
00297 prvQueueAccessLogError( __LINE__ );
00298 }
00299 else
00300 {
00301
00302
00303 prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );
00304 }
00305
00306
00307 taskYIELD();
00308
00309 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
00310 {
00311
00312 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
00313 {
00314 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
00315
00316 uxTask1 = 0;
00317 uxTask2 = 0;
00318
00319
00320
00321
00322 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
00323 {
00324 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
00325 {
00326
00327 prvQueueAccessLogError( __LINE__ );
00328 }
00329 else
00330 {
00331 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
00332 {
00333
00334 uxTask1++;
00335 }
00336 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
00337 {
00338
00339 uxTask2++;
00340 }
00341 }
00342 }
00343
00344 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
00345 {
00346
00347 uxErrorCount1++;
00348 if( uxErrorCount1 > 2 )
00349 {
00350 prvQueueAccessLogError( __LINE__ );
00351 }
00352 }
00353 else
00354 {
00355 uxErrorCount1 = 0;
00356 }
00357
00358 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
00359 {
00360
00361 uxErrorCount2++;
00362 if( uxErrorCount2 > 2 )
00363 {
00364 prvQueueAccessLogError( __LINE__ );
00365 }
00366 }
00367 else
00368 {
00369 uxErrorCount2 = 0;
00370 }
00371
00372
00373 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
00374
00375 uxHighPriorityLoops1++;
00376 uxValueForNormallyEmptyQueue = 0;
00377
00378
00379
00380
00381
00382
00383
00384 vTaskSuspend( NULL );
00385 vTaskResume( xHighPriorityNormallyEmptyTask2 );
00386 }
00387 }
00388 }
00389 }
00390
00391
00392 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
00393 {
00394 unsigned portBASE_TYPE uxValue, uxRxed;
00395 portBASE_TYPE xQueueStatus;
00396
00397
00398 ( void ) pvParameters;
00399
00400 for( ;; )
00401 {
00402 if( ( xQueueStatus = xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) ) != errQUEUE_EMPTY )
00403 {
00404
00405
00406 if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE )
00407 {
00408 prvQueueAccessLogError( __LINE__ );
00409 }
00410
00411 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
00412
00413
00414 vTaskResume( xHighPriorityNormallyEmptyTask1 );
00415 uxLowPriorityLoops1++;
00416 }
00417 else
00418 {
00419
00420
00421 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
00422
00423 portENTER_CRITICAL();
00424 {
00425 uxValueForNormallyEmptyQueue++;
00426 uxValue = uxValueForNormallyEmptyQueue;
00427 }
00428 portEXIT_CRITICAL();
00429
00430 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
00431 {
00432 prvQueueAccessLogError( __LINE__ );
00433 }
00434
00435 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
00436 }
00437 }
00438 }
00439
00440
00441 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
00442 {
00443 unsigned portBASE_TYPE uxValueToTx, ux;
00444 portBASE_TYPE xQueueStatus;
00445
00446
00447 ( void ) pvParameters;
00448
00449
00450
00451 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
00452 {
00453 portENTER_CRITICAL();
00454 {
00455 uxValueForNormallyFullQueue++;
00456 uxValueToTx = uxValueForNormallyFullQueue;
00457 }
00458 portEXIT_CRITICAL();
00459
00460 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
00461 }
00462
00463 for( ;; )
00464 {
00465 portENTER_CRITICAL();
00466 {
00467 uxValueForNormallyFullQueue++;
00468 uxValueToTx = uxValueForNormallyFullQueue;
00469 }
00470 portEXIT_CRITICAL();
00471
00472 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )
00473 {
00474
00475
00476 prvQueueAccessLogError( __LINE__ );
00477 }
00478
00479
00480 taskYIELD();
00481
00482
00483 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
00484 {
00485
00486
00487 vTaskDelay( intqSHORT_DELAY );
00488
00489 vTaskSuspend( xHighPriorityNormallyFullTask2 );
00490
00491 if( xWasSuspended == pdTRUE )
00492 {
00493
00494
00495 prvQueueAccessLogError( __LINE__ );
00496 }
00497
00498
00499
00500 xWasSuspended = pdTRUE;
00501
00502
00503 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
00504 {
00505 if( ucNormallyFullReceivedValues[ ux ] == 0 )
00506 {
00507
00508 prvQueueAccessLogError( __LINE__ );
00509 }
00510 }
00511
00512
00513 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
00514
00515 uxHighPriorityLoops2++;
00516 uxValueForNormallyFullQueue = 0;
00517
00518
00519
00520
00521
00522
00523
00524 vTaskSuspend( NULL );
00525 vTaskResume( xHighPriorityNormallyFullTask2 );
00526 }
00527 }
00528 }
00529
00530
00531 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
00532 {
00533 unsigned portBASE_TYPE uxValueToTx, ux;
00534 portBASE_TYPE xQueueStatus;
00535
00536
00537 ( void ) pvParameters;
00538
00539
00540
00541 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
00542 {
00543 portENTER_CRITICAL();
00544 {
00545 uxValueForNormallyFullQueue++;
00546 uxValueToTx = uxValueForNormallyFullQueue;
00547 }
00548 portEXIT_CRITICAL();
00549
00550 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
00551 }
00552
00553 for( ;; )
00554 {
00555 portENTER_CRITICAL();
00556 {
00557 uxValueForNormallyFullQueue++;
00558 uxValueToTx = uxValueForNormallyFullQueue;
00559 }
00560 portEXIT_CRITICAL();
00561
00562 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )
00563 {
00564 if( xWasSuspended != pdTRUE )
00565 {
00566
00567 prvQueueAccessLogError( __LINE__ );
00568 }
00569 }
00570
00571 xWasSuspended = pdFALSE;
00572
00573 taskYIELD();
00574 }
00575 }
00576
00577
00578 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
00579 {
00580 unsigned portBASE_TYPE uxValue, uxTxed = 9999;
00581 portBASE_TYPE xQueueStatus;
00582
00583
00584 ( void ) pvParameters;
00585
00586 for( ;; )
00587 {
00588 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) ) != errQUEUE_FULL )
00589 {
00590
00591
00592 if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE )
00593 {
00594 prvQueueAccessLogError( __LINE__ );
00595 }
00596
00597 vTaskResume( xHighPriorityNormallyFullTask1 );
00598 uxLowPriorityLoops2++;
00599 }
00600 else
00601 {
00602
00603
00604 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
00605
00606 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
00607 {
00608 prvQueueAccessLogError( __LINE__ );
00609 }
00610 else
00611 {
00612 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
00613 }
00614
00615 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
00616 }
00617 }
00618 }
00619
00620
00621 portBASE_TYPE xFirstTimerHandler( void )
00622 {
00623 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;
00624 static unsigned portBASE_TYPE uxNextOperation = 0;
00625
00626
00627
00628
00629 uxNextOperation++;
00630
00631 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
00632 {
00633 timerNORMALLY_EMPTY_TX();
00634 timerNORMALLY_EMPTY_TX();
00635 timerNORMALLY_EMPTY_TX();
00636 }
00637 else
00638 {
00639 timerNORMALLY_FULL_RX();
00640 timerNORMALLY_FULL_RX();
00641 timerNORMALLY_FULL_RX();
00642 }
00643
00644 return xHigherPriorityTaskWoken;
00645 }
00646
00647
00648 portBASE_TYPE xSecondTimerHandler( void )
00649 {
00650 unsigned portBASE_TYPE uxRxedValue;
00651 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
00652 static unsigned portBASE_TYPE uxNextOperation = 0;
00653
00654
00655
00656
00657 uxNextOperation++;
00658
00659 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
00660 {
00661 timerNORMALLY_EMPTY_TX();
00662 timerNORMALLY_EMPTY_TX();
00663
00664 timerNORMALLY_EMPTY_RX();
00665 timerNORMALLY_EMPTY_RX();
00666 }
00667 else
00668 {
00669 timerNORMALLY_FULL_RX();
00670 timerNORMALLY_FULL_TX();
00671 timerNORMALLY_FULL_TX();
00672 timerNORMALLY_FULL_TX();
00673 timerNORMALLY_FULL_TX();
00674 }
00675
00676 return xHigherPriorityTaskWoken;
00677 }
00678
00679
00680
00681 portBASE_TYPE xAreIntQueueTasksStillRunning( void )
00682 {
00683 static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
00684
00685
00686
00687
00688 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
00689 {
00690
00691 prvQueueAccessLogError( __LINE__ );
00692 }
00693
00694 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
00695
00696 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
00697 {
00698
00699 prvQueueAccessLogError( __LINE__ );
00700 }
00701
00702 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
00703
00704 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
00705 {
00706
00707 prvQueueAccessLogError( __LINE__ );
00708 }
00709
00710 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
00711
00712 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
00713 {
00714
00715 prvQueueAccessLogError( __LINE__ );
00716 }
00717
00718 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
00719
00720 return xErrorStatus;
00721 }
00722