]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/AltBlock.c
Update version numbers in preparation for V8.2.0 release candidate 1.
[freertos] / FreeRTOS / Demo / Common / Minimal / AltBlock.c
1 /*\r
2     FreeRTOS V8.2.0rc1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
12 \r
13     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
14     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
15     >>!   obliged to provide the source code for proprietary components     !<<\r
16     >>!   outside of the FreeRTOS kernel.                                   !<<\r
17 \r
18     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
19     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
20     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
21     link: http://www.freertos.org/a00114.html\r
22 \r
23     1 tab == 4 spaces!\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    Having a problem?  Start by reading the FAQ "My application does   *\r
28      *    not run, what could be wrong?".  Have you defined configASSERT()?  *\r
29      *                                                                       *\r
30      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
31      *                                                                       *\r
32     ***************************************************************************\r
33 \r
34     ***************************************************************************\r
35      *                                                                       *\r
36      *    FreeRTOS provides completely free yet professionally developed,    *\r
37      *    robust, strictly quality controlled, supported, and cross          *\r
38      *    platform software that is more than just the market leader, it     *\r
39      *    is the industry's de facto standard.                               *\r
40      *                                                                       *\r
41      *    Help yourself get started quickly while simultaneously helping     *\r
42      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
43      *    tutorial book, reference manual, or both:                          *\r
44      *    http://www.FreeRTOS.org/Documentation                              *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     ***************************************************************************\r
49      *                                                                       *\r
50      *   Investing in training allows your team to be as productive as       *\r
51      *   possible as early as possible, lowering your overall development    *\r
52      *   cost, and enabling you to bring a more robust product to market     *\r
53      *   earlier than would otherwise be possible.  Richard Barry is both    *\r
54      *   the architect and key author of FreeRTOS, and so also the world's   *\r
55      *   leading authority on what is the world's most popular real time     *\r
56      *   kernel for deeply embedded MCU designs.  Obtaining your training    *\r
57      *   from Richard ensures your team will gain directly from his in-depth *\r
58      *   product knowledge and years of usage experience.  Contact Real Time *\r
59      *   Engineers Ltd to enquire about the FreeRTOS Masterclass, presented  *\r
60      *   by Richard Barry:  http://www.FreeRTOS.org/contact\r
61      *                                                                       *\r
62     ***************************************************************************\r
63 \r
64     ***************************************************************************\r
65      *                                                                       *\r
66      *    You are receiving this top quality software for free.  Please play *\r
67      *    fair and reciprocate by reporting any suspected issues and         *\r
68      *    participating in the community forum:                              *\r
69      *    http://www.FreeRTOS.org/support                                    *\r
70      *                                                                       *\r
71      *    Thank you!                                                         *\r
72      *                                                                       *\r
73     ***************************************************************************\r
74 \r
75     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
76     license and Real Time Engineers Ltd. contact details.\r
77 \r
78     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
79     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
80     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
81 \r
82     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
83     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
84 \r
85     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
86     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
87     licenses offer ticketed support, indemnification and commercial middleware.\r
88 \r
89     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
90     engineered and independently SIL3 certified version for use in safety and\r
91     mission critical applications that require provable dependability.\r
92 \r
93     1 tab == 4 spaces!\r
94 */\r
95 \r
96 /*\r
97  * This is a version of BlockTim.c that uses the light weight API.\r
98  *\r
99  * This file contains some test scenarios that ensure tasks do not exit queue\r
100  * send or receive functions prematurely.  A description of the tests is\r
101  * included within the code.\r
102  */\r
103 \r
104 /* Kernel includes. */\r
105 #include "FreeRTOS.h"\r
106 #include "task.h"\r
107 #include "queue.h"\r
108 \r
109 /* Demo includes. */\r
110 #include "AltBlock.h"\r
111 \r
112 /* Task priorities. */\r
113 #define bktPRIMARY_PRIORITY                     ( 3 )\r
114 #define bktSECONDARY_PRIORITY           ( 2 )\r
115 \r
116 /* Task behaviour. */\r
117 #define bktQUEUE_LENGTH                         ( 5 )\r
118 #define bktSHORT_WAIT                           ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS )\r
119 #define bktPRIMARY_BLOCK_TIME           ( 10 )\r
120 #define bktALLOWABLE_MARGIN                     ( 12 )\r
121 #define bktTIME_TO_BLOCK                        ( 175 )\r
122 #define bktDONT_BLOCK                           ( ( TickType_t ) 0 )\r
123 #define bktRUN_INDICATOR                        ( ( UBaseType_t ) 0x55 )\r
124 \r
125 /* The queue on which the tasks block. */\r
126 static QueueHandle_t xTestQueue;\r
127 \r
128 /* Handle to the secondary task is required by the primary task for calls\r
129 to vTaskSuspend/Resume(). */\r
130 static TaskHandle_t xSecondary;\r
131 \r
132 /* Used to ensure that tasks are still executing without error. */\r
133 static BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;\r
134 static BaseType_t xErrorOccurred = pdFALSE;\r
135 \r
136 /* Provides a simple mechanism for the primary task to know when the\r
137 secondary task has executed. */\r
138 static volatile UBaseType_t xRunIndicator;\r
139 \r
140 /* The two test tasks.  Their behaviour is commented within the files. */\r
141 static void vPrimaryBlockTimeTestTask( void *pvParameters );\r
142 static void vSecondaryBlockTimeTestTask( void *pvParameters );\r
143 \r
144 /*-----------------------------------------------------------*/\r
145 \r
146 void vCreateAltBlockTimeTasks( void )\r
147 {\r
148         /* Create the queue on which the two tasks block. */\r
149     xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) );\r
150 \r
151         /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
152         in use.  The queue registry is provided as a means for kernel aware \r
153         debuggers to locate queues and has no purpose if a kernel aware debugger\r
154         is not being used.  The call to vQueueAddToRegistry() will be removed\r
155         by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
156         defined to be less than 1. */\r
157         vQueueAddToRegistry( xTestQueue, "AltBlockQueue" );\r
158 \r
159 \r
160         /* Create the two test tasks. */\r
161         xTaskCreate( vPrimaryBlockTimeTestTask, "FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
162         xTaskCreate( vSecondaryBlockTimeTestTask, "FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );\r
163 }\r
164 /*-----------------------------------------------------------*/\r
165 \r
166 static void vPrimaryBlockTimeTestTask( void *pvParameters )\r
167 {\r
168 BaseType_t xItem, xData;\r
169 TickType_t xTimeWhenBlocking;\r
170 TickType_t xTimeToBlock, xBlockedTime;\r
171 \r
172         #ifdef USE_STDIO\r
173         void vPrintDisplayMessage( const char * const * ppcMessageToSend );\r
174         \r
175                 const char * const pcTaskStartMsg = "Alt primary block time test started.\r\n";\r
176 \r
177                 /* Queue a message for printing to say the task has started. */\r
178                 vPrintDisplayMessage( &pcTaskStartMsg );\r
179         #endif\r
180 \r
181         ( void ) pvParameters;\r
182 \r
183         for( ;; )\r
184         {\r
185                 /*********************************************************************\r
186         Test 1\r
187 \r
188         Simple block time wakeup test on queue receives. */\r
189                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
190                 {\r
191                         /* The queue is empty. Attempt to read from the queue using a block\r
192                         time.  When we wake, ensure the delta in time is as expected. */\r
193                         xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
194 \r
195                         /* A critical section is used to minimise the jitter in the time\r
196                         measurements. */\r
197                         portENTER_CRITICAL();\r
198                         {\r
199                                 xTimeWhenBlocking = xTaskGetTickCount();\r
200                                 \r
201                                 /* We should unblock after xTimeToBlock having not received\r
202                                 anything on the queue. */\r
203                                 if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )\r
204                                 {\r
205                                         xErrorOccurred = pdTRUE;\r
206                                 }\r
207 \r
208                                 /* How long were we blocked for? */\r
209                                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
210                         }\r
211                         portEXIT_CRITICAL();\r
212 \r
213                         if( xBlockedTime < xTimeToBlock )\r
214                         {\r
215                                 /* Should not have blocked for less than we requested. */\r
216                                 xErrorOccurred = pdTRUE;\r
217                         }\r
218 \r
219                         if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
220                         {\r
221                                 /* Should not have blocked for longer than we requested,\r
222                                 although we would not necessarily run as soon as we were\r
223                                 unblocked so a margin is allowed. */\r
224                                 xErrorOccurred = pdTRUE;\r
225                         }\r
226                 }\r
227 \r
228 \r
229                 #if configUSE_PREEMPTION == 0\r
230                         taskYIELD();\r
231                 #endif\r
232 \r
233 \r
234                 /*********************************************************************\r
235         Test 2\r
236 \r
237         Simple block time wakeup test on queue sends.\r
238 \r
239                 First fill the queue.  It should be empty so all sends should pass. */\r
240                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
241                 {\r
242                         if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
243                         {\r
244                                 xErrorOccurred = pdTRUE;\r
245                         }\r
246                 }\r
247 \r
248                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
249                 {\r
250                         /* The queue is full. Attempt to write to the queue using a block\r
251                         time.  When we wake, ensure the delta in time is as expected. */\r
252                         xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
253 \r
254                         portENTER_CRITICAL();\r
255                         {\r
256                                 xTimeWhenBlocking = xTaskGetTickCount();\r
257                                 \r
258                                 /* We should unblock after xTimeToBlock having not received\r
259                                 anything on the queue. */\r
260                                 if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )\r
261                                 {\r
262                                         xErrorOccurred = pdTRUE;\r
263                                 }\r
264 \r
265                                 /* How long were we blocked for? */\r
266                                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
267                         }\r
268                         portEXIT_CRITICAL();\r
269 \r
270                         if( xBlockedTime < xTimeToBlock )\r
271                         {\r
272                                 /* Should not have blocked for less than we requested. */\r
273                                 xErrorOccurred = pdTRUE;\r
274                         }\r
275 \r
276                         if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
277                         {\r
278                                 /* Should not have blocked for longer than we requested,\r
279                                 although we would not necessarily run as soon as we were\r
280                                 unblocked so a margin is allowed. */\r
281                                 xErrorOccurred = pdTRUE;\r
282                         }\r
283                 }\r
284 \r
285                 #if configUSE_PREEMPTION == 0\r
286                         taskYIELD();\r
287                 #endif\r
288 \r
289                 \r
290                 /*********************************************************************\r
291         Test 3\r
292 \r
293                 Wake the other task, it will block attempting to post to the queue.\r
294                 When we read from the queue the other task will wake, but before it\r
295                 can run we will post to the queue again.  When the other task runs it\r
296                 will find the queue still full, even though it was woken.  It should\r
297                 recognise that its block time has not expired and return to block for\r
298                 the remains of its block time.\r
299 \r
300                 Wake the other task so it blocks attempting to post to the already\r
301                 full queue. */\r
302                 xRunIndicator = 0;\r
303                 vTaskResume( xSecondary );\r
304 \r
305                 /* We need to wait a little to ensure the other task executes. */\r
306                 while( xRunIndicator != bktRUN_INDICATOR )\r
307                 {\r
308                         /* The other task has not yet executed. */\r
309                         vTaskDelay( bktSHORT_WAIT );\r
310                 }\r
311                 /* Make sure the other task is blocked on the queue. */\r
312                 vTaskDelay( bktSHORT_WAIT );\r
313                 xRunIndicator = 0;\r
314 \r
315                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
316                 {\r
317                         /* Now when we make space on the queue the other task should wake\r
318                         but not execute as this task has higher priority. */                            \r
319                         if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
320                         {\r
321                                 xErrorOccurred = pdTRUE;\r
322                         }\r
323 \r
324                         /* Now fill the queue again before the other task gets a chance to\r
325                         execute.  If the other task had executed we would find the queue\r
326                         full ourselves, and the other task have set xRunIndicator. */\r
327                         if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
328                         {\r
329                                 xErrorOccurred = pdTRUE;\r
330                         }\r
331 \r
332                         if( xRunIndicator == bktRUN_INDICATOR )\r
333                         {\r
334                                 /* The other task should not have executed. */\r
335                                 xErrorOccurred = pdTRUE;\r
336                         }\r
337 \r
338                         /* Raise the priority of the other task so it executes and blocks\r
339                         on the queue again. */\r
340                         vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
341 \r
342                         /* The other task should now have re-blocked without exiting the\r
343                         queue function. */\r
344                         if( xRunIndicator == bktRUN_INDICATOR )\r
345                         {\r
346                                 /* The other task should not have executed outside of the\r
347                                 queue function. */\r
348                                 xErrorOccurred = pdTRUE;\r
349                         }\r
350 \r
351                         /* Set the priority back down. */\r
352                         vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );                  \r
353                 }\r
354 \r
355                 /* Let the other task timeout.  When it unblockes it will check that it\r
356                 unblocked at the correct time, then suspend itself. */\r
357                 while( xRunIndicator != bktRUN_INDICATOR )\r
358                 {\r
359                         vTaskDelay( bktSHORT_WAIT );\r
360                 }\r
361                 vTaskDelay( bktSHORT_WAIT );\r
362                 xRunIndicator = 0;\r
363 \r
364                 #if configUSE_PREEMPTION == 0\r
365                         taskYIELD();\r
366                 #endif\r
367 \r
368                 /*********************************************************************\r
369         Test 4\r
370 \r
371                 As per test 3 - but with the send and receive the other way around.\r
372                 The other task blocks attempting to read from the queue.\r
373 \r
374                 Empty the queue.  We should find that it is full. */\r
375                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
376                 {\r
377                         if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
378                         {\r
379                                 xErrorOccurred = pdTRUE;\r
380                         }\r
381                 }\r
382                 \r
383                 /* Wake the other task so it blocks attempting to read from  the\r
384                 already empty queue. */\r
385                 vTaskResume( xSecondary );\r
386 \r
387                 /* We need to wait a little to ensure the other task executes. */\r
388                 while( xRunIndicator != bktRUN_INDICATOR )\r
389                 {\r
390                         vTaskDelay( bktSHORT_WAIT );\r
391                 }\r
392                 vTaskDelay( bktSHORT_WAIT );\r
393                 xRunIndicator = 0;\r
394 \r
395                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
396                 {\r
397                         /* Now when we place an item on the queue the other task should\r
398                         wake but not execute as this task has higher priority. */                               \r
399                         if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
400                         {\r
401                                 xErrorOccurred = pdTRUE;\r
402                         }\r
403 \r
404                         /* Now empty the queue again before the other task gets a chance to\r
405                         execute.  If the other task had executed we would find the queue\r
406                         empty ourselves, and the other task would be suspended. */\r
407                         if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
408                         {\r
409                                 xErrorOccurred = pdTRUE;\r
410                         }\r
411 \r
412                         if( xRunIndicator == bktRUN_INDICATOR )\r
413                         {\r
414                                 /* The other task should not have executed. */\r
415                                 xErrorOccurred = pdTRUE;\r
416                         }\r
417 \r
418                         /* Raise the priority of the other task so it executes and blocks\r
419                         on the queue again. */\r
420                         vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
421 \r
422                         /* The other task should now have re-blocked without exiting the\r
423                         queue function. */\r
424                         if( xRunIndicator == bktRUN_INDICATOR )\r
425                         {\r
426                                 /* The other task should not have executed outside of the\r
427                                 queue function. */\r
428                                 xErrorOccurred = pdTRUE;\r
429                         }\r
430                         vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );                  \r
431                 }\r
432 \r
433                 /* Let the other task timeout.  When it unblockes it will check that it\r
434                 unblocked at the correct time, then suspend itself. */\r
435                 while( xRunIndicator != bktRUN_INDICATOR )\r
436                 {\r
437                         vTaskDelay( bktSHORT_WAIT );\r
438                 }\r
439                 vTaskDelay( bktSHORT_WAIT );\r
440 \r
441                 xPrimaryCycles++;\r
442         }\r
443 }\r
444 /*-----------------------------------------------------------*/\r
445 \r
446 static void vSecondaryBlockTimeTestTask( void *pvParameters )\r
447 {\r
448 TickType_t xTimeWhenBlocking, xBlockedTime;\r
449 BaseType_t xData;\r
450 \r
451         #ifdef USE_STDIO\r
452         void vPrintDisplayMessage( const char * const * ppcMessageToSend );\r
453         \r
454                 const char * const pcTaskStartMsg = "Alt secondary block time test started.\r\n";\r
455 \r
456                 /* Queue a message for printing to say the task has started. */\r
457                 vPrintDisplayMessage( &pcTaskStartMsg );\r
458         #endif\r
459 \r
460         ( void ) pvParameters;\r
461 \r
462         for( ;; )\r
463         {\r
464                 /*********************************************************************\r
465         Test 1 and 2\r
466 \r
467                 This task does does not participate in these tests. */\r
468                 vTaskSuspend( NULL );\r
469 \r
470                 /*********************************************************************\r
471         Test 3\r
472 \r
473                 The first thing we do is attempt to read from the queue.  It should be\r
474                 full so we block.  Note the time before we block so we can check the\r
475                 wake time is as per that expected. */\r
476                 portENTER_CRITICAL();\r
477                 {\r
478                         xTimeWhenBlocking = xTaskGetTickCount();\r
479                         \r
480                         /* We should unblock after bktTIME_TO_BLOCK having not received\r
481                         anything on the queue. */\r
482                         xData = 0;\r
483                         xRunIndicator = bktRUN_INDICATOR;\r
484                         if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )\r
485                         {\r
486                                 xErrorOccurred = pdTRUE;\r
487                         }\r
488 \r
489                         /* How long were we inside the send function? */\r
490                         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
491                 }\r
492                 portEXIT_CRITICAL();\r
493 \r
494                 /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
495                 if( xBlockedTime < bktTIME_TO_BLOCK )\r
496                 {\r
497                         xErrorOccurred = pdTRUE;\r
498                 }\r
499 \r
500                 /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
501                 either.  A margin is permitted as we would not necessarily run as\r
502                 soon as we unblocked. */\r
503                 if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
504                 {\r
505                         xErrorOccurred = pdTRUE;\r
506                 }\r
507 \r
508                 /* Suspend ready for test 3. */\r
509                 xRunIndicator = bktRUN_INDICATOR;\r
510                 vTaskSuspend( NULL );\r
511 \r
512                 /*********************************************************************\r
513         Test 4\r
514 \r
515                 As per test three, but with the send and receive reversed. */\r
516                 portENTER_CRITICAL();\r
517                 {\r
518                         xTimeWhenBlocking = xTaskGetTickCount();\r
519                         \r
520                         /* We should unblock after bktTIME_TO_BLOCK having not received\r
521                         anything on the queue. */\r
522                         xRunIndicator = bktRUN_INDICATOR;\r
523                         if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )\r
524                         {\r
525                                 xErrorOccurred = pdTRUE;\r
526                         }\r
527 \r
528                         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
529                 }\r
530                 portEXIT_CRITICAL();\r
531 \r
532                 /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
533                 if( xBlockedTime < bktTIME_TO_BLOCK )\r
534                 {\r
535                         xErrorOccurred = pdTRUE;\r
536                 }\r
537 \r
538                 /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
539                 either.  A margin is permitted as we would not necessarily run as soon\r
540                 as we unblocked. */\r
541                 if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
542                 {\r
543                         xErrorOccurred = pdTRUE;\r
544                 }\r
545 \r
546                 xRunIndicator = bktRUN_INDICATOR;\r
547 \r
548                 xSecondaryCycles++;\r
549         }\r
550 }\r
551 /*-----------------------------------------------------------*/\r
552 \r
553 BaseType_t xAreAltBlockTimeTestTasksStillRunning( void )\r
554 {\r
555 static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;\r
556 BaseType_t xReturn = pdPASS;\r
557 \r
558         /* Have both tasks performed at least one cycle since this function was\r
559         last called? */\r
560         if( xPrimaryCycles == xLastPrimaryCycleCount )\r
561         {\r
562                 xReturn = pdFAIL;\r
563         }\r
564 \r
565         if( xSecondaryCycles == xLastSecondaryCycleCount )\r
566         {\r
567                 xReturn = pdFAIL;\r
568         }\r
569 \r
570         if( xErrorOccurred == pdTRUE )\r
571         {\r
572                 xReturn = pdFAIL;\r
573         }\r
574 \r
575         xLastSecondaryCycleCount = xSecondaryCycles;\r
576         xLastPrimaryCycleCount = xPrimaryCycles;\r
577 \r
578         return xReturn;\r
579 }\r