2 * FreeRTOS Kernel V10.0.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software. If you wish to use our Amazon
\r
14 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
30 * This file defines one of the more complex set of demo/test tasks. They are
\r
31 * designed to stress test the queue implementation though pseudo simultaneous
\r
32 * multiple reads and multiple writes from both tasks of varying priority and
\r
33 * interrupts. The interrupts are prioritised such to ensure that nesting
\r
34 * occurs (for those ports that support it).
\r
36 * The test ensures that, while being accessed from three tasks and two
\r
37 * interrupts, all the data sent to the queues is also received from
\r
38 * the same queue, and that no duplicate items are either sent or received.
\r
39 * The tests also ensure that a low priority task is never able to successfully
\r
40 * read from or write to a queue when a task of higher priority is attempting
\r
41 * the same operation.
\r
44 /* Standard includes. */
\r
47 /* SafeRTOS includes. */
\r
48 #include "FreeRTOS.h"
\r
52 /* Demo app includes. */
\r
53 #include "IntQueue.h"
\r
54 #include "IntQueueTimer.h"
\r
56 #if( INCLUDE_eTaskGetState != 1 )
\r
57 #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.
\r
60 /* Priorities used by test tasks. */
\r
61 #ifndef intqHIGHER_PRIORITY
\r
62 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
64 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
66 /* The number of values to send/receive before checking that all values were
\r
67 processed as expected. */
\r
68 #define intqNUM_VALUES_TO_LOG ( 200 )
\r
69 #define intqSHORT_DELAY ( 140 )
\r
71 /* The value by which the value being sent to or received from a queue should
\r
72 increment past intqNUM_VALUES_TO_LOG before we check that all values have been
\r
73 sent/received correctly. This is done to ensure that all tasks and interrupts
\r
74 accessing the queue have completed their accesses with the
\r
75 intqNUM_VALUES_TO_LOG range. */
\r
76 #define intqVALUE_OVERRUN ( 50 )
\r
78 /* The delay used by the polling task. A short delay is used for code
\r
80 #define intqONE_TICK_DELAY ( 1 )
\r
82 /* Each task and interrupt is given a unique identifier. This value is used to
\r
83 identify which task sent or received each value. The identifier is also used
\r
84 to distinguish between two tasks that are running the same task function. */
\r
85 #define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
\r
86 #define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
\r
87 #define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
\r
88 #define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 )
\r
89 #define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 )
\r
90 #define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
\r
92 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
\r
93 from each queue by each task, otherwise an error is detected. */
\r
94 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
\r
96 /* Send the next value to the queue that is normally empty. This is called
\r
97 from within the interrupts. */
\r
98 #define timerNORMALLY_EMPTY_TX() \
\r
99 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
\r
101 UBaseType_t uxSavedInterruptStatus; \
\r
102 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
104 uxValueForNormallyEmptyQueue++; \
\r
105 if( xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
107 uxValueForNormallyEmptyQueue--; \
\r
110 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
113 /* Send the next value to the queue that is normally full. This is called
\r
114 from within the interrupts. */
\r
115 #define timerNORMALLY_FULL_TX() \
\r
116 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
\r
118 UBaseType_t uxSavedInterruptStatus; \
\r
119 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
121 uxValueForNormallyFullQueue++; \
\r
122 if( xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
124 uxValueForNormallyFullQueue--; \
\r
127 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
130 /* Receive a value from the normally empty queue. This is called from within
\r
132 #define timerNORMALLY_EMPTY_RX() \
\r
133 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
135 prvQueueAccessLogError( __LINE__ ); \
\r
139 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
142 /* Receive a value from the normally full queue. This is called from within
\r
144 #define timerNORMALLY_FULL_RX() \
\r
145 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
\r
147 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
151 /*-----------------------------------------------------------*/
\r
153 /* The two queues used by the test. */
\r
154 static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
\r
156 /* Variables used to detect a stall in one of the tasks. */
\r
157 static volatile UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
\r
159 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
\r
160 caused the error in xErrorLine. */
\r
161 static BaseType_t xErrorStatus = pdPASS;
\r
162 static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
\r
164 /* Used for sequencing between tasks. */
\r
165 static BaseType_t xWasSuspended = pdFALSE;
\r
167 /* The values that are sent to the queues. An incremented value is sent each
\r
168 time to each queue. */
\r
169 static volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
\r
171 /* A handle to some of the tasks is required so they can be suspended/resumed. */
\r
172 TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
\r
174 /* When a value is received in a queue the value is ticked off in the array
\r
175 the array position of the value is set to a the identifier of the task or
\r
176 interrupt that accessed the queue. This way missing or duplicate values can be
\r
178 static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
179 static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
181 /* The test tasks themselves. */
\r
182 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
\r
183 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
\r
184 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
\r
185 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
\r
186 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
\r
188 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
\r
189 ucNormallyFullReceivedValues arrays, while checking for duplicates. */
\r
190 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource );
\r
191 static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource );
\r
193 /* Logs the line on which an error occurred. */
\r
194 static void prvQueueAccessLogError( UBaseType_t uxLine );
\r
196 /*-----------------------------------------------------------*/
\r
198 void vStartInterruptQueueTasks( void )
\r
200 /* Start the test tasks. */
\r
201 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
\r
202 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
\r
203 xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
204 xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
\r
205 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
\r
206 xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
208 /* Create the queues that are accessed by multiple tasks and multiple
\r
210 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
\r
211 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
\r
213 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
214 in use. The queue registry is provided as a means for kernel aware
\r
215 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
216 is not being used. The call to vQueueAddToRegistry() will be removed
\r
217 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
218 defined to be less than 1. */
\r
219 vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" );
\r
220 vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
\r
222 /*-----------------------------------------------------------*/
\r
224 static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource )
\r
226 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
228 /* We don't expect to receive the same value twice, so if the value
\r
229 has already been marked as received an error has occurred. */
\r
230 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
232 prvQueueAccessLogError( __LINE__ );
\r
235 /* Log that this value has been received. */
\r
236 ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
\r
239 /*-----------------------------------------------------------*/
\r
241 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource )
\r
243 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
245 /* We don't expect to receive the same value twice, so if the value
\r
246 has already been marked as received an error has occurred. */
\r
247 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
249 prvQueueAccessLogError( __LINE__ );
\r
252 /* Log that this value has been received. */
\r
253 ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
\r
256 /*-----------------------------------------------------------*/
\r
258 static void prvQueueAccessLogError( UBaseType_t uxLine )
\r
260 /* Latch the line number that caused the error. */
\r
261 xErrorLine = uxLine;
\r
262 xErrorStatus = pdFAIL;
\r
264 /*-----------------------------------------------------------*/
\r
266 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
268 UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
\r
270 /* The timer should not be started until after the scheduler has started.
\r
271 More than one task is running this code so we check the parameter value
\r
272 to determine which task should start the timer. */
\r
273 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
275 vInitialiseTimerForIntQueueTest();
\r
280 /* Block waiting to receive a value from the normally empty queue.
\r
281 Interrupts will write to the queue so we should receive a value. */
\r
282 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
284 prvQueueAccessLogError( __LINE__ );
\r
288 /* Note which value was received so we can check all expected
\r
289 values are received and no values are duplicated. */
\r
290 prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
\r
293 /* Ensure the other task running this code gets a chance to execute. */
\r
296 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
298 /* Have we received all the expected values? */
\r
299 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
301 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
307 /* Loop through the array, checking that both tasks have
\r
308 placed values into the array, and that no values are missing.
\r
309 Start at 1 as we expect position 0 to be unused. */
\r
310 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
312 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
314 /* A value is missing. */
\r
315 prvQueueAccessLogError( __LINE__ );
\r
319 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
321 /* Value was placed into the array by task 1. */
\r
324 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
326 /* Value was placed into the array by task 2. */
\r
329 else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
336 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
338 /* Only task 2 seemed to log any values. */
\r
340 if( uxErrorCount1 > 2 )
\r
342 prvQueueAccessLogError( __LINE__ );
\r
350 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
352 /* Only task 1 seemed to log any values. */
\r
354 if( uxErrorCount2 > 2 )
\r
356 prvQueueAccessLogError( __LINE__ );
\r
364 if( uxInterrupts == 0 )
\r
366 prvQueueAccessLogError( __LINE__ );
\r
369 /* Clear the array again, ready to start a new cycle. */
\r
370 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
372 uxHighPriorityLoops1++;
\r
373 uxValueForNormallyEmptyQueue = 0;
\r
375 /* Suspend ourselves, allowing the lower priority task to
\r
376 actually receive something from the queue. Until now it
\r
377 will have been prevented from doing so by the higher
\r
378 priority tasks. The lower priority task will resume us
\r
379 if it receives something. We will then resume the other
\r
380 higher priority task. */
\r
381 vTaskSuspend( NULL );
\r
382 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
387 /*-----------------------------------------------------------*/
\r
389 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
391 UBaseType_t uxValue, uxRxed;
\r
393 /* The parameters are not being used so avoid compiler warnings. */
\r
394 ( void ) pvParameters;
\r
398 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
\r
400 /* A value should only be obtained when the high priority task is
\r
402 if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
\r
404 prvQueueAccessLogError( __LINE__ );
\r
407 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
409 /* Wake the higher priority task again. */
\r
410 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
411 uxLowPriorityLoops1++;
\r
415 /* Raise our priority while we send so we can preempt the higher
\r
416 priority task, and ensure we get the Tx value into the queue. */
\r
417 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
419 portENTER_CRITICAL();
\r
421 uxValueForNormallyEmptyQueue++;
\r
422 uxValue = uxValueForNormallyEmptyQueue;
\r
424 portEXIT_CRITICAL();
\r
426 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
428 prvQueueAccessLogError( __LINE__ );
\r
431 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
435 /*-----------------------------------------------------------*/
\r
437 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
439 UBaseType_t uxValueToTx, ux, uxInterrupts;
\r
441 /* The parameters are not being used so avoid compiler warnings. */
\r
442 ( void ) pvParameters;
\r
444 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
445 high priority tasks. */
\r
446 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
448 portENTER_CRITICAL();
\r
450 uxValueForNormallyFullQueue++;
\r
451 uxValueToTx = uxValueForNormallyFullQueue;
\r
453 portEXIT_CRITICAL();
\r
455 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
460 portENTER_CRITICAL();
\r
462 uxValueForNormallyFullQueue++;
\r
463 uxValueToTx = uxValueForNormallyFullQueue;
\r
465 portEXIT_CRITICAL();
\r
467 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
469 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
470 expect it to ever time out. */
\r
471 prvQueueAccessLogError( __LINE__ );
\r
474 /* Allow the other task running this code to run. */
\r
477 /* Have all the expected values been sent to the queue? */
\r
478 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
480 /* Make sure the other high priority task completes its send of
\r
481 any values below intqNUM_VALUE_TO_LOG. */
\r
482 vTaskDelay( intqSHORT_DELAY );
\r
484 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
486 if( xWasSuspended == pdTRUE )
\r
488 /* We would have expected the other high priority task to have
\r
489 set this back to false by now. */
\r
490 prvQueueAccessLogError( __LINE__ );
\r
493 /* Set the suspended flag so an error is not logged if the other
\r
494 task recognises a time out when it is unsuspended. */
\r
495 xWasSuspended = pdTRUE;
\r
497 /* Check interrupts are also sending. */
\r
500 /* Start at 1 as we expect position 0 to be unused. */
\r
501 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
503 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
505 /* A value was missing. */
\r
506 prvQueueAccessLogError( __LINE__ );
\r
508 else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
514 if( uxInterrupts == 0 )
\r
516 /* No writes from interrupts were found. Are interrupts
\r
517 actually running? */
\r
518 prvQueueAccessLogError( __LINE__ );
\r
521 /* Reset the array ready for the next cycle. */
\r
522 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
524 uxHighPriorityLoops2++;
\r
525 uxValueForNormallyFullQueue = 0;
\r
527 /* Suspend ourselves, allowing the lower priority task to
\r
528 actually receive something from the queue. Until now it
\r
529 will have been prevented from doing so by the higher
\r
530 priority tasks. The lower priority task will resume us
\r
531 if it receives something. We will then resume the other
\r
532 higher priority task. */
\r
533 vTaskSuspend( NULL );
\r
534 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
538 /*-----------------------------------------------------------*/
\r
540 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
542 UBaseType_t uxValueToTx, ux;
\r
544 /* The parameters are not being used so avoid compiler warnings. */
\r
545 ( void ) pvParameters;
\r
547 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
548 high priority tasks. */
\r
549 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
551 portENTER_CRITICAL();
\r
553 uxValueForNormallyFullQueue++;
\r
554 uxValueToTx = uxValueForNormallyFullQueue;
\r
556 portEXIT_CRITICAL();
\r
558 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
563 portENTER_CRITICAL();
\r
565 uxValueForNormallyFullQueue++;
\r
566 uxValueToTx = uxValueForNormallyFullQueue;
\r
568 portEXIT_CRITICAL();
\r
570 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
572 if( xWasSuspended != pdTRUE )
\r
574 /* It is ok to time out if the task has been suspended. */
\r
575 prvQueueAccessLogError( __LINE__ );
\r
579 xWasSuspended = pdFALSE;
\r
584 /*-----------------------------------------------------------*/
\r
586 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
588 UBaseType_t uxValue, uxTxed = 9999;
\r
590 /* The parameters are not being used so avoid compiler warnings. */
\r
591 ( void ) pvParameters;
\r
595 if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
\r
597 /* Should only succeed when the higher priority task is suspended */
\r
598 if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended )
\r
600 prvQueueAccessLogError( __LINE__ );
\r
603 vTaskResume( xHighPriorityNormallyFullTask1 );
\r
604 uxLowPriorityLoops2++;
\r
608 /* Raise our priority while we receive so we can preempt the higher
\r
609 priority task, and ensure we get the value from the queue. */
\r
610 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
612 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
614 prvQueueAccessLogError( __LINE__ );
\r
618 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
\r
621 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
625 /*-----------------------------------------------------------*/
\r
627 BaseType_t xFirstTimerHandler( void )
\r
629 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
630 UBaseType_t uxRxedValue;
\r
631 static UBaseType_t uxNextOperation = 0;
\r
633 /* Called from a timer interrupt. Perform various read and write
\r
634 accesses on the queues. */
\r
638 if( uxNextOperation & ( UBaseType_t ) 0x01 )
\r
640 timerNORMALLY_EMPTY_TX();
\r
641 timerNORMALLY_EMPTY_TX();
\r
642 timerNORMALLY_EMPTY_TX();
\r
646 timerNORMALLY_FULL_RX();
\r
647 timerNORMALLY_FULL_RX();
\r
648 timerNORMALLY_FULL_RX();
\r
651 return xHigherPriorityTaskWoken;
\r
653 /*-----------------------------------------------------------*/
\r
655 BaseType_t xSecondTimerHandler( void )
\r
657 UBaseType_t uxRxedValue;
\r
658 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
659 static UBaseType_t uxNextOperation = 0;
\r
661 /* Called from a timer interrupt. Perform various read and write
\r
662 accesses on the queues. */
\r
666 if( uxNextOperation & ( UBaseType_t ) 0x01 )
\r
668 timerNORMALLY_EMPTY_TX();
\r
669 timerNORMALLY_EMPTY_TX();
\r
671 timerNORMALLY_EMPTY_RX();
\r
672 timerNORMALLY_EMPTY_RX();
\r
676 timerNORMALLY_FULL_RX();
\r
677 timerNORMALLY_FULL_TX();
\r
678 timerNORMALLY_FULL_TX();
\r
679 timerNORMALLY_FULL_TX();
\r
682 return xHigherPriorityTaskWoken;
\r
684 /*-----------------------------------------------------------*/
\r
687 BaseType_t xAreIntQueueTasksStillRunning( void )
\r
689 static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
691 /* xErrorStatus can be set outside of this function. This function just
\r
692 checks that all the tasks are still cycling. */
\r
694 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
696 /* The high priority 1 task has stalled. */
\r
697 prvQueueAccessLogError( __LINE__ );
\r
700 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
702 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
704 /* The high priority 2 task has stalled. */
\r
705 prvQueueAccessLogError( __LINE__ );
\r
708 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
710 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
712 /* The low priority 1 task has stalled. */
\r
713 prvQueueAccessLogError( __LINE__ );
\r
716 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
718 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
720 /* The low priority 2 task has stalled. */
\r
721 prvQueueAccessLogError( __LINE__ );
\r
724 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
726 return xErrorStatus;
\r