]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/GenQTest.c
b306984d6dbca0f83583dce37cdb8a4a49d6dc0a
[freertos] / FreeRTOS / Demo / Common / Minimal / GenQTest.c
1 /*\r
2     FreeRTOS V7.4.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
3 \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
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
10      *    Complete, revised, and edited pdf reference manuals are also       *\r
11      *    available.                                                         *\r
12      *                                                                       *\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
19      *                                                                       *\r
20      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
21      *                                                                       *\r
22      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
23      *                                                                       *\r
24     ***************************************************************************\r
25 \r
26 \r
27     This file is part of the FreeRTOS distribution.\r
28 \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
32 \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
36     kernel.\r
37 \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 itcan 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
46 \r
47     1 tab == 4 spaces!\r
48 \r
49     ***************************************************************************\r
50      *                                                                       *\r
51      *    Having a problem?  Start by reading the FAQ "My application does   *\r
52      *    not run, what could be wrong?"                                     *\r
53      *                                                                       *\r
54      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
55      *                                                                       *\r
56     ***************************************************************************\r
57 \r
58 \r
59     http://www.FreeRTOS.org - Documentation, books, training, latest versions, \r
60     license and Real Time Engineers Ltd. contact details.\r
61 \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
65 \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
69     \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
73 */\r
74 \r
75 \r
76 /* \r
77  * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 - \r
78  * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and \r
79  * mutex behaviour. \r
80  *\r
81  * See the comments above the prvSendFrontAndBackTest() and \r
82  * prvLowPriorityMutexTask() prototypes below for more information.\r
83  */\r
84 \r
85 \r
86 #include <stdlib.h>\r
87 \r
88 /* Scheduler include files. */\r
89 #include "FreeRTOS.h"\r
90 #include "task.h"\r
91 #include "queue.h"\r
92 #include "semphr.h"\r
93 \r
94 /* Demo program include files. */\r
95 #include "GenQTest.h"\r
96 \r
97 #define genqQUEUE_LENGTH                ( 5 )\r
98 #define genqNO_BLOCK                    ( 0 )\r
99 \r
100 #define genqMUTEX_LOW_PRIORITY          ( tskIDLE_PRIORITY )\r
101 #define genqMUTEX_TEST_PRIORITY         ( tskIDLE_PRIORITY + 1 )\r
102 #define genqMUTEX_MEDIUM_PRIORITY       ( tskIDLE_PRIORITY + 2 )\r
103 #define genqMUTEX_HIGH_PRIORITY         ( tskIDLE_PRIORITY + 3 )\r
104 \r
105 /*-----------------------------------------------------------*/\r
106 \r
107 /*\r
108  * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack()\r
109  * macros by using both to fill a queue, then reading from the queue to\r
110  * check the resultant queue order is as expected.  Queue data is also\r
111  * peeked.\r
112  */\r
113 static void prvSendFrontAndBackTest( void *pvParameters );\r
114 \r
115 /*\r
116  * The following three tasks are used to demonstrate the mutex behaviour.\r
117  * Each task is given a different priority to demonstrate the priority\r
118  * inheritance mechanism.\r
119  *\r
120  * The low priority task obtains a mutex.  After this a high priority task\r
121  * attempts to obtain the same mutex, causing its priority to be inherited\r
122  * by the low priority task.  The task with the inherited high priority then\r
123  * resumes a medium priority task to ensure it is not blocked by the medium\r
124  * priority task while it holds the inherited high priority.  Once the mutex\r
125  * is returned the task with the inherited priority returns to its original\r
126  * low priority, and is therefore immediately preempted by first the high\r
127  * priority task and then the medium prioroity task before it can continue.\r
128  */\r
129 static void prvLowPriorityMutexTask( void *pvParameters );\r
130 static void prvMediumPriorityMutexTask( void *pvParameters );\r
131 static void prvHighPriorityMutexTask( void *pvParameters );\r
132 \r
133 /*-----------------------------------------------------------*/\r
134 \r
135 /* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
136 detected in any of the tasks. */\r
137 static portBASE_TYPE xErrorDetected = pdFALSE;\r
138 \r
139 /* Counters that are incremented on each cycle of a test.  This is used to\r
140 detect a stalled task - a test that is no longer running. */\r
141 static volatile unsigned portLONG ulLoopCounter = 0;\r
142 static volatile unsigned portLONG ulLoopCounter2 = 0;\r
143 \r
144 /* The variable that is guarded by the mutex in the mutex demo tasks. */\r
145 static volatile unsigned portLONG ulGuardedVariable = 0;\r
146 \r
147 /* Handles used in the mutext test to suspend and resume the high and medium\r
148 priority mutex test tasks. */\r
149 static xTaskHandle xHighPriorityMutexTask, xMediumPriorityMutexTask;\r
150 \r
151 /*-----------------------------------------------------------*/\r
152 \r
153 void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority )\r
154 {\r
155 xQueueHandle xQueue;\r
156 xSemaphoreHandle xMutex;\r
157 \r
158         /* Create the queue that we are going to use for the\r
159         prvSendFrontAndBackTest demo. */\r
160         xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( unsigned portLONG ) );\r
161 \r
162         /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
163         in use.  The queue registry is provided as a means for kernel aware \r
164         debuggers to locate queues and has no purpose if a kernel aware debugger\r
165         is not being used.  The call to vQueueAddToRegistry() will be removed\r
166         by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
167         defined to be less than 1. */\r
168         vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "Gen_Queue_Test" );\r
169 \r
170         /* Create the demo task and pass it the queue just created.  We are\r
171         passing the queue handle by value so it does not matter that it is\r
172         declared on the stack here. */\r
173         xTaskCreate( prvSendFrontAndBackTest, ( signed portCHAR * )"GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );\r
174 \r
175         /* Create the mutex used by the prvMutexTest task. */\r
176         xMutex = xSemaphoreCreateMutex();\r
177 \r
178         /* vQueueAddToRegistry() adds the mutex to the registry, if one is\r
179         in use.  The registry is provided as a means for kernel aware \r
180         debuggers to locate mutexes and has no purpose if a kernel aware debugger\r
181         is not being used.  The call to vQueueAddToRegistry() will be removed\r
182         by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
183         defined to be less than 1. */\r
184         vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Gen_Queue_Mutex" );\r
185 \r
186         /* Create the mutex demo tasks and pass it the mutex just created.  We are\r
187         passing the mutex handle by value so it does not matter that it is declared\r
188         on the stack here. */\r
189         xTaskCreate( prvLowPriorityMutexTask, ( signed portCHAR * )"MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
190         xTaskCreate( prvMediumPriorityMutexTask, ( signed portCHAR * )"MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
191         xTaskCreate( prvHighPriorityMutexTask, ( signed portCHAR * )"MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
192 }\r
193 /*-----------------------------------------------------------*/\r
194 \r
195 static void prvSendFrontAndBackTest( void *pvParameters )\r
196 {\r
197 unsigned portLONG ulData, ulData2;\r
198 xQueueHandle xQueue;\r
199 \r
200         #ifdef USE_STDIO\r
201         void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
202         \r
203                 const portCHAR * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n";\r
204 \r
205                 /* Queue a message for printing to say the task has started. */\r
206                 vPrintDisplayMessage( &pcTaskStartMsg );\r
207         #endif\r
208 \r
209         xQueue = ( xQueueHandle ) pvParameters;\r
210 \r
211         for( ;; )\r
212         {\r
213                 /* The queue is empty, so sending an item to the back of the queue\r
214                 should have the same efect as sending it to the front of the queue.\r
215 \r
216                 First send to the front and check everything is as expected. */\r
217                 xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
218 \r
219                 if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
220                 {\r
221                         xErrorDetected = pdTRUE;\r
222                 }\r
223 \r
224                 if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
225                 {\r
226                         xErrorDetected = pdTRUE;\r
227                 }\r
228 \r
229                 /* The data we sent to the queue should equal the data we just received\r
230                 from the queue. */\r
231                 if( ulLoopCounter != ulData )\r
232                 {\r
233                         xErrorDetected = pdTRUE;\r
234                 }\r
235 \r
236                 /* Then do the same, sending the data to the back, checking everything\r
237                 is as expected. */\r
238                 if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
239                 {\r
240                         xErrorDetected = pdTRUE;\r
241                 }\r
242 \r
243                 xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
244 \r
245                 if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
246                 {\r
247                         xErrorDetected = pdTRUE;\r
248                 }\r
249 \r
250                 if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
251                 {\r
252                         xErrorDetected = pdTRUE;\r
253                 }\r
254 \r
255                 if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
256                 {\r
257                         xErrorDetected = pdTRUE;\r
258                 }\r
259 \r
260                 /* The data we sent to the queue should equal the data we just received\r
261                 from the queue. */\r
262                 if( ulLoopCounter != ulData )\r
263                 {\r
264                         xErrorDetected = pdTRUE;\r
265                 }\r
266 \r
267                 #if configUSE_PREEMPTION == 0\r
268                         taskYIELD();\r
269                 #endif\r
270 \r
271 \r
272 \r
273                 /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */\r
274                 for( ulData = 2; ulData < 5; ulData++ )\r
275                 {\r
276                         xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
277                 }\r
278 \r
279                 /* Now the order in the queue should be 2, 3, 4, with 2 being the first\r
280                 thing to be read out.  Now add 1 then 0 to the front of the queue. */\r
281                 if( uxQueueMessagesWaiting( xQueue ) != 3 )\r
282                 {\r
283                         xErrorDetected = pdTRUE;\r
284                 }\r
285                 ulData = 1;\r
286                 xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
287                 ulData = 0;\r
288                 xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
289 \r
290                 /* Now the queue should be full, and when we read the data out we\r
291                 should receive 0, 1, 2, 3, 4. */\r
292                 if( uxQueueMessagesWaiting( xQueue ) != 5 )\r
293                 {\r
294                         xErrorDetected = pdTRUE;\r
295                 }\r
296 \r
297                 if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
298                 {\r
299                         xErrorDetected = pdTRUE;\r
300                 }\r
301 \r
302                 if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
303                 {\r
304                         xErrorDetected = pdTRUE;\r
305                 }\r
306 \r
307                 #if configUSE_PREEMPTION == 0\r
308                         taskYIELD();\r
309                 #endif\r
310 \r
311                 /* Check the data we read out is in the expected order. */\r
312                 for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )\r
313                 {\r
314                         /* Try peeking the data first. */\r
315                         if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
316                         {\r
317                                 xErrorDetected = pdTRUE;\r
318                         }\r
319 \r
320                         if( ulData != ulData2 )\r
321                         {\r
322                                 xErrorDetected = pdTRUE;\r
323                         }\r
324                         \r
325 \r
326                         /* Now try receiving the data for real.  The value should be the\r
327                         same.  Clobber the value first so we know we really received it. */\r
328                         ulData2 = ~ulData2;\r
329                         if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
330                         {\r
331                                 xErrorDetected = pdTRUE;\r
332                         }\r
333 \r
334                         if( ulData != ulData2 )\r
335                         {\r
336                                 xErrorDetected = pdTRUE;\r
337                         }\r
338                 }\r
339 \r
340                 /* The queue should now be empty again. */\r
341                 if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
342                 {\r
343                         xErrorDetected = pdTRUE;\r
344                 }\r
345 \r
346                 #if configUSE_PREEMPTION == 0\r
347                         taskYIELD();\r
348                 #endif\r
349 \r
350 \r
351                 /* Our queue is empty once more, add 10, 11 to the back. */\r
352                 ulData = 10;\r
353                 if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
354                 {\r
355                         xErrorDetected = pdTRUE;\r
356                 }\r
357                 ulData = 11;\r
358                 if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
359                 {\r
360                         xErrorDetected = pdTRUE;\r
361                 }\r
362 \r
363                 if( uxQueueMessagesWaiting( xQueue ) != 2 )\r
364                 {\r
365                         xErrorDetected = pdTRUE;\r
366                 }\r
367 \r
368                 /* Now we should have 10, 11 in the queue.  Add 7, 8, 9 to the\r
369                 front. */\r
370                 for( ulData = 9; ulData >= 7; ulData-- )\r
371                 {\r
372                         if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
373                         {\r
374                                 xErrorDetected = pdTRUE;\r
375                         }\r
376                 }\r
377 \r
378                 /* Now check that the queue is full, and that receiving data provides\r
379                 the expected sequence of 7, 8, 9, 10, 11. */\r
380                 if( uxQueueMessagesWaiting( xQueue ) != 5 )\r
381                 {\r
382                         xErrorDetected = pdTRUE;\r
383                 }\r
384 \r
385                 if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
386                 {\r
387                         xErrorDetected = pdTRUE;\r
388                 }\r
389 \r
390                 if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
391                 {\r
392                         xErrorDetected = pdTRUE;\r
393                 }\r
394 \r
395                 #if configUSE_PREEMPTION == 0\r
396                         taskYIELD();\r
397                 #endif\r
398 \r
399                 /* Check the data we read out is in the expected order. */\r
400                 for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )\r
401                 {\r
402                         if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
403                         {\r
404                                 xErrorDetected = pdTRUE;\r
405                         }\r
406 \r
407                         if( ulData != ulData2 )\r
408                         {\r
409                                 xErrorDetected = pdTRUE;\r
410                         }\r
411                 }\r
412 \r
413                 if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
414                 {\r
415                         xErrorDetected = pdTRUE;\r
416                 }\r
417 \r
418                 ulLoopCounter++;\r
419         }\r
420 }\r
421 /*-----------------------------------------------------------*/\r
422 \r
423 static void prvLowPriorityMutexTask( void *pvParameters )\r
424 {\r
425 xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;\r
426 \r
427         #ifdef USE_STDIO\r
428         void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
429         \r
430                 const portCHAR * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";\r
431 \r
432                 /* Queue a message for printing to say the task has started. */\r
433                 vPrintDisplayMessage( &pcTaskStartMsg );\r
434         #endif\r
435 \r
436         for( ;; )\r
437         {\r
438                 /* Take the mutex.  It should be available now. */\r
439                 if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
440                 {\r
441                         xErrorDetected = pdTRUE;\r
442                 }\r
443 \r
444                 /* Set our guarded variable to a known start value. */\r
445                 ulGuardedVariable = 0;\r
446 \r
447                 /* Our priority should be as per that assigned when the task was\r
448                 created. */\r
449                 if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
450                 {\r
451                         xErrorDetected = pdTRUE;\r
452                 }\r
453 \r
454                 /* Now unsuspend the high priority task.  This will attempt to take the\r
455                 mutex, and block when it finds it cannot obtain it. */\r
456                 vTaskResume( xHighPriorityMutexTask );\r
457 \r
458                 /* We should now have inherited the prioritoy of the high priority task,\r
459                 as by now it will have attempted to get the mutex. */\r
460                 if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
461                 {\r
462                         xErrorDetected = pdTRUE;\r
463                 }\r
464 \r
465                 /* We can attempt to set our priority to the test priority - between the\r
466                 idle priority and the medium/high test priorities, but our actual\r
467                 prioroity should remain at the high priority. */\r
468                 vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );\r
469                 if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
470                 {\r
471                         xErrorDetected = pdTRUE;\r
472                 }\r
473 \r
474                 /* Now unsuspend the medium priority task.  This should not run as our\r
475                 inherited priority is above that of the medium priority task. */\r
476                 vTaskResume( xMediumPriorityMutexTask );\r
477 \r
478                 /* If the did run then it will have incremented our guarded variable. */\r
479                 if( ulGuardedVariable != 0 )\r
480                 {\r
481                         xErrorDetected = pdTRUE;\r
482                 }\r
483 \r
484                 /* When we give back the semaphore our priority should be disinherited\r
485                 back to the priority to which we attempted to set ourselves.  This means\r
486                 that when the high priority task next blocks, the medium priority task\r
487                 should execute and increment the guarded variable.   When we next run\r
488                 both the high and medium priority tasks will have been suspended again. */\r
489                 if( xSemaphoreGive( xMutex ) != pdPASS )\r
490                 {\r
491                         xErrorDetected = pdTRUE;\r
492                 }\r
493 \r
494                 /* Check that the guarded variable did indeed increment... */\r
495                 if( ulGuardedVariable != 1 )\r
496                 {\r
497                         xErrorDetected = pdTRUE;\r
498                 }\r
499 \r
500                 /* ... and that our priority has been disinherited to\r
501                 genqMUTEX_TEST_PRIORITY. */\r
502                 if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )\r
503                 {\r
504                         xErrorDetected = pdTRUE;\r
505                 }\r
506 \r
507                 /* Set our priority back to our original priority ready for the next\r
508                 loop around this test. */\r
509                 vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );\r
510 \r
511                 /* Just to show we are still running. */\r
512                 ulLoopCounter2++;\r
513 \r
514                 #if configUSE_PREEMPTION == 0\r
515                         taskYIELD();\r
516                 #endif          \r
517         }\r
518 }\r
519 /*-----------------------------------------------------------*/\r
520 \r
521 static void prvMediumPriorityMutexTask( void *pvParameters )\r
522 {\r
523         ( void ) pvParameters;\r
524 \r
525         for( ;; )\r
526         {\r
527                 /* The medium priority task starts by suspending itself.  The low\r
528                 priority task will unsuspend this task when required. */\r
529                 vTaskSuspend( NULL );\r
530 \r
531                 /* When this task unsuspends all it does is increment the guarded\r
532                 variable, this is so the low priority task knows that it has\r
533                 executed. */\r
534                 ulGuardedVariable++;\r
535         }\r
536 }\r
537 /*-----------------------------------------------------------*/\r
538 \r
539 static void prvHighPriorityMutexTask( void *pvParameters )\r
540 {\r
541 xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;\r
542 \r
543         for( ;; )\r
544         {\r
545                 /* The high priority task starts by suspending itself.  The low\r
546                 priority task will unsuspend this task when required. */\r
547                 vTaskSuspend( NULL );\r
548 \r
549                 /* When this task unsuspends all it does is attempt to obtain\r
550                 the mutex.  It should find the mutex is not available so a\r
551                 block time is specified. */\r
552                 if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )\r
553                 {\r
554                         xErrorDetected = pdTRUE;\r
555                 }\r
556 \r
557                 /* When we eventually obtain the mutex we just give it back then\r
558                 return to suspend ready for the next test. */\r
559                 if( xSemaphoreGive( xMutex ) != pdPASS )\r
560                 {\r
561                         xErrorDetected = pdTRUE;\r
562                 }               \r
563         }\r
564 }\r
565 /*-----------------------------------------------------------*/\r
566 \r
567 /* This is called to check that all the created tasks are still running. */\r
568 portBASE_TYPE xAreGenericQueueTasksStillRunning( void )\r
569 {\r
570 static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;\r
571 \r
572         /* If the demo task is still running then we expect the loopcounters to\r
573         have incremented since this function was last called. */\r
574         if( ulLastLoopCounter == ulLoopCounter )\r
575         {\r
576                 xErrorDetected = pdTRUE;\r
577         }\r
578 \r
579         if( ulLastLoopCounter2 == ulLoopCounter2 )\r
580         {\r
581                 xErrorDetected = pdTRUE;\r
582         }\r
583 \r
584         ulLastLoopCounter = ulLoopCounter;\r
585         ulLastLoopCounter2 = ulLoopCounter2;    \r
586 \r
587         /* Errors detected in the task itself will have latched xErrorDetected\r
588         to true. */\r
589 \r
590         return ( portBASE_TYPE ) !xErrorDetected;\r
591 }\r
592 \r
593 \r