]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/AbortDelay.c
Update version number to 9.0.0rc2.
[freertos] / FreeRTOS / Demo / Common / Minimal / AbortDelay.c
1 /*\r
2     FreeRTOS V9.0.0rc2 - 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_xTaskGetTaskHandle != 1 )\r
93         #error This test file uses the xTaskGetTaskHandle() API function so INCLUDE_xTaskGetTaskHandle 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 = xTaskGetTaskHandle( 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 \r
241         /* Just to remove compiler warnings. */\r
242         ( void ) pvParameters;\r
243 \r
244         xControllingTask = xTaskGetTaskHandle( pcControllingTaskName );\r
245         configASSERT( xControllingTask );\r
246 \r
247         for( ;; )\r
248         {\r
249                 /* Wait to be notified of the test that is to be performed next. */\r
250                 xTaskNotifyWait( 0, ULONG_MAX, &ulNotificationValue, portMAX_DELAY );\r
251 \r
252                 switch( ulNotificationValue )\r
253                 {\r
254                         case abtNOTIFY_WAIT_ABORTS:\r
255                                 prvTestAbortingTaskNotifyWait();\r
256                                 break;\r
257 \r
258                         case abtNOTIFY_TAKE_ABORTS:\r
259                                 prvTestAbortingTaskNotifyTake();\r
260                                 break;\r
261 \r
262                         case abtDELAY_ABORTS:\r
263                                 prvTestAbortingTaskDelay();\r
264                                 break;\r
265 \r
266                         case abtDELAY_UNTIL_ABORTS:\r
267                                 prvTestAbortingTaskDelayUntil();\r
268                                 break;\r
269 \r
270                         case abtSEMAPHORE_TAKE_ABORTS:\r
271                                 prvTestAbortingSemaphoreTake();\r
272                                 break;\r
273 \r
274                         case abtEVENT_GROUP_ABORTS:\r
275                                 prvTestAbortingEventGroupWait();\r
276                                 break;\r
277 \r
278                         case abtQUEUE_SEND_ABORTS:\r
279                                 prvTestAbortingQueueSend();\r
280                                 break;\r
281 \r
282                         default:\r
283                                 /* Should not get here. */\r
284                                 break;\r
285                 }\r
286 \r
287                 /* Let the primary task know the test is complete. */\r
288                 xTaskNotifyGive( xControllingTask );\r
289 \r
290                 /* To indicate this task is still executing. */\r
291                 xBlockingCycles++;\r
292         }\r
293 }\r
294 /*-----------------------------------------------------------*/\r
295 \r
296 static void prvTestAbortingTaskDelayUntil( void )\r
297 {\r
298 TickType_t xTimeAtStart, xLastBlockTime;\r
299 \r
300         /* Note the time before the delay so the length of the delay is known. */\r
301         xTimeAtStart = xTaskGetTickCount();\r
302 \r
303         /* Take a copy of the time as it is updated in the call to\r
304         vTaskDelayUntil() but its original value is needed to determine the actual\r
305         time spend in the Blocked state. */\r
306         xLastBlockTime = xTimeAtStart;\r
307 \r
308         /* This first delay should just time out. */\r
309         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
310         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
311 \r
312         /* This second delay should be aborted by the primary task half way\r
313         through.  Again take a copy of the time as it is updated in the call to\r
314         vTaskDelayUntil() buts its original value is needed to determine the amount\r
315         of time actually spent in the Blocked state. */\r
316         xTimeAtStart = xTaskGetTickCount();\r
317         xLastBlockTime = xTimeAtStart;\r
318         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
319         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
320 \r
321         /* As with the other tests, the third block period should not time out. */\r
322         xTimeAtStart = xTaskGetTickCount();\r
323         xLastBlockTime = xTimeAtStart;\r
324         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
325         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
326 }\r
327 /*-----------------------------------------------------------*/\r
328 \r
329 static void prvTestAbortingTaskDelay( void )\r
330 {\r
331 TickType_t xTimeAtStart;\r
332 \r
333         /* Note the time before the delay so the length of the delay is known. */\r
334         xTimeAtStart = xTaskGetTickCount();\r
335 \r
336         /* This first delay should just time out. */\r
337         vTaskDelay( xMaxBlockTime );\r
338         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
339 \r
340         /* Note the time before the delay so the length of the delay is known. */\r
341         xTimeAtStart = xTaskGetTickCount();\r
342 \r
343         /* This second delay should be aborted by the primary task half way\r
344         through. */\r
345         vTaskDelay( xMaxBlockTime );\r
346         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
347 \r
348         /* Note the time before the delay so the length of the delay is known. */\r
349         xTimeAtStart = xTaskGetTickCount();\r
350 \r
351         /* This third delay should just time out again. */\r
352         vTaskDelay( xMaxBlockTime );\r
353         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
354 }\r
355 /*-----------------------------------------------------------*/\r
356 \r
357 static void prvTestAbortingTaskNotifyTake( void )\r
358 {\r
359 TickType_t xTimeAtStart;\r
360 uint32_t ulReturn;\r
361 \r
362         /* Note the time before the delay so the length of the delay is known. */\r
363         xTimeAtStart = xTaskGetTickCount();\r
364 \r
365         /* This first delay should just time out. */\r
366         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
367         if( ulReturn != 0 )\r
368         {\r
369                 xErrorOccurred = pdTRUE;\r
370         }\r
371         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
372 \r
373         /* Note the time before the delay so the length of the delay is known. */\r
374         xTimeAtStart = xTaskGetTickCount();\r
375 \r
376         /* This second delay should be aborted by the primary task half way\r
377         through. */\r
378         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
379         if( ulReturn != 0 )\r
380         {\r
381                 xErrorOccurred = pdTRUE;\r
382         }\r
383         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
384 \r
385         /* Note the time before the delay so the length of the delay is known. */\r
386         xTimeAtStart = xTaskGetTickCount();\r
387 \r
388         /* This third delay should just time out again. */\r
389         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
390         if( ulReturn != 0 )\r
391         {\r
392                 xErrorOccurred = pdTRUE;\r
393         }\r
394         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
395 }\r
396 /*-----------------------------------------------------------*/\r
397 \r
398 static void prvTestAbortingEventGroupWait( void )\r
399 {\r
400 TickType_t xTimeAtStart;\r
401 EventGroupHandle_t xEventGroup;\r
402 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;\r
403 \r
404         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
405         {\r
406                 static StaticEventGroup_t xEventGroupBuffer;\r
407 \r
408                 /* Create the event group.  Statically allocated memory is used so the\r
409                 creation cannot fail. */\r
410                 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );\r
411         }\r
412         #else\r
413         {\r
414                 xEventGroup = xEventGroupCreate();\r
415                 configASSERT( xEventGroup );\r
416         }\r
417         #endif\r
418 \r
419         /* Note the time before the delay so the length of the delay is known. */\r
420         xTimeAtStart = xTaskGetTickCount();\r
421 \r
422         /* This first delay should just time out. */\r
423         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
424         if( xReturn != 0x00 )\r
425         {\r
426                 xErrorOccurred = pdTRUE;\r
427         }\r
428         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
429 \r
430         /* Note the time before the delay so the length of the delay is known. */\r
431         xTimeAtStart = xTaskGetTickCount();\r
432 \r
433         /* This second delay should be aborted by the primary task half way\r
434         through. */\r
435         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
436         if( xReturn != 0x00 )\r
437         {\r
438                 xErrorOccurred = pdTRUE;\r
439         }\r
440         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
441 \r
442         /* Note the time before the delay so the length of the delay is known. */\r
443         xTimeAtStart = xTaskGetTickCount();\r
444 \r
445         /* This third delay should just time out again. */\r
446         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
447         if( xReturn != 0x00 )\r
448         {\r
449                 xErrorOccurred = pdTRUE;\r
450         }\r
451         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
452 \r
453         /* Not really necessary in this case, but for completeness. */\r
454         vEventGroupDelete( xEventGroup );\r
455 }\r
456 /*-----------------------------------------------------------*/\r
457 \r
458 static void prvTestAbortingQueueSend( void )\r
459 {\r
460 TickType_t xTimeAtStart;\r
461 BaseType_t xReturn;\r
462 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;\r
463 QueueHandle_t xQueue;\r
464 uint8_t ucItemToQueue;\r
465 \r
466         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
467         {\r
468                 static StaticQueue_t xQueueBuffer;\r
469                 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];\r
470 \r
471                 /* Create the queue.  Statically allocated memory is used so the\r
472                 creation cannot fail. */\r
473                 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );\r
474         }\r
475         #else\r
476         {\r
477                 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );\r
478                 configASSERT( xQueue );\r
479         }\r
480         #endif\r
481 \r
482         /* This function tests aborting when in the blocked state waiting to send,\r
483         so the queue must be full.  There is only one space in the queue. */\r
484         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
485         if( xReturn != pdPASS )\r
486         {\r
487                 xErrorOccurred = pdTRUE;\r
488         }\r
489 \r
490         /* Note the time before the delay so the length of the delay is known. */\r
491         xTimeAtStart = xTaskGetTickCount();\r
492 \r
493         /* This first delay should just time out. */\r
494         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
495         if( xReturn != pdFALSE )\r
496         {\r
497                 xErrorOccurred = pdTRUE;\r
498         }\r
499         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
500 \r
501         /* Note the time before the delay so the length of the delay is known. */\r
502         xTimeAtStart = xTaskGetTickCount();\r
503 \r
504         /* This second delay should be aborted by the primary task half way\r
505         through. */\r
506         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
507         if( xReturn != pdFALSE )\r
508         {\r
509                 xErrorOccurred = pdTRUE;\r
510         }\r
511         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
512 \r
513         /* Note the time before the delay so the length of the delay is known. */\r
514         xTimeAtStart = xTaskGetTickCount();\r
515 \r
516         /* This third delay should just time out again. */\r
517         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
518         if( xReturn != pdFALSE )\r
519         {\r
520                 xErrorOccurred = pdTRUE;\r
521         }\r
522         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
523 \r
524         /* Not really necessary in this case, but for completeness. */\r
525         vQueueDelete( xQueue );\r
526 }\r
527 /*-----------------------------------------------------------*/\r
528 \r
529 static void prvTestAbortingSemaphoreTake( void )\r
530 {\r
531 TickType_t xTimeAtStart;\r
532 BaseType_t xReturn;\r
533 SemaphoreHandle_t xSemaphore;\r
534 \r
535         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
536         {\r
537                 static StaticSemaphore_t xSemaphoreBuffer;\r
538 \r
539                 /* Create the semaphore.  Statically allocated memory is used so the\r
540                 creation cannot fail. */\r
541                 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
542         }\r
543         #else\r
544         {\r
545                 xSemaphore = xSemaphoreCreateBinary();\r
546         }\r
547         #endif\r
548 \r
549         /* Note the time before the delay so the length of the delay is known. */\r
550         xTimeAtStart = xTaskGetTickCount();\r
551 \r
552         /* This first delay should just time out. */\r
553         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
554         if( xReturn != pdFALSE )\r
555         {\r
556                 xErrorOccurred = pdTRUE;\r
557         }\r
558         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
559 \r
560         /* Note the time before the delay so the length of the delay is known. */\r
561         xTimeAtStart = xTaskGetTickCount();\r
562 \r
563         /* This second delay should be aborted by the primary task half way\r
564         through. */\r
565         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
566         if( xReturn != pdFALSE )\r
567         {\r
568                 xErrorOccurred = pdTRUE;\r
569         }\r
570         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
571 \r
572         /* Note the time before the delay so the length of the delay is known. */\r
573         xTimeAtStart = xTaskGetTickCount();\r
574 \r
575         /* This third delay should just time out again. */\r
576         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
577         if( xReturn != pdFALSE )\r
578         {\r
579                 xErrorOccurred = pdTRUE;\r
580         }\r
581         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
582 \r
583         /* Not really necessary in this case, but for completeness. */\r
584         vSemaphoreDelete( xSemaphore );\r
585 }\r
586 /*-----------------------------------------------------------*/\r
587 \r
588 static void prvTestAbortingTaskNotifyWait( void )\r
589 {\r
590 TickType_t xTimeAtStart;\r
591 BaseType_t xReturn;\r
592 \r
593         /* Note the time before the delay so the length of the delay is known. */\r
594         xTimeAtStart = xTaskGetTickCount();\r
595 \r
596         /* This first delay should just time out. */\r
597         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
598         if( xReturn != pdFALSE )\r
599         {\r
600                 xErrorOccurred = pdTRUE;\r
601         }\r
602         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
603 \r
604         /* Note the time before the delay so the length of the delay is known. */\r
605         xTimeAtStart = xTaskGetTickCount();\r
606 \r
607         /* This second delay should be aborted by the primary task half way\r
608         through. */\r
609         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
610         if( xReturn != pdFALSE )\r
611         {\r
612                 xErrorOccurred = pdTRUE;\r
613         }\r
614         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
615 \r
616         /* Note the time before the delay so the length of the delay is known. */\r
617         xTimeAtStart = xTaskGetTickCount();\r
618 \r
619         /* This third delay should just time out again. */\r
620         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
621         if( xReturn != pdFALSE )\r
622         {\r
623                 xErrorOccurred = pdTRUE;\r
624         }\r
625         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
626 }\r
627 /*-----------------------------------------------------------*/\r
628 \r
629 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )\r
630 {\r
631 TickType_t xTimeNow, xActualBlockTime;\r
632 \r
633         xTimeNow = xTaskGetTickCount();\r
634         xActualBlockTime = xTimeNow - xStartTime;\r
635 \r
636         /* The actual block time should not be less than the expected block time. */\r
637         if( xActualBlockTime < xExpectedBlockTime )\r
638         {\r
639                 xErrorOccurred = pdTRUE;\r
640         }\r
641 \r
642         /* The actual block time can be greater than the expected block time, as it\r
643         depends on the priority of the other tasks, but it should be within an\r
644         acceptable margin. */\r
645         if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )\r
646         {\r
647                 xErrorOccurred = pdTRUE;\r
648         }\r
649 }\r
650 /*-----------------------------------------------------------*/\r
651 \r
652 BaseType_t xAreAbortDelayTestTasksStillRunning( void )\r
653 {\r
654 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;\r
655 BaseType_t xReturn = pdPASS;\r
656 \r
657         /* Have both tasks performed at least one cycle since this function was\r
658         last called? */\r
659         if( xControllingCycles == xLastControllingCycleCount )\r
660         {\r
661                 xReturn = pdFAIL;\r
662         }\r
663 \r
664         if( xBlockingCycles == xLastBlockingCycleCount )\r
665         {\r
666                 xReturn = pdFAIL;\r
667         }\r
668 \r
669         if( xErrorOccurred == pdTRUE )\r
670         {\r
671                 xReturn = pdFAIL;\r
672         }\r
673 \r
674         xLastBlockingCycleCount = xBlockingCycles;\r
675         xLastControllingCycleCount = xControllingCycles;\r
676 \r
677         return xReturn;\r
678 }\r
679 \r
680 #endif /* INCLUDE_xTaskAbortDelay == 1 */\r