2 * FreeRTOS Kernel V10.3.0
\r
3 * Copyright (C) 2020 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.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
29 * This file defines one of the more complex set of demo/test tasks. They are
\r
30 * designed to stress test the queue implementation though pseudo simultaneous
\r
31 * multiple reads and multiple writes from both tasks of varying priority and
\r
32 * interrupts. The interrupts are prioritised such to ensure that nesting
\r
33 * occurs (for those ports that support it).
\r
35 * The test ensures that, while being accessed from three tasks and two
\r
36 * interrupts, all the data sent to the queues is also received from
\r
37 * the same queue, and that no duplicate items are either sent or received.
\r
38 * The tests also ensure that a low priority task is never able to successfully
\r
39 * read from or write to a queue when a task of higher priority is attempting
\r
40 * the same operation.
\r
43 /* Standard includes. */
\r
46 /* SafeRTOS includes. */
\r
47 #include "FreeRTOS.h"
\r
51 /* Demo app includes. */
\r
52 #include "IntQueue.h"
\r
53 #include "IntQueueTimer.h"
\r
55 #if( INCLUDE_eTaskGetState != 1 )
\r
56 #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.
\r
59 /* Priorities used by test tasks. */
\r
60 #ifndef intqHIGHER_PRIORITY
\r
61 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
63 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
65 /* The number of values to send/receive before checking that all values were
\r
66 processed as expected. */
\r
67 #define intqNUM_VALUES_TO_LOG ( 200 )
\r
68 #define intqSHORT_DELAY ( 140 )
\r
70 /* The value by which the value being sent to or received from a queue should
\r
71 increment past intqNUM_VALUES_TO_LOG before we check that all values have been
\r
72 sent/received correctly. This is done to ensure that all tasks and interrupts
\r
73 accessing the queue have completed their accesses with the
\r
74 intqNUM_VALUES_TO_LOG range. */
\r
75 #define intqVALUE_OVERRUN ( 50 )
\r
77 /* The delay used by the polling task. A short delay is used for code
\r
79 #define intqONE_TICK_DELAY ( 1 )
\r
81 /* Each task and interrupt is given a unique identifier. This value is used to
\r
82 identify which task sent or received each value. The identifier is also used
\r
83 to distinguish between two tasks that are running the same task function. */
\r
84 #define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
\r
85 #define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
\r
86 #define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
\r
87 #define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 )
\r
88 #define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 )
\r
89 #define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
\r
91 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
\r
92 from each queue by each task, otherwise an error is detected. */
\r
93 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
\r
95 /* Send the next value to the queue that is normally empty. This is called
\r
96 from within the interrupts. */
\r
97 #define timerNORMALLY_EMPTY_TX() \
\r
98 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
\r
100 UBaseType_t uxSavedInterruptStatus; \
\r
101 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
103 uxValueForNormallyEmptyQueue++; \
\r
104 if( xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
106 uxValueForNormallyEmptyQueue--; \
\r
109 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
112 /* Send the next value to the queue that is normally full. This is called
\r
113 from within the interrupts. */
\r
114 #define timerNORMALLY_FULL_TX() \
\r
115 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
\r
117 UBaseType_t uxSavedInterruptStatus; \
\r
118 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
120 uxValueForNormallyFullQueue++; \
\r
121 if( xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
123 uxValueForNormallyFullQueue--; \
\r
126 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
129 /* Receive a value from the normally empty queue. This is called from within
\r
131 #define timerNORMALLY_EMPTY_RX() \
\r
132 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
134 prvQueueAccessLogError( __LINE__ ); \
\r
138 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
141 /* Receive a value from the normally full queue. This is called from within
\r
143 #define timerNORMALLY_FULL_RX() \
\r
144 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
\r
146 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
150 /*-----------------------------------------------------------*/
\r
152 /* The two queues used by the test. */
\r
153 static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
\r
155 /* Variables used to detect a stall in one of the tasks. */
\r
156 static volatile UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
\r
158 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
\r
159 caused the error in xErrorLine. */
\r
160 static BaseType_t xErrorStatus = pdPASS;
\r
161 static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
\r
163 /* Used for sequencing between tasks. */
\r
164 static BaseType_t xWasSuspended = pdFALSE;
\r
166 /* The values that are sent to the queues. An incremented value is sent each
\r
167 time to each queue. */
\r
168 static volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
\r
170 /* A handle to some of the tasks is required so they can be suspended/resumed. */
\r
171 TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
\r
173 /* When a value is received in a queue the value is ticked off in the array
\r
174 the array position of the value is set to a the identifier of the task or
\r
175 interrupt that accessed the queue. This way missing or duplicate values can be
\r
177 static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
178 static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
180 /* The test tasks themselves. */
\r
181 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
\r
182 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
\r
183 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
\r
184 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
\r
185 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
\r
187 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
\r
188 ucNormallyFullReceivedValues arrays, while checking for duplicates. */
\r
189 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource );
\r
190 static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource );
\r
192 /* Logs the line on which an error occurred. */
\r
193 static void prvQueueAccessLogError( UBaseType_t uxLine );
\r
195 /*-----------------------------------------------------------*/
\r
197 void vStartInterruptQueueTasks( void )
\r
199 /* Start the test tasks. */
\r
200 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
\r
201 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
\r
202 xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
203 xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
\r
204 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
\r
205 xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
207 /* Create the queues that are accessed by multiple tasks and multiple
\r
209 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
\r
210 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
\r
212 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
213 in use. The queue registry is provided as a means for kernel aware
\r
214 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
215 is not being used. The call to vQueueAddToRegistry() will be removed
\r
216 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
217 defined to be less than 1. */
\r
218 vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" );
\r
219 vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
\r
221 /*-----------------------------------------------------------*/
\r
223 static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource )
\r
225 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
227 /* We don't expect to receive the same value twice, so if the value
\r
228 has already been marked as received an error has occurred. */
\r
229 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
231 prvQueueAccessLogError( __LINE__ );
\r
234 /* Log that this value has been received. */
\r
235 ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
\r
238 /*-----------------------------------------------------------*/
\r
240 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource )
\r
242 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
244 /* We don't expect to receive the same value twice, so if the value
\r
245 has already been marked as received an error has occurred. */
\r
246 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
248 prvQueueAccessLogError( __LINE__ );
\r
251 /* Log that this value has been received. */
\r
252 ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
\r
255 /*-----------------------------------------------------------*/
\r
257 static void prvQueueAccessLogError( UBaseType_t uxLine )
\r
259 /* Latch the line number that caused the error. */
\r
260 xErrorLine = uxLine;
\r
261 xErrorStatus = pdFAIL;
\r
263 /*-----------------------------------------------------------*/
\r
265 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
267 UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
\r
269 /* The timer should not be started until after the scheduler has started.
\r
270 More than one task is running this code so we check the parameter value
\r
271 to determine which task should start the timer. */
\r
272 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
274 vInitialiseTimerForIntQueueTest();
\r
279 /* Block waiting to receive a value from the normally empty queue.
\r
280 Interrupts will write to the queue so we should receive a value. */
\r
281 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
283 prvQueueAccessLogError( __LINE__ );
\r
287 /* Note which value was received so we can check all expected
\r
288 values are received and no values are duplicated. */
\r
289 prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
\r
292 /* Ensure the other task running this code gets a chance to execute. */
\r
295 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
297 /* Have we received all the expected values? */
\r
298 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
300 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
306 /* Loop through the array, checking that both tasks have
\r
307 placed values into the array, and that no values are missing.
\r
308 Start at 1 as we expect position 0 to be unused. */
\r
309 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
311 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
313 /* A value is missing. */
\r
314 prvQueueAccessLogError( __LINE__ );
\r
318 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
320 /* Value was placed into the array by task 1. */
\r
323 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
325 /* Value was placed into the array by task 2. */
\r
328 else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
335 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
337 /* Only task 2 seemed to log any values. */
\r
339 if( uxErrorCount1 > 2 )
\r
341 prvQueueAccessLogError( __LINE__ );
\r
349 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
351 /* Only task 1 seemed to log any values. */
\r
353 if( uxErrorCount2 > 2 )
\r
355 prvQueueAccessLogError( __LINE__ );
\r
363 if( uxInterrupts == 0 )
\r
365 prvQueueAccessLogError( __LINE__ );
\r
368 /* Clear the array again, ready to start a new cycle. */
\r
369 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
371 uxHighPriorityLoops1++;
\r
372 uxValueForNormallyEmptyQueue = 0;
\r
374 /* Suspend ourselves, allowing the lower priority task to
\r
375 actually receive something from the queue. Until now it
\r
376 will have been prevented from doing so by the higher
\r
377 priority tasks. The lower priority task will resume us
\r
378 if it receives something. We will then resume the other
\r
379 higher priority task. */
\r
380 vTaskSuspend( NULL );
\r
381 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
386 /*-----------------------------------------------------------*/
\r
388 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
390 UBaseType_t uxValue, uxRxed;
\r
392 /* The parameters are not being used so avoid compiler warnings. */
\r
393 ( void ) pvParameters;
\r
397 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
\r
399 /* A value should only be obtained when the high priority task is
\r
401 if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
\r
403 prvQueueAccessLogError( __LINE__ );
\r
406 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
408 /* Wake the higher priority task again. */
\r
409 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
410 uxLowPriorityLoops1++;
\r
414 /* Raise our priority while we send so we can preempt the higher
\r
415 priority task, and ensure we get the Tx value into the queue. */
\r
416 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
418 portENTER_CRITICAL();
\r
420 uxValueForNormallyEmptyQueue++;
\r
421 uxValue = uxValueForNormallyEmptyQueue;
\r
423 portEXIT_CRITICAL();
\r
425 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
427 prvQueueAccessLogError( __LINE__ );
\r
430 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
434 /*-----------------------------------------------------------*/
\r
436 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
438 UBaseType_t uxValueToTx, ux, uxInterrupts;
\r
440 /* The parameters are not being used so avoid compiler warnings. */
\r
441 ( void ) pvParameters;
\r
443 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
444 high priority tasks. */
\r
445 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
447 portENTER_CRITICAL();
\r
449 uxValueForNormallyFullQueue++;
\r
450 uxValueToTx = uxValueForNormallyFullQueue;
\r
452 portEXIT_CRITICAL();
\r
454 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
459 portENTER_CRITICAL();
\r
461 uxValueForNormallyFullQueue++;
\r
462 uxValueToTx = uxValueForNormallyFullQueue;
\r
464 portEXIT_CRITICAL();
\r
466 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
468 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
469 expect it to ever time out. */
\r
470 prvQueueAccessLogError( __LINE__ );
\r
473 /* Allow the other task running this code to run. */
\r
476 /* Have all the expected values been sent to the queue? */
\r
477 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
479 /* Make sure the other high priority task completes its send of
\r
480 any values below intqNUM_VALUE_TO_LOG. */
\r
481 vTaskDelay( intqSHORT_DELAY );
\r
483 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
485 if( xWasSuspended == pdTRUE )
\r
487 /* We would have expected the other high priority task to have
\r
488 set this back to false by now. */
\r
489 prvQueueAccessLogError( __LINE__ );
\r
492 /* Set the suspended flag so an error is not logged if the other
\r
493 task recognises a time out when it is unsuspended. */
\r
494 xWasSuspended = pdTRUE;
\r
496 /* Check interrupts are also sending. */
\r
499 /* Start at 1 as we expect position 0 to be unused. */
\r
500 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
502 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
504 /* A value was missing. */
\r
505 prvQueueAccessLogError( __LINE__ );
\r
507 else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
513 if( uxInterrupts == 0 )
\r
515 /* No writes from interrupts were found. Are interrupts
\r
516 actually running? */
\r
517 prvQueueAccessLogError( __LINE__ );
\r
520 /* Reset the array ready for the next cycle. */
\r
521 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
523 uxHighPriorityLoops2++;
\r
524 uxValueForNormallyFullQueue = 0;
\r
526 /* Suspend ourselves, allowing the lower priority task to
\r
527 actually receive something from the queue. Until now it
\r
528 will have been prevented from doing so by the higher
\r
529 priority tasks. The lower priority task will resume us
\r
530 if it receives something. We will then resume the other
\r
531 higher priority task. */
\r
532 vTaskSuspend( NULL );
\r
533 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
537 /*-----------------------------------------------------------*/
\r
539 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
541 UBaseType_t uxValueToTx, ux;
\r
543 /* The parameters are not being used so avoid compiler warnings. */
\r
544 ( void ) pvParameters;
\r
546 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
547 high priority tasks. */
\r
548 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
550 portENTER_CRITICAL();
\r
552 uxValueForNormallyFullQueue++;
\r
553 uxValueToTx = uxValueForNormallyFullQueue;
\r
555 portEXIT_CRITICAL();
\r
557 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
562 portENTER_CRITICAL();
\r
564 uxValueForNormallyFullQueue++;
\r
565 uxValueToTx = uxValueForNormallyFullQueue;
\r
567 portEXIT_CRITICAL();
\r
569 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
571 if( xWasSuspended != pdTRUE )
\r
573 /* It is ok to time out if the task has been suspended. */
\r
574 prvQueueAccessLogError( __LINE__ );
\r
578 xWasSuspended = pdFALSE;
\r
583 /*-----------------------------------------------------------*/
\r
585 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
587 UBaseType_t uxValue, uxTxed = 9999;
\r
589 /* The parameters are not being used so avoid compiler warnings. */
\r
590 ( void ) pvParameters;
\r
594 if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
\r
596 /* Should only succeed when the higher priority task is suspended */
\r
597 if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended )
\r
599 prvQueueAccessLogError( __LINE__ );
\r
602 vTaskResume( xHighPriorityNormallyFullTask1 );
\r
603 uxLowPriorityLoops2++;
\r
607 /* Raise our priority while we receive so we can preempt the higher
\r
608 priority task, and ensure we get the value from the queue. */
\r
609 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
611 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
613 prvQueueAccessLogError( __LINE__ );
\r
617 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
\r
620 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
624 /*-----------------------------------------------------------*/
\r
626 BaseType_t xFirstTimerHandler( void )
\r
628 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
629 UBaseType_t uxRxedValue;
\r
630 static UBaseType_t uxNextOperation = 0;
\r
632 /* Called from a timer interrupt. Perform various read and write
\r
633 accesses on the queues. */
\r
637 if( uxNextOperation & ( UBaseType_t ) 0x01 )
\r
639 timerNORMALLY_EMPTY_TX();
\r
640 timerNORMALLY_EMPTY_TX();
\r
641 timerNORMALLY_EMPTY_TX();
\r
645 timerNORMALLY_FULL_RX();
\r
646 timerNORMALLY_FULL_RX();
\r
647 timerNORMALLY_FULL_RX();
\r
650 return xHigherPriorityTaskWoken;
\r
652 /*-----------------------------------------------------------*/
\r
654 BaseType_t xSecondTimerHandler( void )
\r
656 UBaseType_t uxRxedValue;
\r
657 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
658 static UBaseType_t uxNextOperation = 0;
\r
660 /* Called from a timer interrupt. Perform various read and write
\r
661 accesses on the queues. */
\r
665 if( uxNextOperation & ( UBaseType_t ) 0x01 )
\r
667 timerNORMALLY_EMPTY_TX();
\r
668 timerNORMALLY_EMPTY_TX();
\r
670 timerNORMALLY_EMPTY_RX();
\r
671 timerNORMALLY_EMPTY_RX();
\r
675 timerNORMALLY_FULL_RX();
\r
676 timerNORMALLY_FULL_TX();
\r
677 timerNORMALLY_FULL_TX();
\r
678 timerNORMALLY_FULL_TX();
\r
681 return xHigherPriorityTaskWoken;
\r
683 /*-----------------------------------------------------------*/
\r
686 BaseType_t xAreIntQueueTasksStillRunning( void )
\r
688 static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
690 /* xErrorStatus can be set outside of this function. This function just
\r
691 checks that all the tasks are still cycling. */
\r
693 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
695 /* The high priority 1 task has stalled. */
\r
696 prvQueueAccessLogError( __LINE__ );
\r
699 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
701 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
703 /* The high priority 2 task has stalled. */
\r
704 prvQueueAccessLogError( __LINE__ );
\r
707 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
709 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
711 /* The low priority 1 task has stalled. */
\r
712 prvQueueAccessLogError( __LINE__ );
\r
715 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
717 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
719 /* The low priority 2 task has stalled. */
\r
720 prvQueueAccessLogError( __LINE__ );
\r
723 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
725 return xErrorStatus;
\r