]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/AltBlock.c
dcce5b38e66c22761c40d3494aad9ad98e3dde0d
[freertos] / FreeRTOS / Demo / Common / Minimal / AltBlock.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  * This is a version of BlockTim.c that uses the light weight API.\r
77  *\r
78  * This file contains some test scenarios that ensure tasks do not exit queue\r
79  * send or receive functions prematurely.  A description of the tests is\r
80  * included within the code.\r
81  */\r
82 \r
83 /* Kernel includes. */\r
84 #include "FreeRTOS.h"\r
85 #include "task.h"\r
86 #include "queue.h"\r
87 \r
88 /* Demo includes. */\r
89 #include "AltBlock.h"\r
90 \r
91 /* Task priorities. */\r
92 #define bktPRIMARY_PRIORITY                     ( 3 )\r
93 #define bktSECONDARY_PRIORITY           ( 2 )\r
94 \r
95 /* Task behaviour. */\r
96 #define bktQUEUE_LENGTH                         ( 5 )\r
97 #define bktSHORT_WAIT                           ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )\r
98 #define bktPRIMARY_BLOCK_TIME           ( 10 )\r
99 #define bktALLOWABLE_MARGIN                     ( 12 )\r
100 #define bktTIME_TO_BLOCK                        ( 175 )\r
101 #define bktDONT_BLOCK                           ( ( portTickType ) 0 )\r
102 #define bktRUN_INDICATOR                        ( ( unsigned portBASE_TYPE ) 0x55 )\r
103 \r
104 /* The queue on which the tasks block. */\r
105 static xQueueHandle xTestQueue;\r
106 \r
107 /* Handle to the secondary task is required by the primary task for calls\r
108 to vTaskSuspend/Resume(). */\r
109 static xTaskHandle xSecondary;\r
110 \r
111 /* Used to ensure that tasks are still executing without error. */\r
112 static portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;\r
113 static portBASE_TYPE xErrorOccurred = pdFALSE;\r
114 \r
115 /* Provides a simple mechanism for the primary task to know when the\r
116 secondary task has executed. */\r
117 static volatile unsigned portBASE_TYPE xRunIndicator;\r
118 \r
119 /* The two test tasks.  Their behaviour is commented within the files. */\r
120 static void vPrimaryBlockTimeTestTask( void *pvParameters );\r
121 static void vSecondaryBlockTimeTestTask( void *pvParameters );\r
122 \r
123 /*-----------------------------------------------------------*/\r
124 \r
125 void vCreateAltBlockTimeTasks( void )\r
126 {\r
127         /* Create the queue on which the two tasks block. */\r
128     xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );\r
129 \r
130         /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
131         in use.  The queue registry is provided as a means for kernel aware \r
132         debuggers to locate queues and has no purpose if a kernel aware debugger\r
133         is not being used.  The call to vQueueAddToRegistry() will be removed\r
134         by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
135         defined to be less than 1. */\r
136         vQueueAddToRegistry( xTestQueue, ( signed portCHAR * ) "AltBlockQueue" );\r
137 \r
138 \r
139         /* Create the two test tasks. */\r
140         xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
141         xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );\r
142 }\r
143 /*-----------------------------------------------------------*/\r
144 \r
145 static void vPrimaryBlockTimeTestTask( void *pvParameters )\r
146 {\r
147 portBASE_TYPE xItem, xData;\r
148 portTickType xTimeWhenBlocking;\r
149 portTickType xTimeToBlock, xBlockedTime;\r
150 \r
151         #ifdef USE_STDIO\r
152         void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
153         \r
154                 const portCHAR * const pcTaskStartMsg = "Alt primary block time test started.\r\n";\r
155 \r
156                 /* Queue a message for printing to say the task has started. */\r
157                 vPrintDisplayMessage( &pcTaskStartMsg );\r
158         #endif\r
159 \r
160         ( void ) pvParameters;\r
161 \r
162         for( ;; )\r
163         {\r
164                 /*********************************************************************\r
165         Test 1\r
166 \r
167         Simple block time wakeup test on queue receives. */\r
168                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
169                 {\r
170                         /* The queue is empty. Attempt to read from the queue using a block\r
171                         time.  When we wake, ensure the delta in time is as expected. */\r
172                         xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
173 \r
174                         /* A critical section is used to minimise the jitter in the time\r
175                         measurements. */\r
176                         portENTER_CRITICAL();\r
177                         {\r
178                                 xTimeWhenBlocking = xTaskGetTickCount();\r
179                                 \r
180                                 /* We should unblock after xTimeToBlock having not received\r
181                                 anything on the queue. */\r
182                                 if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )\r
183                                 {\r
184                                         xErrorOccurred = pdTRUE;\r
185                                 }\r
186 \r
187                                 /* How long were we blocked for? */\r
188                                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
189                         }\r
190                         portEXIT_CRITICAL();\r
191 \r
192                         if( xBlockedTime < xTimeToBlock )\r
193                         {\r
194                                 /* Should not have blocked for less than we requested. */\r
195                                 xErrorOccurred = pdTRUE;\r
196                         }\r
197 \r
198                         if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
199                         {\r
200                                 /* Should not have blocked for longer than we requested,\r
201                                 although we would not necessarily run as soon as we were\r
202                                 unblocked so a margin is allowed. */\r
203                                 xErrorOccurred = pdTRUE;\r
204                         }\r
205                 }\r
206 \r
207 \r
208                 #if configUSE_PREEMPTION == 0\r
209                         taskYIELD();\r
210                 #endif\r
211 \r
212 \r
213                 /*********************************************************************\r
214         Test 2\r
215 \r
216         Simple block time wakeup test on queue sends.\r
217 \r
218                 First fill the queue.  It should be empty so all sends should pass. */\r
219                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
220                 {\r
221                         if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
222                         {\r
223                                 xErrorOccurred = pdTRUE;\r
224                         }\r
225                 }\r
226 \r
227                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
228                 {\r
229                         /* The queue is full. Attempt to write to the queue using a block\r
230                         time.  When we wake, ensure the delta in time is as expected. */\r
231                         xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
232 \r
233                         portENTER_CRITICAL();\r
234                         {\r
235                                 xTimeWhenBlocking = xTaskGetTickCount();\r
236                                 \r
237                                 /* We should unblock after xTimeToBlock having not received\r
238                                 anything on the queue. */\r
239                                 if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )\r
240                                 {\r
241                                         xErrorOccurred = pdTRUE;\r
242                                 }\r
243 \r
244                                 /* How long were we blocked for? */\r
245                                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
246                         }\r
247                         portEXIT_CRITICAL();\r
248 \r
249                         if( xBlockedTime < xTimeToBlock )\r
250                         {\r
251                                 /* Should not have blocked for less than we requested. */\r
252                                 xErrorOccurred = pdTRUE;\r
253                         }\r
254 \r
255                         if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
256                         {\r
257                                 /* Should not have blocked for longer than we requested,\r
258                                 although we would not necessarily run as soon as we were\r
259                                 unblocked so a margin is allowed. */\r
260                                 xErrorOccurred = pdTRUE;\r
261                         }\r
262                 }\r
263 \r
264                 #if configUSE_PREEMPTION == 0\r
265                         taskYIELD();\r
266                 #endif\r
267 \r
268                 \r
269                 /*********************************************************************\r
270         Test 3\r
271 \r
272                 Wake the other task, it will block attempting to post to the queue.\r
273                 When we read from the queue the other task will wake, but before it\r
274                 can run we will post to the queue again.  When the other task runs it\r
275                 will find the queue still full, even though it was woken.  It should\r
276                 recognise that its block time has not expired and return to block for\r
277                 the remains of its block time.\r
278 \r
279                 Wake the other task so it blocks attempting to post to the already\r
280                 full queue. */\r
281                 xRunIndicator = 0;\r
282                 vTaskResume( xSecondary );\r
283 \r
284                 /* We need to wait a little to ensure the other task executes. */\r
285                 while( xRunIndicator != bktRUN_INDICATOR )\r
286                 {\r
287                         /* The other task has not yet executed. */\r
288                         vTaskDelay( bktSHORT_WAIT );\r
289                 }\r
290                 /* Make sure the other task is blocked on the queue. */\r
291                 vTaskDelay( bktSHORT_WAIT );\r
292                 xRunIndicator = 0;\r
293 \r
294                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
295                 {\r
296                         /* Now when we make space on the queue the other task should wake\r
297                         but not execute as this task has higher priority. */                            \r
298                         if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
299                         {\r
300                                 xErrorOccurred = pdTRUE;\r
301                         }\r
302 \r
303                         /* Now fill the queue again before the other task gets a chance to\r
304                         execute.  If the other task had executed we would find the queue\r
305                         full ourselves, and the other task have set xRunIndicator. */\r
306                         if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
307                         {\r
308                                 xErrorOccurred = pdTRUE;\r
309                         }\r
310 \r
311                         if( xRunIndicator == bktRUN_INDICATOR )\r
312                         {\r
313                                 /* The other task should not have executed. */\r
314                                 xErrorOccurred = pdTRUE;\r
315                         }\r
316 \r
317                         /* Raise the priority of the other task so it executes and blocks\r
318                         on the queue again. */\r
319                         vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
320 \r
321                         /* The other task should now have re-blocked without exiting the\r
322                         queue function. */\r
323                         if( xRunIndicator == bktRUN_INDICATOR )\r
324                         {\r
325                                 /* The other task should not have executed outside of the\r
326                                 queue function. */\r
327                                 xErrorOccurred = pdTRUE;\r
328                         }\r
329 \r
330                         /* Set the priority back down. */\r
331                         vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );                  \r
332                 }\r
333 \r
334                 /* Let the other task timeout.  When it unblockes it will check that it\r
335                 unblocked at the correct time, then suspend itself. */\r
336                 while( xRunIndicator != bktRUN_INDICATOR )\r
337                 {\r
338                         vTaskDelay( bktSHORT_WAIT );\r
339                 }\r
340                 vTaskDelay( bktSHORT_WAIT );\r
341                 xRunIndicator = 0;\r
342 \r
343                 #if configUSE_PREEMPTION == 0\r
344                         taskYIELD();\r
345                 #endif\r
346 \r
347                 /*********************************************************************\r
348         Test 4\r
349 \r
350                 As per test 3 - but with the send and receive the other way around.\r
351                 The other task blocks attempting to read from the queue.\r
352 \r
353                 Empty the queue.  We should find that it is full. */\r
354                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
355                 {\r
356                         if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
357                         {\r
358                                 xErrorOccurred = pdTRUE;\r
359                         }\r
360                 }\r
361                 \r
362                 /* Wake the other task so it blocks attempting to read from  the\r
363                 already empty queue. */\r
364                 vTaskResume( xSecondary );\r
365 \r
366                 /* We need to wait a little to ensure the other task executes. */\r
367                 while( xRunIndicator != bktRUN_INDICATOR )\r
368                 {\r
369                         vTaskDelay( bktSHORT_WAIT );\r
370                 }\r
371                 vTaskDelay( bktSHORT_WAIT );\r
372                 xRunIndicator = 0;\r
373 \r
374                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
375                 {\r
376                         /* Now when we place an item on the queue the other task should\r
377                         wake but not execute as this task has higher priority. */                               \r
378                         if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
379                         {\r
380                                 xErrorOccurred = pdTRUE;\r
381                         }\r
382 \r
383                         /* Now empty the queue again before the other task gets a chance to\r
384                         execute.  If the other task had executed we would find the queue\r
385                         empty ourselves, and the other task would be suspended. */\r
386                         if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
387                         {\r
388                                 xErrorOccurred = pdTRUE;\r
389                         }\r
390 \r
391                         if( xRunIndicator == bktRUN_INDICATOR )\r
392                         {\r
393                                 /* The other task should not have executed. */\r
394                                 xErrorOccurred = pdTRUE;\r
395                         }\r
396 \r
397                         /* Raise the priority of the other task so it executes and blocks\r
398                         on the queue again. */\r
399                         vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
400 \r
401                         /* The other task should now have re-blocked without exiting the\r
402                         queue function. */\r
403                         if( xRunIndicator == bktRUN_INDICATOR )\r
404                         {\r
405                                 /* The other task should not have executed outside of the\r
406                                 queue function. */\r
407                                 xErrorOccurred = pdTRUE;\r
408                         }\r
409                         vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );                  \r
410                 }\r
411 \r
412                 /* Let the other task timeout.  When it unblockes it will check that it\r
413                 unblocked at the correct time, then suspend itself. */\r
414                 while( xRunIndicator != bktRUN_INDICATOR )\r
415                 {\r
416                         vTaskDelay( bktSHORT_WAIT );\r
417                 }\r
418                 vTaskDelay( bktSHORT_WAIT );\r
419 \r
420                 xPrimaryCycles++;\r
421         }\r
422 }\r
423 /*-----------------------------------------------------------*/\r
424 \r
425 static void vSecondaryBlockTimeTestTask( void *pvParameters )\r
426 {\r
427 portTickType xTimeWhenBlocking, xBlockedTime;\r
428 portBASE_TYPE xData;\r
429 \r
430         #ifdef USE_STDIO\r
431         void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
432         \r
433                 const portCHAR * const pcTaskStartMsg = "Alt secondary block time test started.\r\n";\r
434 \r
435                 /* Queue a message for printing to say the task has started. */\r
436                 vPrintDisplayMessage( &pcTaskStartMsg );\r
437         #endif\r
438 \r
439         ( void ) pvParameters;\r
440 \r
441         for( ;; )\r
442         {\r
443                 /*********************************************************************\r
444         Test 1 and 2\r
445 \r
446                 This task does does not participate in these tests. */\r
447                 vTaskSuspend( NULL );\r
448 \r
449                 /*********************************************************************\r
450         Test 3\r
451 \r
452                 The first thing we do is attempt to read from the queue.  It should be\r
453                 full so we block.  Note the time before we block so we can check the\r
454                 wake time is as per that expected. */\r
455                 portENTER_CRITICAL();\r
456                 {\r
457                         xTimeWhenBlocking = xTaskGetTickCount();\r
458                         \r
459                         /* We should unblock after bktTIME_TO_BLOCK having not received\r
460                         anything on the queue. */\r
461                         xData = 0;\r
462                         xRunIndicator = bktRUN_INDICATOR;\r
463                         if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )\r
464                         {\r
465                                 xErrorOccurred = pdTRUE;\r
466                         }\r
467 \r
468                         /* How long were we inside the send function? */\r
469                         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
470                 }\r
471                 portEXIT_CRITICAL();\r
472 \r
473                 /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
474                 if( xBlockedTime < bktTIME_TO_BLOCK )\r
475                 {\r
476                         xErrorOccurred = pdTRUE;\r
477                 }\r
478 \r
479                 /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
480                 either.  A margin is permitted as we would not necessarily run as\r
481                 soon as we unblocked. */\r
482                 if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
483                 {\r
484                         xErrorOccurred = pdTRUE;\r
485                 }\r
486 \r
487                 /* Suspend ready for test 3. */\r
488                 xRunIndicator = bktRUN_INDICATOR;\r
489                 vTaskSuspend( NULL );\r
490 \r
491                 /*********************************************************************\r
492         Test 4\r
493 \r
494                 As per test three, but with the send and receive reversed. */\r
495                 portENTER_CRITICAL();\r
496                 {\r
497                         xTimeWhenBlocking = xTaskGetTickCount();\r
498                         \r
499                         /* We should unblock after bktTIME_TO_BLOCK having not received\r
500                         anything on the queue. */\r
501                         xRunIndicator = bktRUN_INDICATOR;\r
502                         if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )\r
503                         {\r
504                                 xErrorOccurred = pdTRUE;\r
505                         }\r
506 \r
507                         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
508                 }\r
509                 portEXIT_CRITICAL();\r
510 \r
511                 /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
512                 if( xBlockedTime < bktTIME_TO_BLOCK )\r
513                 {\r
514                         xErrorOccurred = pdTRUE;\r
515                 }\r
516 \r
517                 /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
518                 either.  A margin is permitted as we would not necessarily run as soon\r
519                 as we unblocked. */\r
520                 if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
521                 {\r
522                         xErrorOccurred = pdTRUE;\r
523                 }\r
524 \r
525                 xRunIndicator = bktRUN_INDICATOR;\r
526 \r
527                 xSecondaryCycles++;\r
528         }\r
529 }\r
530 /*-----------------------------------------------------------*/\r
531 \r
532 portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning( void )\r
533 {\r
534 static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;\r
535 portBASE_TYPE xReturn = pdPASS;\r
536 \r
537         /* Have both tasks performed at least one cycle since this function was\r
538         last called? */\r
539         if( xPrimaryCycles == xLastPrimaryCycleCount )\r
540         {\r
541                 xReturn = pdFAIL;\r
542         }\r
543 \r
544         if( xSecondaryCycles == xLastSecondaryCycleCount )\r
545         {\r
546                 xReturn = pdFAIL;\r
547         }\r
548 \r
549         if( xErrorOccurred == pdTRUE )\r
550         {\r
551                 xReturn = pdFAIL;\r
552         }\r
553 \r
554         xLastSecondaryCycleCount = xSecondaryCycles;\r
555         xLastPrimaryCycleCount = xPrimaryCycles;\r
556 \r
557         return xReturn;\r
558 }\r