]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/AbortDelay.c
Prepare for V9.0.0 release:
[freertos] / FreeRTOS / Demo / Common / Minimal / AbortDelay.c
1 /*\r
2     FreeRTOS V9.0.0 - Copyright (C) 2016 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     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /*\r
71  * This file contains some test scenarios that ensure tasks respond correctly\r
72  * to xTaskAbortDelay() calls.\r
73  */\r
74 \r
75 /* Standard includes. */\r
76 #include "limits.h"\r
77 \r
78 /* Kernel includes. */\r
79 #include "FreeRTOS.h"\r
80 #include "task.h"\r
81 #include "queue.h"\r
82 #include "semphr.h"\r
83 #include "event_groups.h"\r
84 \r
85 /* Demo includes. */\r
86 #include "AbortDelay.h"\r
87 \r
88 /* This file can only be used if the functionality it tests is included in the\r
89 build.  Remove the whole file if this is not the case. */\r
90 #if( INCLUDE_xTaskAbortDelay == 1 )\r
91 \r
92 #if( INCLUDE_xTaskGetHandle != 1 )\r
93         #error This test file uses the xTaskGetHandle() API function so INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h.\r
94 #endif\r
95 \r
96 /* Task priorities.  Allow these to be overridden. */\r
97 #ifndef abtCONTROLLING_PRIORITY\r
98         #define abtCONTROLLING_PRIORITY         ( configMAX_PRIORITIES - 3 )\r
99 #endif\r
100 \r
101 #ifndef abtBLOCKING_PRIORITY\r
102         #define abtBLOCKING_PRIORITY    ( configMAX_PRIORITIES - 2 )\r
103 #endif\r
104 \r
105 /* The tests that are performed. */\r
106 #define abtNOTIFY_WAIT_ABORTS           0\r
107 #define abtNOTIFY_TAKE_ABORTS           1\r
108 #define abtDELAY_ABORTS                         2\r
109 #define abtDELAY_UNTIL_ABORTS           3\r
110 #define abtSEMAPHORE_TAKE_ABORTS        4\r
111 #define abtEVENT_GROUP_ABORTS           5\r
112 #define abtQUEUE_SEND_ABORTS            6\r
113 #define abtMAX_TESTS                            7\r
114 \r
115 /*-----------------------------------------------------------*/\r
116 \r
117 /*\r
118  * The two test tasks.  The controlling task specifies which test to executed.\r
119  * More information is provided in the comments within the tasks.\r
120  */\r
121 static void prvControllingTask( void *pvParameters );\r
122 static void prvBlockingTask( void *pvParameters );\r
123 \r
124 /*\r
125  * Test functions called by the blocking task.  Each function follows the same\r
126  * pattern, but the way the task blocks is different in each case.\r
127  *\r
128  * In each function three blocking calls are made.  The first and third\r
129  * blocking call is expected to time out, while the middle blocking call is\r
130  * expected to be aborted by the controlling task half way through the block\r
131  * time.\r
132  */\r
133 static void prvTestAbortingTaskNotifyWait( void );\r
134 static void prvTestAbortingTaskNotifyTake( void );\r
135 static void prvTestAbortingTaskDelay( void );\r
136 static void prvTestAbortingTaskDelayUntil( void );\r
137 static void prvTestAbortingSemaphoreTake( void );\r
138 static void prvTestAbortingEventGroupWait( void );\r
139 static void prvTestAbortingQueueSend( void );\r
140 \r
141 /*\r
142  * Checks the amount of time a task spent in the Blocked state is within the\r
143  * expected bounds.\r
144  */\r
145 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );\r
146 \r
147 /*-----------------------------------------------------------*/\r
148 \r
149 /* Used to ensure that tasks are still executing without error. */\r
150 static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;\r
151 static volatile BaseType_t xErrorOccurred = pdFALSE;\r
152 \r
153 /* Each task needs to know the other tasks handle so they can send signals to\r
154 each other.  The handle is obtained from the task's name. */\r
155 static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";\r
156 \r
157 /* The maximum amount of time a task will block for. */\r
158 const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );\r
159 const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );\r
160 \r
161 /* The actual block time is dependent on the priority of other tasks in the\r
162 system so the actual block time might be greater than that expected, but it\r
163 should be within an acceptable upper bound. */\r
164 const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );\r
165 \r
166 /*-----------------------------------------------------------*/\r
167 \r
168 void vCreateAbortDelayTasks( void )\r
169 {\r
170         /* Create the two test tasks described above. */\r
171         xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );\r
172         xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );\r
173 }\r
174 /*-----------------------------------------------------------*/\r
175 \r
176 static void prvControllingTask( void *pvParameters )\r
177 {\r
178 TaskHandle_t xBlockingTask;\r
179 uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;\r
180 TickType_t xTimeAtStart;\r
181 const TickType_t xStartMargin = 2UL;\r
182 \r
183         /* Just to remove compiler warnings. */\r
184         ( void ) pvParameters;\r
185 \r
186         xBlockingTask = xTaskGetHandle( pcBlockingTaskName );\r
187         configASSERT( xBlockingTask );\r
188 \r
189         for( ;; )\r
190         {\r
191                 /* Tell the secondary task to perform the next test. */\r
192                 xTimeAtStart = xTaskGetTickCount();\r
193                 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );\r
194 \r
195                 /* The secondary task has a higher priority, so will now be in the\r
196                 Blocked state to wait for a maximum of xMaxBlockTime.  It expects that\r
197                 period to complete with a timeout.  It will then block for\r
198                 xMaxBlockTimeAgain, but this time it expects to the block time to abort\r
199                 half way through.  Block until it is time to send the abort to the\r
200                 secondary task.  xStartMargin is used because this task takes timing\r
201                 from the beginning of the test, whereas the blocking task takes timing\r
202                 from the entry into the Blocked state - and as the tasks run at\r
203                 different priorities, there may be some discrepancy.  Also, temporarily\r
204                 raise the priority of the controlling task to that of the blocking\r
205                 task to minimise discrepancies. */\r
206                 vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );\r
207                 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );\r
208                 xTaskAbortDelay( xBlockingTask );\r
209 \r
210                 /* Reset the priority to the normal controlling priority. */\r
211                 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );\r
212 \r
213                 /* Now wait to be notified that the secondary task has completed its\r
214                 test. */\r
215                 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
216 \r
217                 /* Did the entire test run for the expected time, which is two full\r
218                 block times plus the half block time caused by calling\r
219                 xTaskAbortDelay()? */\r
220                 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );\r
221 \r
222                 /* Move onto the next test. */\r
223                 ulTestToPerform++;\r
224 \r
225                 if( ulTestToPerform >= abtMAX_TESTS )\r
226                 {\r
227                         ulTestToPerform = 0;\r
228                 }\r
229 \r
230                 /* To indicate this task is still executing. */\r
231                 xControllingCycles++;\r
232         }\r
233 }\r
234 /*-----------------------------------------------------------*/\r
235 \r
236 static void prvBlockingTask( void *pvParameters )\r
237 {\r
238 TaskHandle_t xControllingTask;\r
239 uint32_t ulNotificationValue;\r
240 const uint32_t ulMax = 0xffffffffUL;\r
241 \r
242         /* Just to remove compiler warnings. */\r
243         ( void ) pvParameters;\r
244 \r
245         xControllingTask = xTaskGetHandle( pcControllingTaskName );\r
246         configASSERT( xControllingTask );\r
247 \r
248         for( ;; )\r
249         {\r
250                 /* Wait to be notified of the test that is to be performed next. */\r
251                 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );\r
252 \r
253                 switch( ulNotificationValue )\r
254                 {\r
255                         case abtNOTIFY_WAIT_ABORTS:\r
256                                 prvTestAbortingTaskNotifyWait();\r
257                                 break;\r
258 \r
259                         case abtNOTIFY_TAKE_ABORTS:\r
260                                 prvTestAbortingTaskNotifyTake();\r
261                                 break;\r
262 \r
263                         case abtDELAY_ABORTS:\r
264                                 prvTestAbortingTaskDelay();\r
265                                 break;\r
266 \r
267                         case abtDELAY_UNTIL_ABORTS:\r
268                                 prvTestAbortingTaskDelayUntil();\r
269                                 break;\r
270 \r
271                         case abtSEMAPHORE_TAKE_ABORTS:\r
272                                 prvTestAbortingSemaphoreTake();\r
273                                 break;\r
274 \r
275                         case abtEVENT_GROUP_ABORTS:\r
276                                 prvTestAbortingEventGroupWait();\r
277                                 break;\r
278 \r
279                         case abtQUEUE_SEND_ABORTS:\r
280                                 prvTestAbortingQueueSend();\r
281                                 break;\r
282 \r
283                         default:\r
284                                 /* Should not get here. */\r
285                                 break;\r
286                 }\r
287 \r
288                 /* Let the primary task know the test is complete. */\r
289                 xTaskNotifyGive( xControllingTask );\r
290 \r
291                 /* To indicate this task is still executing. */\r
292                 xBlockingCycles++;\r
293         }\r
294 }\r
295 /*-----------------------------------------------------------*/\r
296 \r
297 static void prvTestAbortingTaskDelayUntil( void )\r
298 {\r
299 TickType_t xTimeAtStart, xLastBlockTime;\r
300 \r
301         /* Note the time before the delay so the length of the delay is known. */\r
302         xTimeAtStart = xTaskGetTickCount();\r
303 \r
304         /* Take a copy of the time as it is updated in the call to\r
305         vTaskDelayUntil() but its original value is needed to determine the actual\r
306         time spend in the Blocked state. */\r
307         xLastBlockTime = xTimeAtStart;\r
308 \r
309         /* This first delay should just time out. */\r
310         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
311         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
312 \r
313         /* This second delay should be aborted by the primary task half way\r
314         through.  Again take a copy of the time as it is updated in the call to\r
315         vTaskDelayUntil() buts its original value is needed to determine the amount\r
316         of time actually spent in the Blocked state. */\r
317         xTimeAtStart = xTaskGetTickCount();\r
318         xLastBlockTime = xTimeAtStart;\r
319         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
320         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
321 \r
322         /* As with the other tests, the third block period should not time out. */\r
323         xTimeAtStart = xTaskGetTickCount();\r
324         xLastBlockTime = xTimeAtStart;\r
325         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
326         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
327 }\r
328 /*-----------------------------------------------------------*/\r
329 \r
330 static void prvTestAbortingTaskDelay( void )\r
331 {\r
332 TickType_t xTimeAtStart;\r
333 \r
334         /* Note the time before the delay so the length of the delay is known. */\r
335         xTimeAtStart = xTaskGetTickCount();\r
336 \r
337         /* This first delay should just time out. */\r
338         vTaskDelay( xMaxBlockTime );\r
339         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
340 \r
341         /* Note the time before the delay so the length of the delay is known. */\r
342         xTimeAtStart = xTaskGetTickCount();\r
343 \r
344         /* This second delay should be aborted by the primary task half way\r
345         through. */\r
346         vTaskDelay( xMaxBlockTime );\r
347         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
348 \r
349         /* Note the time before the delay so the length of the delay is known. */\r
350         xTimeAtStart = xTaskGetTickCount();\r
351 \r
352         /* This third delay should just time out again. */\r
353         vTaskDelay( xMaxBlockTime );\r
354         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
355 }\r
356 /*-----------------------------------------------------------*/\r
357 \r
358 static void prvTestAbortingTaskNotifyTake( void )\r
359 {\r
360 TickType_t xTimeAtStart;\r
361 uint32_t ulReturn;\r
362 \r
363         /* Note the time before the delay so the length of the delay is known. */\r
364         xTimeAtStart = xTaskGetTickCount();\r
365 \r
366         /* This first delay should just time out. */\r
367         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
368         if( ulReturn != 0 )\r
369         {\r
370                 xErrorOccurred = pdTRUE;\r
371         }\r
372         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
373 \r
374         /* Note the time before the delay so the length of the delay is known. */\r
375         xTimeAtStart = xTaskGetTickCount();\r
376 \r
377         /* This second delay should be aborted by the primary task half way\r
378         through. */\r
379         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
380         if( ulReturn != 0 )\r
381         {\r
382                 xErrorOccurred = pdTRUE;\r
383         }\r
384         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
385 \r
386         /* Note the time before the delay so the length of the delay is known. */\r
387         xTimeAtStart = xTaskGetTickCount();\r
388 \r
389         /* This third delay should just time out again. */\r
390         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
391         if( ulReturn != 0 )\r
392         {\r
393                 xErrorOccurred = pdTRUE;\r
394         }\r
395         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
396 }\r
397 /*-----------------------------------------------------------*/\r
398 \r
399 static void prvTestAbortingEventGroupWait( void )\r
400 {\r
401 TickType_t xTimeAtStart;\r
402 EventGroupHandle_t xEventGroup;\r
403 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;\r
404 \r
405         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
406         {\r
407                 static StaticEventGroup_t xEventGroupBuffer;\r
408 \r
409                 /* Create the event group.  Statically allocated memory is used so the\r
410                 creation cannot fail. */\r
411                 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );\r
412         }\r
413         #else\r
414         {\r
415                 xEventGroup = xEventGroupCreate();\r
416                 configASSERT( xEventGroup );\r
417         }\r
418         #endif\r
419 \r
420         /* Note the time before the delay so the length of the delay is known. */\r
421         xTimeAtStart = xTaskGetTickCount();\r
422 \r
423         /* This first delay should just time out. */\r
424         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
425         if( xReturn != 0x00 )\r
426         {\r
427                 xErrorOccurred = pdTRUE;\r
428         }\r
429         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
430 \r
431         /* Note the time before the delay so the length of the delay is known. */\r
432         xTimeAtStart = xTaskGetTickCount();\r
433 \r
434         /* This second delay should be aborted by the primary task half way\r
435         through. */\r
436         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
437         if( xReturn != 0x00 )\r
438         {\r
439                 xErrorOccurred = pdTRUE;\r
440         }\r
441         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
442 \r
443         /* Note the time before the delay so the length of the delay is known. */\r
444         xTimeAtStart = xTaskGetTickCount();\r
445 \r
446         /* This third delay should just time out again. */\r
447         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
448         if( xReturn != 0x00 )\r
449         {\r
450                 xErrorOccurred = pdTRUE;\r
451         }\r
452         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
453 \r
454         /* Not really necessary in this case, but for completeness. */\r
455         vEventGroupDelete( xEventGroup );\r
456 }\r
457 /*-----------------------------------------------------------*/\r
458 \r
459 static void prvTestAbortingQueueSend( void )\r
460 {\r
461 TickType_t xTimeAtStart;\r
462 BaseType_t xReturn;\r
463 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;\r
464 QueueHandle_t xQueue;\r
465 uint8_t ucItemToQueue;\r
466 \r
467         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
468         {\r
469                 static StaticQueue_t xQueueBuffer;\r
470                 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];\r
471 \r
472                 /* Create the queue.  Statically allocated memory is used so the\r
473                 creation cannot fail. */\r
474                 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );\r
475         }\r
476         #else\r
477         {\r
478                 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );\r
479                 configASSERT( xQueue );\r
480         }\r
481         #endif\r
482 \r
483         /* This function tests aborting when in the blocked state waiting to send,\r
484         so the queue must be full.  There is only one space in the queue. */\r
485         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
486         if( xReturn != pdPASS )\r
487         {\r
488                 xErrorOccurred = pdTRUE;\r
489         }\r
490 \r
491         /* Note the time before the delay so the length of the delay is known. */\r
492         xTimeAtStart = xTaskGetTickCount();\r
493 \r
494         /* This first delay should just time out. */\r
495         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
496         if( xReturn != pdFALSE )\r
497         {\r
498                 xErrorOccurred = pdTRUE;\r
499         }\r
500         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
501 \r
502         /* Note the time before the delay so the length of the delay is known. */\r
503         xTimeAtStart = xTaskGetTickCount();\r
504 \r
505         /* This second delay should be aborted by the primary task half way\r
506         through. */\r
507         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
508         if( xReturn != pdFALSE )\r
509         {\r
510                 xErrorOccurred = pdTRUE;\r
511         }\r
512         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
513 \r
514         /* Note the time before the delay so the length of the delay is known. */\r
515         xTimeAtStart = xTaskGetTickCount();\r
516 \r
517         /* This third delay should just time out again. */\r
518         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
519         if( xReturn != pdFALSE )\r
520         {\r
521                 xErrorOccurred = pdTRUE;\r
522         }\r
523         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
524 \r
525         /* Not really necessary in this case, but for completeness. */\r
526         vQueueDelete( xQueue );\r
527 }\r
528 /*-----------------------------------------------------------*/\r
529 \r
530 static void prvTestAbortingSemaphoreTake( void )\r
531 {\r
532 TickType_t xTimeAtStart;\r
533 BaseType_t xReturn;\r
534 SemaphoreHandle_t xSemaphore;\r
535 \r
536         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
537         {\r
538                 static StaticSemaphore_t xSemaphoreBuffer;\r
539 \r
540                 /* Create the semaphore.  Statically allocated memory is used so the\r
541                 creation cannot fail. */\r
542                 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
543         }\r
544         #else\r
545         {\r
546                 xSemaphore = xSemaphoreCreateBinary();\r
547         }\r
548         #endif\r
549 \r
550         /* Note the time before the delay so the length of the delay is known. */\r
551         xTimeAtStart = xTaskGetTickCount();\r
552 \r
553         /* This first delay should just time out. */\r
554         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
555         if( xReturn != pdFALSE )\r
556         {\r
557                 xErrorOccurred = pdTRUE;\r
558         }\r
559         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
560 \r
561         /* Note the time before the delay so the length of the delay is known. */\r
562         xTimeAtStart = xTaskGetTickCount();\r
563 \r
564         /* This second delay should be aborted by the primary task half way\r
565         through. */\r
566         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
567         if( xReturn != pdFALSE )\r
568         {\r
569                 xErrorOccurred = pdTRUE;\r
570         }\r
571         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
572 \r
573         /* Note the time before the delay so the length of the delay is known. */\r
574         xTimeAtStart = xTaskGetTickCount();\r
575 \r
576         /* This third delay should just time out again. */\r
577         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
578         if( xReturn != pdFALSE )\r
579         {\r
580                 xErrorOccurred = pdTRUE;\r
581         }\r
582         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
583 \r
584         /* Not really necessary in this case, but for completeness. */\r
585         vSemaphoreDelete( xSemaphore );\r
586 }\r
587 /*-----------------------------------------------------------*/\r
588 \r
589 static void prvTestAbortingTaskNotifyWait( void )\r
590 {\r
591 TickType_t xTimeAtStart;\r
592 BaseType_t xReturn;\r
593 \r
594         /* Note the time before the delay so the length of the delay is known. */\r
595         xTimeAtStart = xTaskGetTickCount();\r
596 \r
597         /* This first delay should just time out. */\r
598         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
599         if( xReturn != pdFALSE )\r
600         {\r
601                 xErrorOccurred = pdTRUE;\r
602         }\r
603         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
604 \r
605         /* Note the time before the delay so the length of the delay is known. */\r
606         xTimeAtStart = xTaskGetTickCount();\r
607 \r
608         /* This second delay should be aborted by the primary task half way\r
609         through. */\r
610         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
611         if( xReturn != pdFALSE )\r
612         {\r
613                 xErrorOccurred = pdTRUE;\r
614         }\r
615         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
616 \r
617         /* Note the time before the delay so the length of the delay is known. */\r
618         xTimeAtStart = xTaskGetTickCount();\r
619 \r
620         /* This third delay should just time out again. */\r
621         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
622         if( xReturn != pdFALSE )\r
623         {\r
624                 xErrorOccurred = pdTRUE;\r
625         }\r
626         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
627 }\r
628 /*-----------------------------------------------------------*/\r
629 \r
630 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )\r
631 {\r
632 TickType_t xTimeNow, xActualBlockTime;\r
633 \r
634         xTimeNow = xTaskGetTickCount();\r
635         xActualBlockTime = xTimeNow - xStartTime;\r
636 \r
637         /* The actual block time should not be less than the expected block time. */\r
638         if( xActualBlockTime < xExpectedBlockTime )\r
639         {\r
640                 xErrorOccurred = pdTRUE;\r
641         }\r
642 \r
643         /* The actual block time can be greater than the expected block time, as it\r
644         depends on the priority of the other tasks, but it should be within an\r
645         acceptable margin. */\r
646         if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )\r
647         {\r
648                 xErrorOccurred = pdTRUE;\r
649         }\r
650 }\r
651 /*-----------------------------------------------------------*/\r
652 \r
653 BaseType_t xAreAbortDelayTestTasksStillRunning( void )\r
654 {\r
655 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;\r
656 BaseType_t xReturn = pdPASS;\r
657 \r
658         /* Have both tasks performed at least one cycle since this function was\r
659         last called? */\r
660         if( xControllingCycles == xLastControllingCycleCount )\r
661         {\r
662                 xReturn = pdFAIL;\r
663         }\r
664 \r
665         if( xBlockingCycles == xLastBlockingCycleCount )\r
666         {\r
667                 xReturn = pdFAIL;\r
668         }\r
669 \r
670         if( xErrorOccurred == pdTRUE )\r
671         {\r
672                 xReturn = pdFAIL;\r
673         }\r
674 \r
675         xLastBlockingCycleCount = xBlockingCycles;\r
676         xLastControllingCycleCount = xControllingCycles;\r
677 \r
678         return xReturn;\r
679 }\r
680 \r
681 #endif /* INCLUDE_xTaskAbortDelay == 1 */\r