2 FreeRTOS V7.4.1 - 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 ( 75 )
\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 * ) "LQRx", 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 * ) "LQRx", 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
249 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
250 in use. The queue registry is provided as a means for kernel aware
\r
251 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
252 is not being used. The call to vQueueAddToRegistry() will be removed
\r
253 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
254 defined to be less than 1. */
\r
255 vQueueAddToRegistry( xNormallyFullQueue, ( signed portCHAR * ) "NormallyFull" );
\r
256 vQueueAddToRegistry( xNormallyEmptyQueue, ( signed portCHAR * ) "NormallyEmpty" );
\r
258 /*-----------------------------------------------------------*/
\r
260 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
262 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
264 /* We don't expect to receive the same value twice, so if the value
\r
265 has already been marked as received an error has occurred. */
\r
266 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
268 prvQueueAccessLogError( __LINE__ );
\r
271 /* Log that this value has been received. */
\r
272 ucNormallyFullReceivedValues[ uxValue ] = uxSource;
\r
275 /*-----------------------------------------------------------*/
\r
277 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
279 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
281 /* We don't expect to receive the same value twice, so if the value
\r
282 has already been marked as received an error has occurred. */
\r
283 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
285 prvQueueAccessLogError( __LINE__ );
\r
288 /* Log that this value has been received. */
\r
289 ucNormallyEmptyReceivedValues[ uxValue ] = uxSource;
\r
292 /*-----------------------------------------------------------*/
\r
294 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
\r
296 /* Latch the line number that caused the error. */
\r
297 xErrorLine = uxLine;
\r
298 xErrorStatus = pdFAIL;
\r
300 /*-----------------------------------------------------------*/
\r
302 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
304 unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
\r
306 /* The timer should not be started until after the scheduler has started.
\r
307 More than one task is running this code so we check the parameter value
\r
308 to determine which task should start the timer. */
\r
309 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
311 vInitialiseTimerForIntQueueTest();
\r
316 /* Block waiting to receive a value from the normally empty queue.
\r
317 Interrupts will write to the queue so we should receive a value. */
\r
318 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
320 prvQueueAccessLogError( __LINE__ );
\r
324 /* Note which value was received so we can check all expected
\r
325 values are received and no values are duplicated. */
\r
326 prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );
\r
329 /* Ensure the other task running this code gets a chance to execute. */
\r
332 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
334 /* Have we received all the expected values? */
\r
335 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
337 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
343 /* Loop through the array, checking that both tasks have
\r
344 placed values into the array, and that no values are missing.
\r
345 Start at 1 as we expect position 0 to be unused. */
\r
346 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
348 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
350 /* A value is missing. */
\r
351 prvQueueAccessLogError( __LINE__ );
\r
355 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
357 /* Value was placed into the array by task 1. */
\r
360 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
362 /* Value was placed into the array by task 2. */
\r
365 else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
372 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
374 /* Only task 2 seemed to log any values. */
\r
376 if( uxErrorCount1 > 2 )
\r
378 prvQueueAccessLogError( __LINE__ );
\r
386 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
388 /* Only task 1 seemed to log any values. */
\r
390 if( uxErrorCount2 > 2 )
\r
392 prvQueueAccessLogError( __LINE__ );
\r
400 if( uxInterrupts == 0 )
\r
402 prvQueueAccessLogError( __LINE__ );
\r
405 /* Clear the array again, ready to start a new cycle. */
\r
406 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
408 uxHighPriorityLoops1++;
\r
409 uxValueForNormallyEmptyQueue = 0;
\r
411 /* Suspend ourselves, allowing the lower priority task to
\r
412 actually receive something from the queue. Until now it
\r
413 will have been prevented from doing so by the higher
\r
414 priority tasks. The lower priority task will resume us
\r
415 if it receives something. We will then resume the other
\r
416 higher priority task. */
\r
417 vTaskSuspend( NULL );
\r
418 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
423 /*-----------------------------------------------------------*/
\r
425 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
427 unsigned portBASE_TYPE uxValue, uxRxed;
\r
429 /* The parameters are not being used so avoid compiler warnings. */
\r
430 ( void ) pvParameters;
\r
434 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
\r
436 /* We should only obtain a value when the high priority task is
\r
438 if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE )
\r
440 prvQueueAccessLogError( __LINE__ );
\r
443 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
445 /* Wake the higher priority task again. */
\r
446 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
447 uxLowPriorityLoops1++;
\r
451 /* Raise our priority while we send so we can preempt the higher
\r
452 priority task, and ensure we get the Tx value into the queue. */
\r
453 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
455 portENTER_CRITICAL();
\r
457 uxValueForNormallyEmptyQueue++;
\r
458 uxValue = uxValueForNormallyEmptyQueue;
\r
460 portEXIT_CRITICAL();
\r
462 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
464 prvQueueAccessLogError( __LINE__ );
\r
467 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
471 /*-----------------------------------------------------------*/
\r
473 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
475 unsigned portBASE_TYPE uxValueToTx, ux, uxInterrupts;
\r
477 /* The parameters are not being used so avoid compiler warnings. */
\r
478 ( void ) pvParameters;
\r
480 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
481 high priority tasks. */
\r
482 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
484 portENTER_CRITICAL();
\r
486 uxValueForNormallyFullQueue++;
\r
487 uxValueToTx = uxValueForNormallyFullQueue;
\r
489 portEXIT_CRITICAL();
\r
491 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
496 portENTER_CRITICAL();
\r
498 uxValueForNormallyFullQueue++;
\r
499 uxValueToTx = uxValueForNormallyFullQueue;
\r
501 portEXIT_CRITICAL();
\r
503 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
505 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
506 expect it to ever time out. */
\r
507 prvQueueAccessLogError( __LINE__ );
\r
510 /* Allow the other task running this code to run. */
\r
513 /* Have all the expected values been sent to the queue? */
\r
514 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
516 /* Make sure the other high priority task completes its send of
\r
517 any values below intqNUM_VALUE_TO_LOG. */
\r
518 vTaskDelay( intqSHORT_DELAY );
\r
520 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
522 if( xWasSuspended == pdTRUE )
\r
524 /* We would have expected the other high priority task to have
\r
525 set this back to false by now. */
\r
526 prvQueueAccessLogError( __LINE__ );
\r
529 /* Set the suspended flag so an error is not logged if the other
\r
530 task recognises a time out when it is unsuspended. */
\r
531 xWasSuspended = pdTRUE;
\r
533 /* Check interrupts are also sending. */
\r
536 /* Start at 1 as we expect position 0 to be unused. */
\r
537 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
539 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
541 /* A value was missing. */
\r
542 prvQueueAccessLogError( __LINE__ );
\r
544 else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
550 if( uxInterrupts == 0 )
\r
552 /* No writes from interrupts were found. Are interrupts
\r
553 actually running? */
\r
554 prvQueueAccessLogError( __LINE__ );
\r
557 /* Reset the array ready for the next cycle. */
\r
558 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
560 uxHighPriorityLoops2++;
\r
561 uxValueForNormallyFullQueue = 0;
\r
563 /* Suspend ourselves, allowing the lower priority task to
\r
564 actually receive something from the queue. Until now it
\r
565 will have been prevented from doing so by the higher
\r
566 priority tasks. The lower priority task will resume us
\r
567 if it receives something. We will then resume the other
\r
568 higher priority task. */
\r
569 vTaskSuspend( NULL );
\r
570 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
574 /*-----------------------------------------------------------*/
\r
576 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
578 unsigned portBASE_TYPE uxValueToTx, ux;
\r
580 /* The parameters are not being used so avoid compiler warnings. */
\r
581 ( void ) pvParameters;
\r
583 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
584 high priority tasks. */
\r
585 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
587 portENTER_CRITICAL();
\r
589 uxValueForNormallyFullQueue++;
\r
590 uxValueToTx = uxValueForNormallyFullQueue;
\r
592 portEXIT_CRITICAL();
\r
594 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
599 portENTER_CRITICAL();
\r
601 uxValueForNormallyFullQueue++;
\r
602 uxValueToTx = uxValueForNormallyFullQueue;
\r
604 portEXIT_CRITICAL();
\r
606 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
608 if( xWasSuspended != pdTRUE )
\r
610 /* It is ok to time out if the task has been suspended. */
\r
611 prvQueueAccessLogError( __LINE__ );
\r
615 xWasSuspended = pdFALSE;
\r
620 /*-----------------------------------------------------------*/
\r
622 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
624 unsigned portBASE_TYPE uxValue, uxTxed = 9999;
\r
626 /* The parameters are not being used so avoid compiler warnings. */
\r
627 ( void ) pvParameters;
\r
631 if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
\r
633 /* We would only expect to succeed when the higher priority task
\r
635 if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE )
\r
637 prvQueueAccessLogError( __LINE__ );
\r
640 vTaskResume( xHighPriorityNormallyFullTask1 );
\r
641 uxLowPriorityLoops2++;
\r
645 /* Raise our priority while we receive so we can preempt the higher
\r
646 priority task, and ensure we get the value from the queue. */
\r
647 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
649 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
651 prvQueueAccessLogError( __LINE__ );
\r
655 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
\r
658 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
662 /*-----------------------------------------------------------*/
\r
664 portBASE_TYPE xFirstTimerHandler( void )
\r
666 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;
\r
667 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
669 /* Called from a timer interrupt. Perform various read and write
\r
670 accesses on the queues. */
\r
674 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
676 timerNORMALLY_EMPTY_TX();
\r
677 timerNORMALLY_EMPTY_TX();
\r
678 timerNORMALLY_EMPTY_TX();
\r
682 timerNORMALLY_FULL_RX();
\r
683 timerNORMALLY_FULL_RX();
\r
684 timerNORMALLY_FULL_RX();
\r
687 return xHigherPriorityTaskWoken;
\r
689 /*-----------------------------------------------------------*/
\r
691 portBASE_TYPE xSecondTimerHandler( void )
\r
693 unsigned portBASE_TYPE uxRxedValue;
\r
694 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
695 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
697 /* Called from a timer interrupt. Perform various read and write
\r
698 accesses on the queues. */
\r
702 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
704 timerNORMALLY_EMPTY_TX();
\r
705 timerNORMALLY_EMPTY_TX();
\r
707 timerNORMALLY_EMPTY_RX();
\r
708 timerNORMALLY_EMPTY_RX();
\r
712 timerNORMALLY_FULL_RX();
\r
713 timerNORMALLY_FULL_TX();
\r
714 timerNORMALLY_FULL_TX();
\r
715 timerNORMALLY_FULL_TX();
\r
716 timerNORMALLY_FULL_TX();
\r
719 return xHigherPriorityTaskWoken;
\r
721 /*-----------------------------------------------------------*/
\r
724 portBASE_TYPE xAreIntQueueTasksStillRunning( void )
\r
726 static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
728 /* xErrorStatus can be set outside of this function. This function just
\r
729 checks that all the tasks are still cycling. */
\r
731 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
733 /* The high priority 1 task has stalled. */
\r
734 prvQueueAccessLogError( __LINE__ );
\r
737 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
739 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
741 /* The high priority 2 task has stalled. */
\r
742 prvQueueAccessLogError( __LINE__ );
\r
745 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
747 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
749 /* The low priority 1 task has stalled. */
\r
750 prvQueueAccessLogError( __LINE__ );
\r
753 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
755 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
757 /* The low priority 2 task has stalled. */
\r
758 prvQueueAccessLogError( __LINE__ );
\r
761 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
763 return xErrorStatus;
\r