2 FreeRTOS.org V5.0.3 - Copyright (C) 2003-2008 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS.org is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 ***************************************************************************
\r
29 * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, *
\r
30 * and even write all or part of your application on your behalf. *
\r
31 * See http://www.OpenRTOS.com for details of the services we provide to *
\r
32 * expedite your project. *
\r
34 ***************************************************************************
\r
35 ***************************************************************************
\r
37 Please ensure to read the configuration and relevant port sections of the
\r
38 online documentation.
\r
40 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
43 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
46 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
47 licensing and training services.
\r
51 * This file defines one of the more complex set of demo/test tasks. They are
\r
52 * designed to stress test the queue implementation though pseudo simultaneous
\r
53 * multiple reads and multiple writes from both tasks of varying priority and
\r
54 * interrupts. The interrupts are prioritised such to ensure that nesting
\r
55 * occurs (for those ports that support it).
\r
57 * The test ensures that, while being accessed from three tasks and two
\r
58 * interrupts, all the data sent to the queues is also received from
\r
59 * the same queue, and that no duplicate items are either sent or received.
\r
60 * The tests also ensure that a low priority task is never able to successfully
\r
61 * read from or write to a queue when a task of higher priority is attempting
\r
62 * the same operation.
\r
65 /* Standard includes. */
\r
68 /* SafeRTOS includes. */
\r
69 #include "FreeRTOS.h"
\r
73 /* Demo app includes. */
\r
74 #include "IntQueue.h"
\r
75 #include "IntQueueTimer.h"
\r
77 /* Priorities used by test tasks. */
\r
78 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
79 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
81 /* The number of values to send/receive before checking that all values were
\r
82 processed as expected. */
\r
83 #define intqNUM_VALUES_TO_LOG ( 200 )
\r
84 #define intqSHORT_DELAY ( 75 )
\r
86 /* The value by which the value being sent to or received from a queue should
\r
87 increment past intqNUM_VALUES_TO_LOG before we check that all values have been
\r
88 sent/received correctly. This is done to ensure that all tasks and interrupts
\r
89 accessing the queue have completed their accesses with the
\r
90 intqNUM_VALUES_TO_LOG range. */
\r
91 #define intqVALUE_OVERRUN ( 50 )
\r
93 /* The delay used by the polling task. A short delay is used for code
\r
95 #define intqONE_TICK_DELAY ( 1 )
\r
97 /* Each task and interrupt is given a unique identifier. This value is used to
\r
98 identify which task sent or received each value. The identifier is also used
\r
99 to distinguish between two tasks that are running the same task function. */
\r
100 #define intqHIGH_PRIORITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 )
\r
101 #define intqHIGH_PRIORITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 )
\r
102 #define intqLOW_PRIORITY_TASK ( ( unsigned portBASE_TYPE ) 3 )
\r
103 #define intqFIRST_INTERRUPT ( ( unsigned portBASE_TYPE ) 4 )
\r
104 #define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 )
\r
105 #define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 )
\r
107 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
\r
108 from each queue by each task, otherwise an error is detected. */
\r
109 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
\r
111 /* Send the next value to the queue that is normally empty. This is called
\r
112 from within the interrupts. */
\r
113 #define timerNORMALLY_EMPTY_TX() \
\r
114 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
\r
116 unsigned portBASE_TYPE uxSavedInterruptStatus; \
\r
117 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
119 xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \
\r
120 uxValueForNormallyEmptyQueue++; \
\r
122 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
125 /* Send the next value to the queue that is normally full. This is called
\r
126 from within the interrupts. */
\r
127 #define timerNORMALLY_FULL_TX() \
\r
128 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
\r
130 unsigned portBASE_TYPE uxSavedInterruptStatus; \
\r
131 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
133 xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \
\r
134 uxValueForNormallyFullQueue++; \
\r
136 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
139 /* Receive a value from the normally empty queue. This is called from within
\r
141 #define timerNORMALLY_EMPTY_RX() \
\r
142 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
144 prvQueueAccessLogError( __LINE__ ); \
\r
148 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
151 /* Receive a value from the normally full queue. This is called from within
\r
153 #define timerNORMALLY_FULL_RX() \
\r
154 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
\r
156 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
160 /*-----------------------------------------------------------*/
\r
162 /* The two queues used by the test. */
\r
163 static xQueueHandle xNormallyEmptyQueue, xNormallyFullQueue;
\r
165 /* Variables used to detect a stall in one of the tasks. */
\r
166 static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
\r
168 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
\r
169 caused the error in xErrorLine. */
\r
170 static portBASE_TYPE xErrorStatus = pdPASS;
\r
171 static unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;
\r
173 /* Used for sequencing between tasks. */
\r
174 static portBASE_TYPE xWasSuspended = pdFALSE;
\r
176 /* The values that are sent to the queues. An incremented value is sent each
\r
177 time to each queue. */
\r
178 volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
\r
180 /* A handle to some of the tasks is required so they can be suspended/resumed. */
\r
181 xTaskHandle xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
\r
183 /* When a value is received in a queue the value is ticked off in the array
\r
184 the array position of the value is set to a the identifier of the task or
\r
185 interrupt that accessed the queue. This way missing or duplicate values can be
\r
187 static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
188 static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
190 /* The test tasks themselves. */
\r
191 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
\r
192 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
\r
193 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
\r
194 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
\r
195 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
\r
197 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
\r
198 ucNormallyFullReceivedValues arrays, while checking for duplicates. */
\r
199 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
\r
200 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
\r
202 /* Logs the line on which an error occurred. */
\r
203 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine );
\r
205 /*-----------------------------------------------------------*/
\r
207 void vStartInterruptQueueTasks( void )
\r
209 /* Start the test tasks. */
\r
210 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
\r
211 xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
\r
212 xTaskCreate( prvLowerPriorityNormallyEmptyTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
213 xTaskCreate( prv1stHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
\r
214 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
\r
215 xTaskCreate( prvLowerPriorityNormallyFullTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
217 /* Create the queues that are accessed by multiple tasks and multiple
\r
219 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
\r
220 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
\r
222 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
223 in use. The queue registry is provided as a means for kernel aware
\r
224 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
225 is not being used. The call to vQueueAddToRegistry() will be removed
\r
226 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
227 defined to be less than 1. */
\r
228 vQueueAddToRegistry( xNormallyFullQueue, ( signed portCHAR * ) "NormallyFull" );
\r
229 vQueueAddToRegistry( xNormallyEmptyQueue, ( signed portCHAR * ) "NormallyEmpty" );
\r
231 /*-----------------------------------------------------------*/
\r
233 static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
235 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
237 /* We don't expect to receive the same value twice, so if the value
\r
238 has already been marked as received an error has occurred. */
\r
239 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
241 prvQueueAccessLogError( __LINE__ );
\r
244 /* Log that this value has been received. */
\r
245 ucNormallyFullReceivedValues[ uxValue ] = uxSource;
\r
248 /*-----------------------------------------------------------*/
\r
250 static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
\r
252 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
254 /* We don't expect to receive the same value twice, so if the value
\r
255 has already been marked as received an error has occurred. */
\r
256 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
258 prvQueueAccessLogError( __LINE__ );
\r
261 /* Log that this value has been received. */
\r
262 ucNormallyEmptyReceivedValues[ uxValue ] = uxSource;
\r
265 /*-----------------------------------------------------------*/
\r
267 static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
\r
269 /* Latch the line number that caused the error. */
\r
270 xErrorLine = uxLine;
\r
271 xErrorStatus = pdFAIL;
\r
273 /*-----------------------------------------------------------*/
\r
275 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
277 unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2;
\r
279 /* The timer should not be started until after the scheduler has started.
\r
280 More than one task is running this code so we check the parameter value
\r
281 to determine which task should start the timer. */
\r
282 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
284 vInitialiseTimerForIntQueueTest();
\r
289 /* Block waiting to receive a value from the normally empty queue.
\r
290 Interrupts will write to the queue so we should receive a value. */
\r
291 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
293 prvQueueAccessLogError( __LINE__ );
\r
297 /* Note which value was received so we can check all expected
\r
298 values are received and no values are duplicated. */
\r
299 prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );
\r
302 /* Ensure the other task running this code gets a chance to execute. */
\r
305 if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
307 /* Have we received all the expected values? */
\r
308 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
310 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
315 /* Loop through the array, checking that both tasks have
\r
316 placed values into the array, and that no values are missing. */
\r
317 for( ux = 0; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
319 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
321 /* A value is missing. */
\r
322 prvQueueAccessLogError( __LINE__ );
\r
326 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
328 /* Value was placed into the array by task 1. */
\r
331 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
333 /* Value was placed into the array by task 2. */
\r
339 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
341 /* Only task 2 seemed to log any values. */
\r
342 prvQueueAccessLogError( __LINE__ );
\r
345 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
347 /* Only task 1 seemed to log any values. */
\r
348 prvQueueAccessLogError( __LINE__ );
\r
351 /* Clear the array again, ready to start a new cycle. */
\r
352 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
354 uxHighPriorityLoops1++;
\r
355 uxValueForNormallyEmptyQueue = 0;
\r
357 /* Suspend ourselves, allowing the lower priority task to
\r
358 actually receive something from the queue. Until now it
\r
359 will have been prevented from doing so by the higher
\r
360 priority tasks. The lower priority task will resume us
\r
361 if it receives something. We will then resume the other
\r
362 higher priority task. */
\r
363 vTaskSuspend( NULL );
\r
364 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
369 /*-----------------------------------------------------------*/
\r
371 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
373 unsigned portBASE_TYPE uxValue, uxRxed;
\r
374 portBASE_TYPE xQueueStatus;
\r
376 /* The parameters are not being used so avoid compiler warnings. */
\r
377 ( void ) pvParameters;
\r
381 if( ( xQueueStatus = xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) ) != errQUEUE_EMPTY )
\r
383 /* We should only obtain a value when the high priority task is
\r
385 if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE )
\r
387 prvQueueAccessLogError( __LINE__ );
\r
390 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
392 /* Wake the higher priority task again. */
\r
393 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
394 uxLowPriorityLoops1++;
\r
398 /* Raise our priority while we send so we can preempt the higher
\r
399 priority task, and ensure we get the Tx value into the queue. */
\r
400 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
402 portENTER_CRITICAL();
\r
404 uxValue = uxValueForNormallyEmptyQueue;
\r
405 uxValueForNormallyEmptyQueue++;
\r
407 portEXIT_CRITICAL();
\r
409 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
411 prvQueueAccessLogError( __LINE__ );
\r
414 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
418 /*-----------------------------------------------------------*/
\r
420 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
422 unsigned portBASE_TYPE uxValueToTx, ux;
\r
423 portBASE_TYPE xQueueStatus;
\r
425 /* The parameters are not being used so avoid compiler warnings. */
\r
426 ( void ) pvParameters;
\r
428 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
429 high priority tasks. */
\r
430 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
432 portENTER_CRITICAL();
\r
434 uxValueToTx = uxValueForNormallyFullQueue;
\r
435 uxValueForNormallyFullQueue++;
\r
437 portEXIT_CRITICAL();
\r
439 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
444 portENTER_CRITICAL();
\r
446 uxValueToTx = uxValueForNormallyFullQueue;
\r
447 uxValueForNormallyFullQueue++;
\r
449 portEXIT_CRITICAL();
\r
451 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )
\r
453 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
454 expect it to ever time out. */
\r
455 prvQueueAccessLogError( __LINE__ );
\r
458 /* Allow the other task running this code to run. */
\r
461 /* Have all the expected values been sent to the queue? */
\r
462 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
464 /* Make sure the other high priority task completes its send of
\r
465 any values below intqNUM_VALUE_TO_LOG. */
\r
466 vTaskDelay( intqSHORT_DELAY );
\r
468 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
470 if( xWasSuspended == pdTRUE )
\r
472 /* We would have expected the other high priority task to have
\r
473 set this back to false by now. */
\r
474 prvQueueAccessLogError( __LINE__ );
\r
477 /* Set the suspended flag so an error is not logged if the other
\r
478 task recognises a time out when it is unsuspended. */
\r
479 xWasSuspended = pdTRUE;
\r
481 for( ux = 0; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
483 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
485 /* A value was missing. */
\r
486 prvQueueAccessLogError( __LINE__ );
\r
490 /* Reset the array ready for the next cycle. */
\r
491 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
493 uxHighPriorityLoops2++;
\r
494 uxValueForNormallyFullQueue = 0;
\r
496 /* Suspend ourselves, allowing the lower priority task to
\r
497 actually receive something from the queue. Until now it
\r
498 will have been prevented from doing so by the higher
\r
499 priority tasks. The lower priority task will resume us
\r
500 if it receives something. We will then resume the other
\r
501 higher priority task. */
\r
502 vTaskSuspend( NULL );
\r
503 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
507 /*-----------------------------------------------------------*/
\r
509 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
511 unsigned portBASE_TYPE uxValueToTx, ux;
\r
512 portBASE_TYPE xQueueStatus;
\r
514 /* The parameters are not being used so avoid compiler warnings. */
\r
515 ( void ) pvParameters;
\r
517 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
518 high priority tasks. */
\r
519 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
521 portENTER_CRITICAL();
\r
523 uxValueToTx = uxValueForNormallyFullQueue;
\r
524 uxValueForNormallyFullQueue++;
\r
526 portEXIT_CRITICAL();
\r
528 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
533 portENTER_CRITICAL();
\r
535 uxValueToTx = uxValueForNormallyFullQueue;
\r
536 uxValueForNormallyFullQueue++;
\r
538 portEXIT_CRITICAL();
\r
540 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS )
\r
542 if( xWasSuspended != pdTRUE )
\r
544 /* It is ok to time out if the task has been suspended. */
\r
545 prvQueueAccessLogError( __LINE__ );
\r
549 xWasSuspended = pdFALSE;
\r
554 /*-----------------------------------------------------------*/
\r
556 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
558 unsigned portBASE_TYPE uxValue, uxTxed = 9999;
\r
559 portBASE_TYPE xQueueStatus;
\r
561 /* The parameters are not being used so avoid compiler warnings. */
\r
562 ( void ) pvParameters;
\r
566 if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) ) != errQUEUE_FULL )
\r
568 /* We would only expect to succeed when the higher priority task
\r
570 if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE )
\r
572 prvQueueAccessLogError( __LINE__ );
\r
575 vTaskResume( xHighPriorityNormallyFullTask1 );
\r
576 uxLowPriorityLoops2++;
\r
580 /* Raise our priority while we receive so we can preempt the higher
\r
581 priority task, and ensure we get the value from the queue. */
\r
582 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
584 if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
586 prvQueueAccessLogError( __LINE__ );
\r
590 prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
\r
593 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
597 /*-----------------------------------------------------------*/
\r
599 portBASE_TYPE xFirstTimerHandler( void )
\r
601 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue;
\r
602 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
604 /* Called from a timer interrupt. Perform various read and write
\r
605 accesses on the queues. */
\r
609 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
611 timerNORMALLY_EMPTY_TX();
\r
612 timerNORMALLY_EMPTY_TX();
\r
613 timerNORMALLY_EMPTY_TX();
\r
617 timerNORMALLY_FULL_RX();
\r
618 timerNORMALLY_FULL_RX();
\r
619 timerNORMALLY_FULL_RX();
\r
622 return xHigherPriorityTaskWoken;
\r
624 /*-----------------------------------------------------------*/
\r
626 portBASE_TYPE xSecondTimerHandler( void )
\r
628 unsigned portBASE_TYPE uxRxedValue;
\r
629 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
630 static unsigned portBASE_TYPE uxNextOperation = 0;
\r
632 /* Called from a timer interrupt. Perform various read and write
\r
633 accesses on the queues. */
\r
637 if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
\r
639 timerNORMALLY_EMPTY_TX();
\r
640 timerNORMALLY_EMPTY_TX();
\r
642 timerNORMALLY_EMPTY_RX();
\r
643 timerNORMALLY_EMPTY_RX();
\r
647 timerNORMALLY_FULL_RX();
\r
648 timerNORMALLY_FULL_TX();
\r
649 timerNORMALLY_FULL_TX();
\r
650 timerNORMALLY_FULL_TX();
\r
651 timerNORMALLY_FULL_TX();
\r
654 return xHigherPriorityTaskWoken;
\r
656 /*-----------------------------------------------------------*/
\r
659 portBASE_TYPE xAreIntQueueTasksStillRunning( void )
\r
661 static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
663 /* xErrorStatus can be set outside of this function. This function just
\r
664 checks that all the tasks are still cycling. */
\r
666 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
668 /* The high priority 1 task has stalled. */
\r
669 prvQueueAccessLogError( __LINE__ );
\r
672 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
674 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
676 /* The high priority 2 task has stalled. */
\r
677 prvQueueAccessLogError( __LINE__ );
\r
680 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
682 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
684 /* The low priority 1 task has stalled. */
\r
685 prvQueueAccessLogError( __LINE__ );
\r
688 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
690 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
692 /* The low priority 2 task has stalled. */
\r
693 prvQueueAccessLogError( __LINE__ );
\r
696 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
698 return xErrorStatus;
\r