2 FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
67 * This file defines one of the more complex set of demo/test tasks. They are
\r
68 * designed to stress test the queue implementation though pseudo simultaneous
\r
69 * multiple reads and multiple writes from both tasks of varying priority and
\r
70 * interrupts. The interrupts are prioritised such to ensure that nesting
\r
71 * occurs (for those ports that support it).
\r
73 * The test ensures that, while being accessed from three tasks and two
\r
74 * interrupts, all the data sent to the queues is also received from
\r
75 * the same queue, and that no duplicate items are either sent or received.
\r
76 * The tests also ensure that a low priority task is never able to successfully
\r
77 * read from or write to a queue when a task of higher priority is attempting
\r
78 * the same operation.
\r
81 /* Standard includes. */
\r
84 /* SafeRTOS includes. */
\r
85 #include "FreeRTOS.h"
\r
89 /* Demo app includes. */
\r
90 #include "IntQueue.h"
\r
91 #include "IntQueueTimer.h"
\r
93 #if( INCLUDE_eTaskGetState != 1 )
\r
94 #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.
\r
97 /* Priorities used by test tasks. */
\r
98 #ifndef intqHIGHER_PRIORITY
\r
99 #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
101 #define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
103 /* The number of values to send/receive before checking that all values were
\r
104 processed as expected. */
\r
105 #define intqNUM_VALUES_TO_LOG ( 200 )
\r
106 #define intqSHORT_DELAY ( 140 )
\r
108 /* The value by which the value being sent to or received from a queue should
\r
109 increment past intqNUM_VALUES_TO_LOG before we check that all values have been
\r
110 sent/received correctly. This is done to ensure that all tasks and interrupts
\r
111 accessing the queue have completed their accesses with the
\r
112 intqNUM_VALUES_TO_LOG range. */
\r
113 #define intqVALUE_OVERRUN ( 50 )
\r
115 /* The delay used by the polling task. A short delay is used for code
\r
117 #define intqONE_TICK_DELAY ( 1 )
\r
119 /* Each task and interrupt is given a unique identifier. This value is used to
\r
120 identify which task sent or received each value. The identifier is also used
\r
121 to distinguish between two tasks that are running the same task function. */
\r
122 #define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
\r
123 #define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
\r
124 #define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
\r
125 #define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 )
\r
126 #define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 )
\r
127 #define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
\r
129 /* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
\r
130 from each queue by each task, otherwise an error is detected. */
\r
131 #define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
\r
133 /* Send the next value to the queue that is normally empty. This is called
\r
134 from within the interrupts. */
\r
135 #define timerNORMALLY_EMPTY_TX() \
\r
136 if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
\r
138 UBaseType_t uxSavedInterruptStatus; \
\r
139 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
141 uxValueForNormallyEmptyQueue++; \
\r
142 if( xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
144 uxValueForNormallyEmptyQueue--; \
\r
147 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
150 /* Send the next value to the queue that is normally full. This is called
\r
151 from within the interrupts. */
\r
152 #define timerNORMALLY_FULL_TX() \
\r
153 if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
\r
155 UBaseType_t uxSavedInterruptStatus; \
\r
156 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
158 uxValueForNormallyFullQueue++; \
\r
159 if( xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
161 uxValueForNormallyFullQueue--; \
\r
164 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
167 /* Receive a value from the normally empty queue. This is called from within
\r
169 #define timerNORMALLY_EMPTY_RX() \
\r
170 if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
\r
172 prvQueueAccessLogError( __LINE__ ); \
\r
176 prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
179 /* Receive a value from the normally full queue. This is called from within
\r
181 #define timerNORMALLY_FULL_RX() \
\r
182 if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
\r
184 prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
\r
188 /*-----------------------------------------------------------*/
\r
190 /* The two queues used by the test. */
\r
191 static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
\r
193 /* Variables used to detect a stall in one of the tasks. */
\r
194 static UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
\r
196 /* Any unexpected behaviour sets xErrorStatus to fail and log the line that
\r
197 caused the error in xErrorLine. */
\r
198 static BaseType_t xErrorStatus = pdPASS;
\r
199 static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
\r
201 /* Used for sequencing between tasks. */
\r
202 static BaseType_t xWasSuspended = pdFALSE;
\r
204 /* The values that are sent to the queues. An incremented value is sent each
\r
205 time to each queue. */
\r
206 volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
\r
208 /* A handle to some of the tasks is required so they can be suspended/resumed. */
\r
209 TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
\r
211 /* When a value is received in a queue the value is ticked off in the array
\r
212 the array position of the value is set to a the identifier of the task or
\r
213 interrupt that accessed the queue. This way missing or duplicate values can be
\r
215 static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
216 static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
\r
218 /* The test tasks themselves. */
\r
219 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
\r
220 static void prvLowerPriorityNormallyFullTask( void *pvParameters );
\r
221 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
\r
222 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
\r
223 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
\r
225 /* Used to mark the positions within the ucNormallyEmptyReceivedValues and
\r
226 ucNormallyFullReceivedValues arrays, while checking for duplicates. */
\r
227 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource );
\r
228 static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource );
\r
230 /* Logs the line on which an error occurred. */
\r
231 static void prvQueueAccessLogError( UBaseType_t uxLine );
\r
233 /*-----------------------------------------------------------*/
\r
235 void vStartInterruptQueueTasks( void )
\r
237 /* Start the test tasks. */
\r
238 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
\r
239 xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
\r
240 xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
241 xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
\r
242 xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
\r
243 xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
\r
245 /* Create the queues that are accessed by multiple tasks and multiple
\r
247 xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
\r
248 xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
\r
250 /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
\r
251 in use. The queue registry is provided as a means for kernel aware
\r
252 debuggers to locate queues and has no purpose if a kernel aware debugger
\r
253 is not being used. The call to vQueueAddToRegistry() will be removed
\r
254 by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
\r
255 defined to be less than 1. */
\r
256 vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" );
\r
257 vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
\r
259 /*-----------------------------------------------------------*/
\r
261 static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource )
\r
263 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
265 /* We don't expect to receive the same value twice, so if the value
\r
266 has already been marked as received an error has occurred. */
\r
267 if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
\r
269 prvQueueAccessLogError( __LINE__ );
\r
272 /* Log that this value has been received. */
\r
273 ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
\r
276 /*-----------------------------------------------------------*/
\r
278 static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource )
\r
280 if( uxValue < intqNUM_VALUES_TO_LOG )
\r
282 /* We don't expect to receive the same value twice, so if the value
\r
283 has already been marked as received an error has occurred. */
\r
284 if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
\r
286 prvQueueAccessLogError( __LINE__ );
\r
289 /* Log that this value has been received. */
\r
290 ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
\r
293 /*-----------------------------------------------------------*/
\r
295 static void prvQueueAccessLogError( UBaseType_t uxLine )
\r
297 /* Latch the line number that caused the error. */
\r
298 xErrorLine = uxLine;
\r
299 xErrorStatus = pdFAIL;
\r
301 /*-----------------------------------------------------------*/
\r
303 static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
\r
305 UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
\r
307 /* The timer should not be started until after the scheduler has started.
\r
308 More than one task is running this code so we check the parameter value
\r
309 to determine which task should start the timer. */
\r
310 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
312 vInitialiseTimerForIntQueueTest();
\r
317 /* Block waiting to receive a value from the normally empty queue.
\r
318 Interrupts will write to the queue so we should receive a value. */
\r
319 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
\r
321 prvQueueAccessLogError( __LINE__ );
\r
325 /* Note which value was received so we can check all expected
\r
326 values are received and no values are duplicated. */
\r
327 prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
\r
330 /* Ensure the other task running this code gets a chance to execute. */
\r
333 if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
\r
335 /* Have we received all the expected values? */
\r
336 if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
338 vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
\r
344 /* Loop through the array, checking that both tasks have
\r
345 placed values into the array, and that no values are missing.
\r
346 Start at 1 as we expect position 0 to be unused. */
\r
347 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
349 if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
\r
351 /* A value is missing. */
\r
352 prvQueueAccessLogError( __LINE__ );
\r
356 if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
\r
358 /* Value was placed into the array by task 1. */
\r
361 else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
\r
363 /* Value was placed into the array by task 2. */
\r
366 else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
373 if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
375 /* Only task 2 seemed to log any values. */
\r
377 if( uxErrorCount1 > 2 )
\r
379 prvQueueAccessLogError( __LINE__ );
\r
387 if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
\r
389 /* Only task 1 seemed to log any values. */
\r
391 if( uxErrorCount2 > 2 )
\r
393 prvQueueAccessLogError( __LINE__ );
\r
401 if( uxInterrupts == 0 )
\r
403 prvQueueAccessLogError( __LINE__ );
\r
406 /* Clear the array again, ready to start a new cycle. */
\r
407 memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
\r
409 uxHighPriorityLoops1++;
\r
410 uxValueForNormallyEmptyQueue = 0;
\r
412 /* Suspend ourselves, allowing the lower priority task to
\r
413 actually receive something from the queue. Until now it
\r
414 will have been prevented from doing so by the higher
\r
415 priority tasks. The lower priority task will resume us
\r
416 if it receives something. We will then resume the other
\r
417 higher priority task. */
\r
418 vTaskSuspend( NULL );
\r
419 vTaskResume( xHighPriorityNormallyEmptyTask2 );
\r
424 /*-----------------------------------------------------------*/
\r
426 static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
\r
428 UBaseType_t uxValue, uxRxed;
\r
430 /* The parameters are not being used so avoid compiler warnings. */
\r
431 ( void ) pvParameters;
\r
435 if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
\r
437 /* A value should only be obtained when the high priority task is
\r
439 if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
\r
441 prvQueueAccessLogError( __LINE__ );
\r
444 prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
\r
446 /* Wake the higher priority task again. */
\r
447 vTaskResume( xHighPriorityNormallyEmptyTask1 );
\r
448 uxLowPriorityLoops1++;
\r
452 /* Raise our priority while we send so we can preempt the higher
\r
453 priority task, and ensure we get the Tx value into the queue. */
\r
454 vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
\r
456 portENTER_CRITICAL();
\r
458 uxValueForNormallyEmptyQueue++;
\r
459 uxValue = uxValueForNormallyEmptyQueue;
\r
461 portEXIT_CRITICAL();
\r
463 if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
\r
465 prvQueueAccessLogError( __LINE__ );
\r
468 vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
\r
472 /*-----------------------------------------------------------*/
\r
474 static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
\r
476 UBaseType_t uxValueToTx, ux, uxInterrupts;
\r
478 /* The parameters are not being used so avoid compiler warnings. */
\r
479 ( void ) pvParameters;
\r
481 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
482 high priority tasks. */
\r
483 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
485 portENTER_CRITICAL();
\r
487 uxValueForNormallyFullQueue++;
\r
488 uxValueToTx = uxValueForNormallyFullQueue;
\r
490 portEXIT_CRITICAL();
\r
492 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
497 portENTER_CRITICAL();
\r
499 uxValueForNormallyFullQueue++;
\r
500 uxValueToTx = uxValueForNormallyFullQueue;
\r
502 portEXIT_CRITICAL();
\r
504 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
506 /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
\r
507 expect it to ever time out. */
\r
508 prvQueueAccessLogError( __LINE__ );
\r
511 /* Allow the other task running this code to run. */
\r
514 /* Have all the expected values been sent to the queue? */
\r
515 if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
\r
517 /* Make sure the other high priority task completes its send of
\r
518 any values below intqNUM_VALUE_TO_LOG. */
\r
519 vTaskDelay( intqSHORT_DELAY );
\r
521 vTaskSuspend( xHighPriorityNormallyFullTask2 );
\r
523 if( xWasSuspended == pdTRUE )
\r
525 /* We would have expected the other high priority task to have
\r
526 set this back to false by now. */
\r
527 prvQueueAccessLogError( __LINE__ );
\r
530 /* Set the suspended flag so an error is not logged if the other
\r
531 task recognises a time out when it is unsuspended. */
\r
532 xWasSuspended = pdTRUE;
\r
534 /* Check interrupts are also sending. */
\r
537 /* Start at 1 as we expect position 0 to be unused. */
\r
538 for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
\r
540 if( ucNormallyFullReceivedValues[ ux ] == 0 )
\r
542 /* A value was missing. */
\r
543 prvQueueAccessLogError( __LINE__ );
\r
545 else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
\r
551 if( uxInterrupts == 0 )
\r
553 /* No writes from interrupts were found. Are interrupts
\r
554 actually running? */
\r
555 prvQueueAccessLogError( __LINE__ );
\r
558 /* Reset the array ready for the next cycle. */
\r
559 memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
\r
561 uxHighPriorityLoops2++;
\r
562 uxValueForNormallyFullQueue = 0;
\r
564 /* Suspend ourselves, allowing the lower priority task to
\r
565 actually receive something from the queue. Until now it
\r
566 will have been prevented from doing so by the higher
\r
567 priority tasks. The lower priority task will resume us
\r
568 if it receives something. We will then resume the other
\r
569 higher priority task. */
\r
570 vTaskSuspend( NULL );
\r
571 vTaskResume( xHighPriorityNormallyFullTask2 );
\r
575 /*-----------------------------------------------------------*/
\r
577 static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
\r
579 UBaseType_t uxValueToTx, ux;
\r
581 /* The parameters are not being used so avoid compiler warnings. */
\r
582 ( void ) pvParameters;
\r
584 /* Make sure the queue starts full or near full. >> 1 as there are two
\r
585 high priority tasks. */
\r
586 for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
\r
588 portENTER_CRITICAL();
\r
590 uxValueForNormallyFullQueue++;
\r
591 uxValueToTx = uxValueForNormallyFullQueue;
\r
593 portEXIT_CRITICAL();
\r
595 xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
\r
600 portENTER_CRITICAL();
\r
602 uxValueForNormallyFullQueue++;
\r
603 uxValueToTx = uxValueForNormallyFullQueue;
\r
605 portEXIT_CRITICAL();
\r
607 if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
\r
609 if( xWasSuspended != pdTRUE )
\r
611 /* It is ok to time out if the task has been suspended. */
\r
612 prvQueueAccessLogError( __LINE__ );
\r
616 xWasSuspended = pdFALSE;
\r
621 /*-----------------------------------------------------------*/
\r
623 static void prvLowerPriorityNormallyFullTask( void *pvParameters )
\r
625 UBaseType_t uxValue, uxTxed = 9999;
\r
627 /* The parameters are not being used so avoid compiler warnings. */
\r
628 ( void ) pvParameters;
\r
632 if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
\r
634 /* Should only succeed when the higher priority task is suspended */
\r
635 if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended )
\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 BaseType_t xFirstTimerHandler( void )
\r
666 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
667 UBaseType_t uxRxedValue;
\r
668 static UBaseType_t uxNextOperation = 0;
\r
670 /* Called from a timer interrupt. Perform various read and write
\r
671 accesses on the queues. */
\r
675 if( uxNextOperation & ( UBaseType_t ) 0x01 )
\r
677 timerNORMALLY_EMPTY_TX();
\r
678 timerNORMALLY_EMPTY_TX();
\r
679 timerNORMALLY_EMPTY_TX();
\r
683 timerNORMALLY_FULL_RX();
\r
684 timerNORMALLY_FULL_RX();
\r
685 timerNORMALLY_FULL_RX();
\r
688 return xHigherPriorityTaskWoken;
\r
690 /*-----------------------------------------------------------*/
\r
692 BaseType_t xSecondTimerHandler( void )
\r
694 UBaseType_t uxRxedValue;
\r
695 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
696 static UBaseType_t uxNextOperation = 0;
\r
698 /* Called from a timer interrupt. Perform various read and write
\r
699 accesses on the queues. */
\r
703 if( uxNextOperation & ( UBaseType_t ) 0x01 )
\r
705 timerNORMALLY_EMPTY_TX();
\r
706 timerNORMALLY_EMPTY_TX();
\r
708 timerNORMALLY_EMPTY_RX();
\r
709 timerNORMALLY_EMPTY_RX();
\r
713 timerNORMALLY_FULL_RX();
\r
714 timerNORMALLY_FULL_TX();
\r
715 timerNORMALLY_FULL_TX();
\r
716 timerNORMALLY_FULL_TX();
\r
717 timerNORMALLY_FULL_TX();
\r
720 return xHigherPriorityTaskWoken;
\r
722 /*-----------------------------------------------------------*/
\r
725 BaseType_t xAreIntQueueTasksStillRunning( void )
\r
727 static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
\r
729 /* xErrorStatus can be set outside of this function. This function just
\r
730 checks that all the tasks are still cycling. */
\r
732 if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
\r
734 /* The high priority 1 task has stalled. */
\r
735 prvQueueAccessLogError( __LINE__ );
\r
738 uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
\r
740 if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
\r
742 /* The high priority 2 task has stalled. */
\r
743 prvQueueAccessLogError( __LINE__ );
\r
746 uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
\r
748 if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
\r
750 /* The low priority 1 task has stalled. */
\r
751 prvQueueAccessLogError( __LINE__ );
\r
754 uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
\r
756 if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
\r
758 /* The low priority 2 task has stalled. */
\r
759 prvQueueAccessLogError( __LINE__ );
\r
762 uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
\r
764 return xErrorStatus;
\r