2 FreeRTOS V7.4.2 - Copyright (C) 2013 Real Time Engineers Ltd.
\r
4 FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
\r
5 http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
10 * Complete, revised, and edited pdf reference manuals are also *
\r
13 * Purchasing FreeRTOS documentation will not only help you, by *
\r
14 * ensuring you get running as quickly as possible and with an *
\r
15 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
16 * the FreeRTOS project to continue with its mission of providing *
\r
17 * professional grade, cross platform, de facto standard solutions *
\r
18 * for microcontrollers - completely free of charge! *
\r
20 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
22 * Thank you for using FreeRTOS, and thank you for your support! *
\r
24 ***************************************************************************
\r
27 This file is part of the FreeRTOS distribution.
\r
29 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
30 the terms of the GNU General Public License (version 2) as published by the
\r
31 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
33 >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to
\r
34 distribute a combined work that includes FreeRTOS without being obliged to
\r
35 provide the source code for proprietary components outside of the FreeRTOS
\r
38 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
39 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
40 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
\r
41 details. You should have received a copy of the GNU General Public License
\r
42 and the FreeRTOS license exception along with FreeRTOS; if not it can be
\r
43 viewed here: http://www.freertos.org/a00114.html and also obtained by
\r
44 writing to Real Time Engineers Ltd., contact details for whom are available
\r
45 on the FreeRTOS WEB site.
\r
49 ***************************************************************************
\r
51 * Having a problem? Start by reading the FAQ "My application does *
\r
52 * not run, what could be wrong?" *
\r
54 * http://www.FreeRTOS.org/FAQHelp.html *
\r
56 ***************************************************************************
\r
59 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
60 license and Real Time Engineers Ltd. contact details.
\r
62 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
63 including FreeRTOS+Trace - an indispensable productivity tool, and our new
\r
64 fully thread aware and reentrant UDP/IP stack.
\r
66 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
67 Integrity Systems, who sell the code with commercial support,
\r
68 indemnification and middleware, under the OpenRTOS brand.
\r
70 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
71 engineered and independently SIL3 certified version for use in safety and
\r
72 mission critical applications that require provable dependability.
\r
76 * This file defines one of the more complex set of demo/test tasks. They are
\r
77 * designed to stress test the queue implementation though pseudo simultaneous
\r
78 * multiple reads and multiple writes from both tasks of varying priority and
\r
79 * interrupts. The interrupts are prioritised such to ensure that nesting
\r
80 * occurs (for those ports that support it).
\r
82 * The test ensures that, while being accessed from three tasks and two
\r
83 * interrupts, all the data sent to the queues is also received from
\r
84 * the same queue, and that no duplicate items are either sent or received.
\r
85 * The tests also ensure that a low priority task is never able to successfully
\r
86 * read from or write to a queue when a task of higher priority is attempting
\r
87 * the same operation.
\r
90 /* Standard includes. */
\r
93 /* SafeRTOS includes. */
\r
94 #include "FreeRTOS.h"
\r
98 /* Demo app includes. */
\r
99 #include "IntQueue.h"
\r
100 #include "IntQueueTimer.h"
\r
102 /* Priorities used by test tasks. */
\r
103 #ifndef intqHIGHER_PRIORITY
\r
104 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
106 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
108 /* The number of values to send/receive before checking that all values were
\r
109 processed as expected. */
\r
110 #define intqNUM_VALUES_TO_LOG ( 200 )
\r
111 #define intqSHORT_DELAY ( 140 )
\r
113 /* The value by which the value being sent to or received from a queue should
\r
114 increment past intqNUM_VALUES_TO_LOG before we check that all values have been
\r
115 sent/received correctly. This is done to ensure that all tasks and interrupts
\r
116 accessing the queue have completed their accesses with the
\r
117 intqNUM_VALUES_TO_LOG range. */
\r
118 #define intqVALUE_OVERRUN ( 50 )
\r
120 /* The delay used by the polling task. A short delay is used for code
\r
122 #define intqONE_TICK_DELAY ( 1 )
\r
124 /* Each task and interrupt is given a unique identifier. This value is used to
\r
125 identify which task sent or received each value. The identifier is also used
\r
126 to distinguish between two tasks that are running the same task function. */
\r
127 #define intqHIGH_PRIORITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 )
\r
128 #define intqHIGH_PRIORITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 )
\r
129 #define intqLOW_PRIORITY_TASK ( ( unsigned portBASE_TYPE ) 3 )
\r
130 #define intqFIRST_INTERRUPT ( ( unsigned portBASE_TYPE ) 4 )
\r
131 #define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 )
\r
132 #define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 )
\r
134 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
\r
135 from each queue by each task, otherwise an error is detected. */
\r
136 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
\r
138 /* Send the next value to the queue that is normally empty. This is called
\r
139 from within the interrupts. */
\r
140 #define timerNORMALLY_EMPTY_TX() \
\r
141 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
\r
143 unsigned portBASE_TYPE uxSavedInterruptStatus; \
\r
144 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
146 uxValueForNormallyEmptyQueue++; \
\r
147 xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \
\r
149 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
152 /* Send the next value to the queue that is normally full. This is called
\r
153 from within the interrupts. */
\r
154 #define timerNORMALLY_FULL_TX() \
\r
155 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
\r
157 unsigned portBASE_TYPE uxSavedInterruptStatus; \
\r
158 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
160 uxValueForNormallyFullQueue++; \
\r
161 xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \
\r
163 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
166 /* Receive a value from the normally empty queue. This is called from within
\r
168 #define timerNORMALLY_EMPTY_RX() \
\r
169 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
171 prvQueueAccessLogError( __LINE__ ); \
\r
175 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
178 /* Receive a value from the normally full queue. This is called from within
\r
180 #define timerNORMALLY_FULL_RX() \
\r
181 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
\r
183 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
187 /*-----------------------------------------------------------*/
\r
189 /* The two queues used by the test. */
\r
190 static xQueueHandle xNormallyEmptyQueue, xNormallyFullQueue;
\r
192 /* Variables used to detect a stall in one of the tasks. */
\r
193 static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
\r
195 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
\r
196 caused the error in xErrorLine. */
\r
197 static portBASE_TYPE xErrorStatus = pdPASS;
\r
198 static volatile unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;
\r
200 /* Used for sequencing between tasks. */
\r
201 static portBASE_TYPE xWasSuspended = pdFALSE;
\r
203 /* The values that are sent to the queues. An incremented value is sent each
\r
204 time to each queue. */
\r
205 volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
\r
207 /* A handle to some of the tasks is required so they can be suspended/resumed. */
\r
208 xTaskHandle xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
\r
210 /* When a value is received in a queue the value is ticked off in the array
\r
211 the array position of the value is set to a the identifier of the task or
\r
212 interrupt that accessed the queue. This way missing or duplicate values can be
\r
214 static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
215 static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
217 /* The test tasks themselves. */
\r
218 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
\r
219 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
\r
220 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
\r
221 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
\r
222 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
\r
224 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
\r
225 ucNormallyFullReceivedValues arrays, while checking for duplicates. */
\r
226 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
\r
227 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
\r
229 /* Logs the line on which an error occurred. */
\r
230 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine );
\r
232 /*-----------------------------------------------------------*/
\r
234 void vStartInterruptQueueTasks( void )
\r
236 /* Start the test tasks. */
\r
237 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
\r
238 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
\r
239 xTaskCreate( prvLowerPriorityNormallyEmptyTask, ( signed portCHAR * ) "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
240 xTaskCreate( prv1stHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
\r
241 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
\r
242 xTaskCreate( prvLowerPriorityNormallyFullTask, ( signed portCHAR * ) "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
244 /* Create the queues that are accessed by multiple tasks and multiple
\r
246 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
\r
247 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
\r
248 // vTraceSetQueueName( xNormallyFullQueue, "NF" );
\r
249 // vTraceSetQueueName( xNormallyEmptyQueue, "NE" );
\r
251 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
252 in use. The queue registry is provided as a means for kernel aware
\r
253 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
254 is not being used. The call to vQueueAddToRegistry() will be removed
\r
255 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
256 defined to be less than 1. */
\r
257 vQueueAddToRegistry( xNormallyFullQueue, ( signed portCHAR * ) "NormallyFull" );
\r
258 vQueueAddToRegistry( xNormallyEmptyQueue, ( signed portCHAR * ) "NormallyEmpty" );
\r
260 /*-----------------------------------------------------------*/
\r
262 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
264 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
266 /* We don't expect to receive the same value twice, so if the value
\r
267 has already been marked as received an error has occurred. */
\r
268 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
270 prvQueueAccessLogError( __LINE__ );
\r
273 /* Log that this value has been received. */
\r
274 ucNormallyFullReceivedValues[ uxValue ] = uxSource;
\r
277 /*-----------------------------------------------------------*/
\r
279 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
281 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
283 /* We don't expect to receive the same value twice, so if the value
\r
284 has already been marked as received an error has occurred. */
\r
285 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
287 prvQueueAccessLogError( __LINE__ );
\r
290 /* Log that this value has been received. */
\r
291 ucNormallyEmptyReceivedValues[ uxValue ] = uxSource;
\r
294 /*-----------------------------------------------------------*/
\r
296 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
\r
298 /* Latch the line number that caused the error. */
\r
299 xErrorLine = uxLine;
\r
300 xErrorStatus = pdFAIL;
\r
302 /*-----------------------------------------------------------*/
\r
304 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
306 unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
\r
308 /* The timer should not be started until after the scheduler has started.
\r
309 More than one task is running this code so we check the parameter value
\r
310 to determine which task should start the timer. */
\r
311 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
313 vInitialiseTimerForIntQueueTest();
\r
318 /* Block waiting to receive a value from the normally empty queue.
\r
319 Interrupts will write to the queue so we should receive a value. */
\r
320 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
322 prvQueueAccessLogError( __LINE__ );
\r
326 /* Note which value was received so we can check all expected
\r
327 values are received and no values are duplicated. */
\r
328 prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );
\r
331 /* Ensure the other task running this code gets a chance to execute. */
\r
334 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
336 /* Have we received all the expected values? */
\r
337 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
339 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
345 /* Loop through the array, checking that both tasks have
\r
346 placed values into the array, and that no values are missing.
\r
347 Start at 1 as we expect position 0 to be unused. */
\r
348 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
350 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
352 /* A value is missing. */
\r
353 prvQueueAccessLogError( __LINE__ );
\r
357 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
359 /* Value was placed into the array by task 1. */
\r
362 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
364 /* Value was placed into the array by task 2. */
\r
367 else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
374 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
376 /* Only task 2 seemed to log any values. */
\r
378 if( uxErrorCount1 > 2 )
\r
380 prvQueueAccessLogError( __LINE__ );
\r
388 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
390 /* Only task 1 seemed to log any values. */
\r
392 if( uxErrorCount2 > 2 )
\r
394 prvQueueAccessLogError( __LINE__ );
\r
402 if( uxInterrupts == 0 )
\r
404 prvQueueAccessLogError( __LINE__ );
\r
407 /* Clear the array again, ready to start a new cycle. */
\r
408 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
410 uxHighPriorityLoops1++;
\r
411 uxValueForNormallyEmptyQueue = 0;
\r
413 /* Suspend ourselves, allowing the lower priority task to
\r
414 actually receive something from the queue. Until now it
\r
415 will have been prevented from doing so by the higher
\r
416 priority tasks. The lower priority task will resume us
\r
417 if it receives something. We will then resume the other
\r
418 higher priority task. */
\r
419 vTaskSuspend( NULL );
\r
420 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
425 /*-----------------------------------------------------------*/
\r
427 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
429 unsigned portBASE_TYPE uxValue, uxRxed;
\r
431 /* The parameters are not being used so avoid compiler warnings. */
\r
432 ( void ) pvParameters;
\r
436 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
\r
438 /* We should only obtain a value when the high priority task is
\r
440 if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE )
\r
442 prvQueueAccessLogError( __LINE__ );
\r
445 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
447 /* Wake the higher priority task again. */
\r
448 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
449 uxLowPriorityLoops1++;
\r
453 /* Raise our priority while we send so we can preempt the higher
\r
454 priority task, and ensure we get the Tx value into the queue. */
\r
455 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
457 portENTER_CRITICAL();
\r
459 uxValueForNormallyEmptyQueue++;
\r
460 uxValue = uxValueForNormallyEmptyQueue;
\r
462 portEXIT_CRITICAL();
\r
464 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
466 prvQueueAccessLogError( __LINE__ );
\r
469 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
473 /*-----------------------------------------------------------*/
\r
475 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
477 unsigned portBASE_TYPE uxValueToTx, ux, uxInterrupts;
\r
479 /* The parameters are not being used so avoid compiler warnings. */
\r
480 ( void ) pvParameters;
\r
482 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
483 high priority tasks. */
\r
484 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
486 portENTER_CRITICAL();
\r
488 uxValueForNormallyFullQueue++;
\r
489 uxValueToTx = uxValueForNormallyFullQueue;
\r
491 portEXIT_CRITICAL();
\r
493 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
498 portENTER_CRITICAL();
\r
500 uxValueForNormallyFullQueue++;
\r
501 uxValueToTx = uxValueForNormallyFullQueue;
\r
503 portEXIT_CRITICAL();
\r
505 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
507 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
508 expect it to ever time out. */
\r
509 prvQueueAccessLogError( __LINE__ );
\r
512 /* Allow the other task running this code to run. */
\r
515 /* Have all the expected values been sent to the queue? */
\r
516 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
518 /* Make sure the other high priority task completes its send of
\r
519 any values below intqNUM_VALUE_TO_LOG. */
\r
520 vTaskDelay( intqSHORT_DELAY );
\r
522 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
524 if( xWasSuspended == pdTRUE )
\r
526 /* We would have expected the other high priority task to have
\r
527 set this back to false by now. */
\r
528 prvQueueAccessLogError( __LINE__ );
\r
531 /* Set the suspended flag so an error is not logged if the other
\r
532 task recognises a time out when it is unsuspended. */
\r
533 xWasSuspended = pdTRUE;
\r
535 /* Check interrupts are also sending. */
\r
538 /* Start at 1 as we expect position 0 to be unused. */
\r
539 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
541 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
543 /* A value was missing. */
\r
544 prvQueueAccessLogError( __LINE__ );
\r
546 else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
552 if( uxInterrupts == 0 )
\r
554 /* No writes from interrupts were found. Are interrupts
\r
555 actually running? */
\r
556 prvQueueAccessLogError( __LINE__ );
\r
559 /* Reset the array ready for the next cycle. */
\r
560 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
562 uxHighPriorityLoops2++;
\r
563 uxValueForNormallyFullQueue = 0;
\r
565 /* Suspend ourselves, allowing the lower priority task to
\r
566 actually receive something from the queue. Until now it
\r
567 will have been prevented from doing so by the higher
\r
568 priority tasks. The lower priority task will resume us
\r
569 if it receives something. We will then resume the other
\r
570 higher priority task. */
\r
571 vTaskSuspend( NULL );
\r
572 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
576 /*-----------------------------------------------------------*/
\r
578 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
580 unsigned portBASE_TYPE uxValueToTx, ux;
\r
582 /* The parameters are not being used so avoid compiler warnings. */
\r
583 ( void ) pvParameters;
\r
585 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
586 high priority tasks. */
\r
587 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
589 portENTER_CRITICAL();
\r
591 uxValueForNormallyFullQueue++;
\r
592 uxValueToTx = uxValueForNormallyFullQueue;
\r
594 portEXIT_CRITICAL();
\r
596 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
601 portENTER_CRITICAL();
\r
603 uxValueForNormallyFullQueue++;
\r
604 uxValueToTx = uxValueForNormallyFullQueue;
\r
606 portEXIT_CRITICAL();
\r
608 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
610 if( xWasSuspended != pdTRUE )
\r
612 /* It is ok to time out if the task has been suspended. */
\r
613 prvQueueAccessLogError( __LINE__ );
\r
617 xWasSuspended = pdFALSE;
\r
622 /*-----------------------------------------------------------*/
\r
624 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
626 unsigned portBASE_TYPE uxValue, uxTxed = 9999;
\r
628 /* The parameters are not being used so avoid compiler warnings. */
\r
629 ( void ) pvParameters;
\r
633 if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
\r
635 /* We would only expect to succeed when the higher priority task
\r
637 if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE )
\r
639 prvQueueAccessLogError( __LINE__ );
\r
642 vTaskResume( xHighPriorityNormallyFullTask1 );
\r
643 uxLowPriorityLoops2++;
\r
647 /* Raise our priority while we receive so we can preempt the higher
\r
648 priority task, and ensure we get the value from the queue. */
\r
649 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
651 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
653 prvQueueAccessLogError( __LINE__ );
\r
657 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
\r
660 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
664 /*-----------------------------------------------------------*/
\r
666 portBASE_TYPE xFirstTimerHandler( void )
\r
668 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;
\r
669 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
671 /* Called from a timer interrupt. Perform various read and write
\r
672 accesses on the queues. */
\r
676 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
678 timerNORMALLY_EMPTY_TX();
\r
679 timerNORMALLY_EMPTY_TX();
\r
680 timerNORMALLY_EMPTY_TX();
\r
684 timerNORMALLY_FULL_RX();
\r
685 timerNORMALLY_FULL_RX();
\r
686 timerNORMALLY_FULL_RX();
\r
689 return xHigherPriorityTaskWoken;
\r
691 /*-----------------------------------------------------------*/
\r
693 portBASE_TYPE xSecondTimerHandler( void )
\r
695 unsigned portBASE_TYPE uxRxedValue;
\r
696 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
697 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
699 /* Called from a timer interrupt. Perform various read and write
\r
700 accesses on the queues. */
\r
704 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
706 timerNORMALLY_EMPTY_TX();
\r
707 timerNORMALLY_EMPTY_TX();
\r
709 timerNORMALLY_EMPTY_RX();
\r
710 timerNORMALLY_EMPTY_RX();
\r
714 timerNORMALLY_FULL_RX();
\r
715 timerNORMALLY_FULL_TX();
\r
716 timerNORMALLY_FULL_TX();
\r
717 timerNORMALLY_FULL_TX();
\r
718 timerNORMALLY_FULL_TX();
\r
721 return xHigherPriorityTaskWoken;
\r
723 /*-----------------------------------------------------------*/
\r
726 portBASE_TYPE xAreIntQueueTasksStillRunning( void )
\r
728 static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
730 /* xErrorStatus can be set outside of this function. This function just
\r
731 checks that all the tasks are still cycling. */
\r
733 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
735 /* The high priority 1 task has stalled. */
\r
736 prvQueueAccessLogError( __LINE__ );
\r
739 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
741 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
743 /* The high priority 2 task has stalled. */
\r
744 prvQueueAccessLogError( __LINE__ );
\r
747 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
749 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
751 /* The low priority 1 task has stalled. */
\r
752 prvQueueAccessLogError( __LINE__ );
\r
755 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
757 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
759 /* The low priority 2 task has stalled. */
\r
760 prvQueueAccessLogError( __LINE__ );
\r
763 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
765 return xErrorStatus;
\r