2 FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
\r
4 ***************************************************************************
\r
8 * + New to FreeRTOS, *
\r
9 * + Wanting to learn FreeRTOS or multitasking in general quickly *
\r
10 * + Looking for basic training, *
\r
11 * + Wanting to improve your FreeRTOS skills and productivity *
\r
13 * then take a look at the FreeRTOS eBook *
\r
15 * "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
\r
16 * http://www.FreeRTOS.org/Documentation *
\r
18 * A pdf reference manual is also available. Both are usually delivered *
\r
19 * to your inbox within 20 minutes to two hours when purchased between 8am *
\r
20 * and 8pm GMT (although please allow up to 24 hours in case of *
\r
21 * exceptional circumstances). Thank you for your support! *
\r
23 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 ***NOTE*** The exception to the GPL is included to allow you to distribute
\r
31 a combined work that includes FreeRTOS without being obliged to provide the
\r
32 source code for proprietary components outside of the FreeRTOS kernel.
\r
33 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
\r
34 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
35 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
47 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
50 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
51 licensing and training services.
\r
55 * This file defines one of the more complex set of demo/test tasks. They are
\r
56 * designed to stress test the queue implementation though pseudo simultaneous
\r
57 * multiple reads and multiple writes from both tasks of varying priority and
\r
58 * interrupts. The interrupts are prioritised such to ensure that nesting
\r
59 * occurs (for those ports that support it).
\r
61 * The test ensures that, while being accessed from three tasks and two
\r
62 * interrupts, all the data sent to the queues is also received from
\r
63 * the same queue, and that no duplicate items are either sent or received.
\r
64 * The tests also ensure that a low priority task is never able to successfully
\r
65 * read from or write to a queue when a task of higher priority is attempting
\r
66 * the same operation.
\r
69 /* Standard includes. */
\r
72 /* SafeRTOS includes. */
\r
73 #include "FreeRTOS.h"
\r
77 /* Demo app includes. */
\r
78 #include "IntQueue.h"
\r
79 #include "IntQueueTimer.h"
\r
81 /* Priorities used by test tasks. */
\r
82 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
83 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
85 /* The number of values to send/receive before checking that all values were
\r
86 processed as expected. */
\r
87 #define intqNUM_VALUES_TO_LOG ( 200 )
\r
88 #define intqSHORT_DELAY ( 75 )
\r
90 /* The value by which the value being sent to or received from a queue should
\r
91 increment past intqNUM_VALUES_TO_LOG before we check that all values have been
\r
92 sent/received correctly. This is done to ensure that all tasks and interrupts
\r
93 accessing the queue have completed their accesses with the
\r
94 intqNUM_VALUES_TO_LOG range. */
\r
95 #define intqVALUE_OVERRUN ( 50 )
\r
97 /* The delay used by the polling task. A short delay is used for code
\r
99 #define intqONE_TICK_DELAY ( 1 )
\r
101 /* Each task and interrupt is given a unique identifier. This value is used to
\r
102 identify which task sent or received each value. The identifier is also used
\r
103 to distinguish between two tasks that are running the same task function. */
\r
104 #define intqHIGH_PRIORITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 )
\r
105 #define intqHIGH_PRIORITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 )
\r
106 #define intqLOW_PRIORITY_TASK ( ( unsigned portBASE_TYPE ) 3 )
\r
107 #define intqFIRST_INTERRUPT ( ( unsigned portBASE_TYPE ) 4 )
\r
108 #define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 )
\r
109 #define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 )
\r
111 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
\r
112 from each queue by each task, otherwise an error is detected. */
\r
113 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
\r
115 /* Send the next value to the queue that is normally empty. This is called
\r
116 from within the interrupts. */
\r
117 #define timerNORMALLY_EMPTY_TX() \
\r
118 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
\r
120 unsigned portBASE_TYPE uxSavedInterruptStatus; \
\r
121 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
123 uxValueForNormallyEmptyQueue++; \
\r
124 xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \
\r
126 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
129 /* Send the next value to the queue that is normally full. This is called
\r
130 from within the interrupts. */
\r
131 #define timerNORMALLY_FULL_TX() \
\r
132 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
\r
134 unsigned portBASE_TYPE uxSavedInterruptStatus; \
\r
135 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
137 uxValueForNormallyFullQueue++; \
\r
138 xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \
\r
140 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
143 /* Receive a value from the normally empty queue. This is called from within
\r
145 #define timerNORMALLY_EMPTY_RX() \
\r
146 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
148 prvQueueAccessLogError( __LINE__ ); \
\r
152 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
155 /* Receive a value from the normally full queue. This is called from within
\r
157 #define timerNORMALLY_FULL_RX() \
\r
158 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
\r
160 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
164 /*-----------------------------------------------------------*/
\r
166 /* The two queues used by the test. */
\r
167 static xQueueHandle xNormallyEmptyQueue, xNormallyFullQueue;
\r
169 /* Variables used to detect a stall in one of the tasks. */
\r
170 static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
\r
172 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
\r
173 caused the error in xErrorLine. */
\r
174 static portBASE_TYPE xErrorStatus = pdPASS;
\r
175 static unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;
\r
177 /* Used for sequencing between tasks. */
\r
178 static portBASE_TYPE xWasSuspended = pdFALSE;
\r
180 /* The values that are sent to the queues. An incremented value is sent each
\r
181 time to each queue. */
\r
182 volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
\r
184 /* A handle to some of the tasks is required so they can be suspended/resumed. */
\r
185 xTaskHandle xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
\r
187 /* When a value is received in a queue the value is ticked off in the array
\r
188 the array position of the value is set to a the identifier of the task or
\r
189 interrupt that accessed the queue. This way missing or duplicate values can be
\r
191 static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
192 static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
194 /* The test tasks themselves. */
\r
195 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
\r
196 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
\r
197 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
\r
198 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
\r
199 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
\r
201 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
\r
202 ucNormallyFullReceivedValues arrays, while checking for duplicates. */
\r
203 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
\r
204 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
\r
206 /* Logs the line on which an error occurred. */
\r
207 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine );
\r
209 /*-----------------------------------------------------------*/
\r
211 void vStartInterruptQueueTasks( void )
\r
213 /* Start the test tasks. */
\r
214 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
\r
215 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
\r
216 xTaskCreate( prvLowerPriorityNormallyEmptyTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
217 xTaskCreate( prv1stHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
\r
218 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
\r
219 xTaskCreate( prvLowerPriorityNormallyFullTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
221 /* Create the queues that are accessed by multiple tasks and multiple
\r
223 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
\r
224 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
\r
226 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
227 in use. The queue registry is provided as a means for kernel aware
\r
228 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
229 is not being used. The call to vQueueAddToRegistry() will be removed
\r
230 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
231 defined to be less than 1. */
\r
232 vQueueAddToRegistry( xNormallyFullQueue, ( signed portCHAR * ) "NormallyFull" );
\r
233 vQueueAddToRegistry( xNormallyEmptyQueue, ( signed portCHAR * ) "NormallyEmpty" );
\r
235 /*-----------------------------------------------------------*/
\r
237 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
239 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
241 /* We don't expect to receive the same value twice, so if the value
\r
242 has already been marked as received an error has occurred. */
\r
243 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
245 prvQueueAccessLogError( __LINE__ );
\r
248 /* Log that this value has been received. */
\r
249 ucNormallyFullReceivedValues[ uxValue ] = uxSource;
\r
252 /*-----------------------------------------------------------*/
\r
254 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
256 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
258 /* We don't expect to receive the same value twice, so if the value
\r
259 has already been marked as received an error has occurred. */
\r
260 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
262 prvQueueAccessLogError( __LINE__ );
\r
265 /* Log that this value has been received. */
\r
266 ucNormallyEmptyReceivedValues[ uxValue ] = uxSource;
\r
269 /*-----------------------------------------------------------*/
\r
271 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
\r
273 /* Latch the line number that caused the error. */
\r
274 xErrorLine = uxLine;
\r
275 xErrorStatus = pdFAIL;
\r
277 /*-----------------------------------------------------------*/
\r
279 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
281 unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxErrorCount1 = 0, uxErrorCount2 = 0;
\r
283 /* The timer should not be started until after the scheduler has started.
\r
284 More than one task is running this code so we check the parameter value
\r
285 to determine which task should start the timer. */
\r
286 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
288 vInitialiseTimerForIntQueueTest();
\r
293 /* Block waiting to receive a value from the normally empty queue.
\r
294 Interrupts will write to the queue so we should receive a value. */
\r
295 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
297 prvQueueAccessLogError( __LINE__ );
\r
301 /* Note which value was received so we can check all expected
\r
302 values are received and no values are duplicated. */
\r
303 prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );
\r
306 /* Ensure the other task running this code gets a chance to execute. */
\r
309 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
311 /* Have we received all the expected values? */
\r
312 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
314 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
319 /* Loop through the array, checking that both tasks have
\r
320 placed values into the array, and that no values are missing.
\r
321 Start at 1 as we expect position 0 to be unused. */
\r
322 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
324 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
326 /* A value is missing. */
\r
327 prvQueueAccessLogError( __LINE__ );
\r
331 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
333 /* Value was placed into the array by task 1. */
\r
336 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
338 /* Value was placed into the array by task 2. */
\r
344 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
346 /* Only task 2 seemed to log any values. */
\r
348 if( uxErrorCount1 > 2 )
\r
350 prvQueueAccessLogError( __LINE__ );
\r
358 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
360 /* Only task 1 seemed to log any values. */
\r
362 if( uxErrorCount2 > 2 )
\r
364 prvQueueAccessLogError( __LINE__ );
\r
372 /* Clear the array again, ready to start a new cycle. */
\r
373 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
375 uxHighPriorityLoops1++;
\r
376 uxValueForNormallyEmptyQueue = 0;
\r
378 /* Suspend ourselves, allowing the lower priority task to
\r
379 actually receive something from the queue. Until now it
\r
380 will have been prevented from doing so by the higher
\r
381 priority tasks. The lower priority task will resume us
\r
382 if it receives something. We will then resume the other
\r
383 higher priority task. */
\r
384 vTaskSuspend( NULL );
\r
385 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
390 /*-----------------------------------------------------------*/
\r
392 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
394 unsigned portBASE_TYPE uxValue, uxRxed;
\r
395 portBASE_TYPE xQueueStatus;
\r
397 /* The parameters are not being used so avoid compiler warnings. */
\r
398 ( void ) pvParameters;
\r
402 if( ( xQueueStatus = xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) ) != errQUEUE_EMPTY )
\r
404 /* We should only obtain a value when the high priority task is
\r
406 if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE )
\r
408 prvQueueAccessLogError( __LINE__ );
\r
411 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
413 /* Wake the higher priority task again. */
\r
414 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
415 uxLowPriorityLoops1++;
\r
419 /* Raise our priority while we send so we can preempt the higher
\r
420 priority task, and ensure we get the Tx value into the queue. */
\r
421 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
423 portENTER_CRITICAL();
\r
425 uxValueForNormallyEmptyQueue++;
\r
426 uxValue = uxValueForNormallyEmptyQueue;
\r
428 portEXIT_CRITICAL();
\r
430 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
432 prvQueueAccessLogError( __LINE__ );
\r
435 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
439 /*-----------------------------------------------------------*/
\r
441 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
443 unsigned portBASE_TYPE uxValueToTx, ux;
\r
444 portBASE_TYPE xQueueStatus;
\r
446 /* The parameters are not being used so avoid compiler warnings. */
\r
447 ( void ) pvParameters;
\r
449 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
450 high priority tasks. */
\r
451 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
453 portENTER_CRITICAL();
\r
455 uxValueForNormallyFullQueue++;
\r
456 uxValueToTx = uxValueForNormallyFullQueue;
\r
458 portEXIT_CRITICAL();
\r
460 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
465 portENTER_CRITICAL();
\r
467 uxValueForNormallyFullQueue++;
\r
468 uxValueToTx = uxValueForNormallyFullQueue;
\r
470 portEXIT_CRITICAL();
\r
472 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )
\r
474 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
475 expect it to ever time out. */
\r
476 prvQueueAccessLogError( __LINE__ );
\r
479 /* Allow the other task running this code to run. */
\r
482 /* Have all the expected values been sent to the queue? */
\r
483 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
485 /* Make sure the other high priority task completes its send of
\r
486 any values below intqNUM_VALUE_TO_LOG. */
\r
487 vTaskDelay( intqSHORT_DELAY );
\r
489 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
491 if( xWasSuspended == pdTRUE )
\r
493 /* We would have expected the other high priority task to have
\r
494 set this back to false by now. */
\r
495 prvQueueAccessLogError( __LINE__ );
\r
498 /* Set the suspended flag so an error is not logged if the other
\r
499 task recognises a time out when it is unsuspended. */
\r
500 xWasSuspended = pdTRUE;
\r
502 /* Start at 1 as we expect position 0 to be unused. */
\r
503 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
505 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
507 /* A value was missing. */
\r
508 prvQueueAccessLogError( __LINE__ );
\r
512 /* Reset the array ready for the next cycle. */
\r
513 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
515 uxHighPriorityLoops2++;
\r
516 uxValueForNormallyFullQueue = 0;
\r
518 /* Suspend ourselves, allowing the lower priority task to
\r
519 actually receive something from the queue. Until now it
\r
520 will have been prevented from doing so by the higher
\r
521 priority tasks. The lower priority task will resume us
\r
522 if it receives something. We will then resume the other
\r
523 higher priority task. */
\r
524 vTaskSuspend( NULL );
\r
525 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
529 /*-----------------------------------------------------------*/
\r
531 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
533 unsigned portBASE_TYPE uxValueToTx, ux;
\r
534 portBASE_TYPE xQueueStatus;
\r
536 /* The parameters are not being used so avoid compiler warnings. */
\r
537 ( void ) pvParameters;
\r
539 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
540 high priority tasks. */
\r
541 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
543 portENTER_CRITICAL();
\r
545 uxValueForNormallyFullQueue++;
\r
546 uxValueToTx = uxValueForNormallyFullQueue;
\r
548 portEXIT_CRITICAL();
\r
550 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
555 portENTER_CRITICAL();
\r
557 uxValueForNormallyFullQueue++;
\r
558 uxValueToTx = uxValueForNormallyFullQueue;
\r
560 portEXIT_CRITICAL();
\r
562 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )
\r
564 if( xWasSuspended != pdTRUE )
\r
566 /* It is ok to time out if the task has been suspended. */
\r
567 prvQueueAccessLogError( __LINE__ );
\r
571 xWasSuspended = pdFALSE;
\r
576 /*-----------------------------------------------------------*/
\r
578 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
580 unsigned portBASE_TYPE uxValue, uxTxed = 9999;
\r
581 portBASE_TYPE xQueueStatus;
\r
583 /* The parameters are not being used so avoid compiler warnings. */
\r
584 ( void ) pvParameters;
\r
588 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) ) != errQUEUE_FULL )
\r
590 /* We would only expect to succeed when the higher priority task
\r
592 if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE )
\r
594 prvQueueAccessLogError( __LINE__ );
\r
597 vTaskResume( xHighPriorityNormallyFullTask1 );
\r
598 uxLowPriorityLoops2++;
\r
602 /* Raise our priority while we receive so we can preempt the higher
\r
603 priority task, and ensure we get the value from the queue. */
\r
604 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
606 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
608 prvQueueAccessLogError( __LINE__ );
\r
612 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
\r
615 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
619 /*-----------------------------------------------------------*/
\r
621 portBASE_TYPE xFirstTimerHandler( void )
\r
623 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;
\r
624 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
626 /* Called from a timer interrupt. Perform various read and write
\r
627 accesses on the queues. */
\r
631 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
633 timerNORMALLY_EMPTY_TX();
\r
634 timerNORMALLY_EMPTY_TX();
\r
635 timerNORMALLY_EMPTY_TX();
\r
639 timerNORMALLY_FULL_RX();
\r
640 timerNORMALLY_FULL_RX();
\r
641 timerNORMALLY_FULL_RX();
\r
644 return xHigherPriorityTaskWoken;
\r
646 /*-----------------------------------------------------------*/
\r
648 portBASE_TYPE xSecondTimerHandler( void )
\r
650 unsigned portBASE_TYPE uxRxedValue;
\r
651 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
652 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
654 /* Called from a timer interrupt. Perform various read and write
\r
655 accesses on the queues. */
\r
659 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
661 timerNORMALLY_EMPTY_TX();
\r
662 timerNORMALLY_EMPTY_TX();
\r
664 timerNORMALLY_EMPTY_RX();
\r
665 timerNORMALLY_EMPTY_RX();
\r
669 timerNORMALLY_FULL_RX();
\r
670 timerNORMALLY_FULL_TX();
\r
671 timerNORMALLY_FULL_TX();
\r
672 timerNORMALLY_FULL_TX();
\r
673 timerNORMALLY_FULL_TX();
\r
676 return xHigherPriorityTaskWoken;
\r
678 /*-----------------------------------------------------------*/
\r
681 portBASE_TYPE xAreIntQueueTasksStillRunning( void )
\r
683 static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
685 /* xErrorStatus can be set outside of this function. This function just
\r
686 checks that all the tasks are still cycling. */
\r
688 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
690 /* The high priority 1 task has stalled. */
\r
691 prvQueueAccessLogError( __LINE__ );
\r
694 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
696 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
698 /* The high priority 2 task has stalled. */
\r
699 prvQueueAccessLogError( __LINE__ );
\r
702 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
704 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
706 /* The low priority 1 task has stalled. */
\r
707 prvQueueAccessLogError( __LINE__ );
\r
710 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
712 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
714 /* The low priority 2 task has stalled. */
\r
715 prvQueueAccessLogError( __LINE__ );
\r
718 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
720 return xErrorStatus;
\r