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