3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
29 * This file defines one of the more complex set of demo/test tasks. They are
30 * designed to stress test the queue implementation though pseudo simultaneous
31 * multiple reads and multiple writes from both tasks of varying priority and
32 * interrupts. The interrupts are prioritised such to ensure that nesting
33 * occurs (for those ports that support it).
35 * The test ensures that, while being accessed from three tasks and two
36 * interrupts, all the data sent to the queues is also received from
37 * the same queue, and that no duplicate items are either sent or received.
38 * The tests also ensure that a low priority task is never able to successfully
39 * read from or write to a queue when a task of higher priority is attempting
43 /* Standard includes. */
46 /* SafeRTOS includes. */
51 /* Demo app includes. */
53 #include "IntQueueTimer.h"
55 #if ( INCLUDE_eTaskGetState != 1 )
56 #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.
59 /* Priorities used by test tasks. */
60 #ifndef intqHIGHER_PRIORITY
61 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
63 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
65 /* The number of values to send/receive before checking that all values were
66 * processed as expected. */
67 #define intqNUM_VALUES_TO_LOG ( 200 )
68 #define intqSHORT_DELAY ( 140 )
70 /* The value by which the value being sent to or received from a queue should
71 * increment past intqNUM_VALUES_TO_LOG before we check that all values have been
72 * sent/received correctly. This is done to ensure that all tasks and interrupts
73 * accessing the queue have completed their accesses with the
74 * intqNUM_VALUES_TO_LOG range. */
75 #define intqVALUE_OVERRUN ( 50 )
77 /* The delay used by the polling task. A short delay is used for code
79 #define intqONE_TICK_DELAY ( 1 )
81 /* Each task and interrupt is given a unique identifier. This value is used to
82 * identify which task sent or received each value. The identifier is also used
83 * to distinguish between two tasks that are running the same task function. */
84 #define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
85 #define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
86 #define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
87 #define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 )
88 #define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 )
89 #define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
91 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
92 * from each queue by each task, otherwise an error is detected. */
93 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
95 /* Send the next value to the queue that is normally empty. This is called
96 * from within the interrupts. */
97 #define timerNORMALLY_EMPTY_TX() \
98 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
100 UBaseType_t uxSavedInterruptStatus; \
101 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
103 uxValueForNormallyEmptyQueue++; \
104 if( xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
106 uxValueForNormallyEmptyQueue--; \
109 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
113 /* Send the next value to the queue that is normally full. This is called
114 * from within the interrupts. */
115 #define timerNORMALLY_FULL_TX() \
116 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
118 UBaseType_t uxSavedInterruptStatus; \
119 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
121 uxValueForNormallyFullQueue++; \
122 if( xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
124 uxValueForNormallyFullQueue--; \
127 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
131 /* Receive a value from the normally empty queue. This is called from within
133 #define timerNORMALLY_EMPTY_RX() \
134 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
136 prvQueueAccessLogError( __LINE__ ); \
140 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
143 /* Receive a value from the normally full queue. This is called from within
145 #define timerNORMALLY_FULL_RX() \
146 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
148 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
152 /*-----------------------------------------------------------*/
154 /* The two queues used by the test. */
155 static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
157 /* Variables used to detect a stall in one of the tasks. */
158 static volatile UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
160 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
161 * caused the error in xErrorLine. */
162 static BaseType_t xErrorStatus = pdPASS;
163 static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
165 /* Used for sequencing between tasks. */
166 static BaseType_t xWasSuspended = pdFALSE;
168 /* The values that are sent to the queues. An incremented value is sent each
169 * time to each queue. */
170 static volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
172 /* A handle to some of the tasks is required so they can be suspended/resumed. */
173 TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
175 /* When a value is received in a queue the value is ticked off in the array
176 * the array position of the value is set to a the identifier of the task or
177 * interrupt that accessed the queue. This way missing or duplicate values can be
179 static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
180 static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
182 /* The test tasks themselves. */
183 static void prvLowerPriorityNormallyEmptyTask( void * pvParameters );
184 static void prvLowerPriorityNormallyFullTask( void * pvParameters );
185 static void prvHigherPriorityNormallyEmptyTask( void * pvParameters );
186 static void prv1stHigherPriorityNormallyFullTask( void * pvParameters );
187 static void prv2ndHigherPriorityNormallyFullTask( void * pvParameters );
189 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
190 * ucNormallyFullReceivedValues arrays, while checking for duplicates. */
191 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue,
192 UBaseType_t uxSource );
193 static void prvRecordValue_NormallyFull( UBaseType_t uxValue,
194 UBaseType_t uxSource );
196 /* Logs the line on which an error occurred. */
197 static void prvQueueAccessLogError( UBaseType_t uxLine );
199 /*-----------------------------------------------------------*/
201 void vStartInterruptQueueTasks( void )
203 /* Start the test tasks. */
204 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
205 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
206 xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
207 xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
208 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
209 xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
211 /* Create the queues that are accessed by multiple tasks and multiple
213 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
214 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
216 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
217 * in use. The queue registry is provided as a means for kernel aware
218 * debuggers to locate queues and has no purpose if a kernel aware debugger
219 * is not being used. The call to vQueueAddToRegistry() will be removed
220 * by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
221 * defined to be less than 1. */
222 vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" );
223 vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
225 /*-----------------------------------------------------------*/
227 static void prvRecordValue_NormallyFull( UBaseType_t uxValue,
228 UBaseType_t uxSource )
230 if( uxValue < intqNUM_VALUES_TO_LOG )
232 /* We don't expect to receive the same value twice, so if the value
233 * has already been marked as received an error has occurred. */
234 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
236 prvQueueAccessLogError( __LINE__ );
239 /* Log that this value has been received. */
240 ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
243 /*-----------------------------------------------------------*/
245 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue,
246 UBaseType_t uxSource )
248 if( uxValue < intqNUM_VALUES_TO_LOG )
250 /* We don't expect to receive the same value twice, so if the value
251 * has already been marked as received an error has occurred. */
252 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
254 prvQueueAccessLogError( __LINE__ );
257 /* Log that this value has been received. */
258 ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
261 /*-----------------------------------------------------------*/
263 static void prvQueueAccessLogError( UBaseType_t uxLine )
265 /* Latch the line number that caused the error. */
267 xErrorStatus = pdFAIL;
269 /*-----------------------------------------------------------*/
271 static void prvHigherPriorityNormallyEmptyTask( void * pvParameters )
273 UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
275 /* The timer should not be started until after the scheduler has started.
276 * More than one task is running this code so we check the parameter value
277 * to determine which task should start the timer. */
278 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
280 vInitialiseTimerForIntQueueTest();
285 /* Block waiting to receive a value from the normally empty queue.
286 * Interrupts will write to the queue so we should receive a value. */
287 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
289 prvQueueAccessLogError( __LINE__ );
293 /* Note which value was received so we can check all expected
294 * values are received and no values are duplicated. */
295 prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
298 /* Ensure the other task running this code gets a chance to execute. */
301 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
303 /* Have we received all the expected values? */
304 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
306 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
312 /* Loop through the array, checking that both tasks have
313 * placed values into the array, and that no values are missing.
314 * Start at 1 as we expect position 0 to be unused. */
315 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
317 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
319 /* A value is missing. */
320 prvQueueAccessLogError( __LINE__ );
324 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
326 /* Value was placed into the array by task 1. */
329 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
331 /* Value was placed into the array by task 2. */
334 else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
341 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
343 /* Only task 2 seemed to log any values. */
346 if( uxErrorCount1 > 2 )
348 prvQueueAccessLogError( __LINE__ );
356 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
358 /* Only task 1 seemed to log any values. */
361 if( uxErrorCount2 > 2 )
363 prvQueueAccessLogError( __LINE__ );
371 if( uxInterrupts == 0 )
373 prvQueueAccessLogError( __LINE__ );
376 /* Clear the array again, ready to start a new cycle. */
377 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
379 uxHighPriorityLoops1++;
380 uxValueForNormallyEmptyQueue = 0;
382 /* Suspend ourselves, allowing the lower priority task to
383 * actually receive something from the queue. Until now it
384 * will have been prevented from doing so by the higher
385 * priority tasks. The lower priority task will resume us
386 * if it receives something. We will then resume the other
387 * higher priority task. */
388 vTaskSuspend( NULL );
389 vTaskResume( xHighPriorityNormallyEmptyTask2 );
394 /*-----------------------------------------------------------*/
396 static void prvLowerPriorityNormallyEmptyTask( void * pvParameters )
398 UBaseType_t uxValue, uxRxed;
400 /* The parameters are not being used so avoid compiler warnings. */
401 ( void ) pvParameters;
405 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
407 /* A value should only be obtained when the high priority task is
409 if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
411 prvQueueAccessLogError( __LINE__ );
414 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
416 /* Wake the higher priority task again. */
417 vTaskResume( xHighPriorityNormallyEmptyTask1 );
418 uxLowPriorityLoops1++;
422 /* Raise our priority while we send so we can preempt the higher
423 * priority task, and ensure we get the Tx value into the queue. */
424 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
426 portENTER_CRITICAL();
428 uxValueForNormallyEmptyQueue++;
429 uxValue = uxValueForNormallyEmptyQueue;
433 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
435 prvQueueAccessLogError( __LINE__ );
438 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
442 /*-----------------------------------------------------------*/
444 static void prv1stHigherPriorityNormallyFullTask( void * pvParameters )
446 UBaseType_t uxValueToTx, ux, uxInterrupts;
448 /* The parameters are not being used so avoid compiler warnings. */
449 ( void ) pvParameters;
451 /* Make sure the queue starts full or near full. >> 1 as there are two
452 * high priority tasks. */
453 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
455 portENTER_CRITICAL();
457 uxValueForNormallyFullQueue++;
458 uxValueToTx = uxValueForNormallyFullQueue;
462 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
467 portENTER_CRITICAL();
469 uxValueForNormallyFullQueue++;
470 uxValueToTx = uxValueForNormallyFullQueue;
474 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
476 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
477 * expect it to ever time out. */
478 prvQueueAccessLogError( __LINE__ );
481 /* Allow the other task running this code to run. */
484 /* Have all the expected values been sent to the queue? */
485 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
487 /* Make sure the other high priority task completes its send of
488 * any values below intqNUM_VALUE_TO_LOG. */
489 vTaskDelay( intqSHORT_DELAY );
491 vTaskSuspend( xHighPriorityNormallyFullTask2 );
493 if( xWasSuspended == pdTRUE )
495 /* We would have expected the other high priority task to have
496 * set this back to false by now. */
497 prvQueueAccessLogError( __LINE__ );
500 /* Set the suspended flag so an error is not logged if the other
501 * task recognises a time out when it is unsuspended. */
502 xWasSuspended = pdTRUE;
504 /* Check interrupts are also sending. */
507 /* Start at 1 as we expect position 0 to be unused. */
508 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
510 if( ucNormallyFullReceivedValues[ ux ] == 0 )
512 /* A value was missing. */
513 prvQueueAccessLogError( __LINE__ );
515 else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
521 if( uxInterrupts == 0 )
523 /* No writes from interrupts were found. Are interrupts
524 * actually running? */
525 prvQueueAccessLogError( __LINE__ );
528 /* Reset the array ready for the next cycle. */
529 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
531 uxHighPriorityLoops2++;
532 uxValueForNormallyFullQueue = 0;
534 /* Suspend ourselves, allowing the lower priority task to
535 * actually receive something from the queue. Until now it
536 * will have been prevented from doing so by the higher
537 * priority tasks. The lower priority task will resume us
538 * if it receives something. We will then resume the other
539 * higher priority task. */
540 vTaskSuspend( NULL );
541 vTaskResume( xHighPriorityNormallyFullTask2 );
545 /*-----------------------------------------------------------*/
547 static void prv2ndHigherPriorityNormallyFullTask( void * pvParameters )
549 UBaseType_t uxValueToTx, ux;
551 /* The parameters are not being used so avoid compiler warnings. */
552 ( void ) pvParameters;
554 /* Make sure the queue starts full or near full. >> 1 as there are two
555 * high priority tasks. */
556 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
558 portENTER_CRITICAL();
560 uxValueForNormallyFullQueue++;
561 uxValueToTx = uxValueForNormallyFullQueue;
565 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
570 portENTER_CRITICAL();
572 uxValueForNormallyFullQueue++;
573 uxValueToTx = uxValueForNormallyFullQueue;
577 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
579 if( xWasSuspended != pdTRUE )
581 /* It is ok to time out if the task has been suspended. */
582 prvQueueAccessLogError( __LINE__ );
586 xWasSuspended = pdFALSE;
591 /*-----------------------------------------------------------*/
593 static void prvLowerPriorityNormallyFullTask( void * pvParameters )
595 UBaseType_t uxValue, uxTxed = 9999;
597 /* The parameters are not being used so avoid compiler warnings. */
598 ( void ) pvParameters;
602 if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
604 /* Should only succeed when the higher priority task is suspended */
605 if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended )
607 prvQueueAccessLogError( __LINE__ );
610 vTaskResume( xHighPriorityNormallyFullTask1 );
611 uxLowPriorityLoops2++;
615 /* Raise our priority while we receive so we can preempt the higher
616 * priority task, and ensure we get the value from the queue. */
617 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
619 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
621 prvQueueAccessLogError( __LINE__ );
625 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
628 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
632 /*-----------------------------------------------------------*/
634 BaseType_t xFirstTimerHandler( void )
636 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
637 UBaseType_t uxRxedValue;
638 static UBaseType_t uxNextOperation = 0;
640 /* Called from a timer interrupt. Perform various read and write
641 * accesses on the queues. */
645 if( uxNextOperation & ( UBaseType_t ) 0x01 )
647 timerNORMALLY_EMPTY_TX();
648 timerNORMALLY_EMPTY_TX();
649 timerNORMALLY_EMPTY_TX();
653 timerNORMALLY_FULL_RX();
654 timerNORMALLY_FULL_RX();
655 timerNORMALLY_FULL_RX();
658 return xHigherPriorityTaskWoken;
660 /*-----------------------------------------------------------*/
662 BaseType_t xSecondTimerHandler( void )
664 UBaseType_t uxRxedValue;
665 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
666 static UBaseType_t uxNextOperation = 0;
668 /* Called from a timer interrupt. Perform various read and write
669 * accesses on the queues. */
673 if( uxNextOperation & ( UBaseType_t ) 0x01 )
675 timerNORMALLY_EMPTY_TX();
676 timerNORMALLY_EMPTY_TX();
678 timerNORMALLY_EMPTY_RX();
679 timerNORMALLY_EMPTY_RX();
683 timerNORMALLY_FULL_RX();
684 timerNORMALLY_FULL_TX();
685 timerNORMALLY_FULL_TX();
686 timerNORMALLY_FULL_TX();
689 return xHigherPriorityTaskWoken;
691 /*-----------------------------------------------------------*/
694 BaseType_t xAreIntQueueTasksStillRunning( void )
696 static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
698 /* xErrorStatus can be set outside of this function. This function just
699 * checks that all the tasks are still cycling. */
701 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
703 /* The high priority 1 task has stalled. */
704 prvQueueAccessLogError( __LINE__ );
707 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
709 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
711 /* The high priority 2 task has stalled. */
712 prvQueueAccessLogError( __LINE__ );
715 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
717 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
719 /* The low priority 1 task has stalled. */
720 prvQueueAccessLogError( __LINE__ );
723 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
725 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
727 /* The low priority 2 task has stalled. */
728 prvQueueAccessLogError( __LINE__ );
731 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;