]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/AbortDelay.c
fc4e36f4d3d921423845045c3a6ebe78a5d76ff7
[freertos] / FreeRTOS / Demo / Common / Minimal / AbortDelay.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*\r
29  * This file contains some test scenarios that ensure tasks respond correctly\r
30  * to xTaskAbortDelay() calls.  It also ensures tasks return the correct state\r
31  * of eBlocked when blocked indefinitely in both the case where a task is\r
32  * blocked on an object and when a task is blocked on a notification.\r
33  */\r
34 \r
35 /* Standard includes. */\r
36 #include "limits.h"\r
37 \r
38 /* Kernel includes. */\r
39 #include "FreeRTOS.h"\r
40 #include "task.h"\r
41 #include "queue.h"\r
42 #include "semphr.h"\r
43 #include "event_groups.h"\r
44 #include "stream_buffer.h"\r
45 \r
46 /* Demo includes. */\r
47 #include "AbortDelay.h"\r
48 \r
49 /* This file can only be used if the functionality it tests is included in the\r
50 build.  Remove the whole file if this is not the case. */\r
51 #if( INCLUDE_xTaskAbortDelay == 1 )\r
52 \r
53 #if( INCLUDE_xTaskGetHandle != 1 )\r
54         #error This test file uses the xTaskGetHandle() API function so INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h.\r
55 #endif\r
56 \r
57 /* Task priorities.  Allow these to be overridden. */\r
58 #ifndef abtCONTROLLING_PRIORITY\r
59         #define abtCONTROLLING_PRIORITY         ( configMAX_PRIORITIES - 3 )\r
60 #endif\r
61 \r
62 #ifndef abtBLOCKING_PRIORITY\r
63         #define abtBLOCKING_PRIORITY    ( configMAX_PRIORITIES - 2 )\r
64 #endif\r
65 \r
66 /* The tests that are performed. */\r
67 #define abtNOTIFY_WAIT_ABORTS           0\r
68 #define abtNOTIFY_TAKE_ABORTS           1\r
69 #define abtDELAY_ABORTS                         2\r
70 #define abtDELAY_UNTIL_ABORTS           3\r
71 #define abtSEMAPHORE_TAKE_ABORTS        4\r
72 #define abtEVENT_GROUP_ABORTS           5\r
73 #define abtQUEUE_SEND_ABORTS            6\r
74 #define abtSTREAM_BUFFER_RECEIVE        7\r
75 #define abtMAX_TESTS                            8\r
76 \r
77 /*-----------------------------------------------------------*/\r
78 \r
79 /*\r
80  * The two test tasks.  The controlling task specifies which test to executed.\r
81  * More information is provided in the comments within the tasks.\r
82  */\r
83 static void prvControllingTask( void *pvParameters );\r
84 static void prvBlockingTask( void *pvParameters );\r
85 \r
86 /*\r
87  * Test functions called by the blocking task.  Each function follows the same\r
88  * pattern, but the way the task blocks is different in each case.\r
89  *\r
90  * In each function three blocking calls are made.  The first and third\r
91  * blocking call is expected to time out, while the middle blocking call is\r
92  * expected to be aborted by the controlling task half way through the block\r
93  * time.\r
94  */\r
95 static void prvTestAbortingTaskNotifyWait( void );\r
96 static void prvTestAbortingTaskNotifyTake( void );\r
97 static void prvTestAbortingTaskDelay( void );\r
98 static void prvTestAbortingTaskDelayUntil( void );\r
99 static void prvTestAbortingSemaphoreTake( void );\r
100 static void prvTestAbortingEventGroupWait( void );\r
101 static void prvTestAbortingQueueSend( void );\r
102 static void prvTestAbortingStreamBufferReceive( void );\r
103 \r
104 /*\r
105  * Checks the amount of time a task spent in the Blocked state is within the\r
106  * expected bounds.\r
107  */\r
108 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );\r
109 \r
110 /*-----------------------------------------------------------*/\r
111 \r
112 /* Used to ensure that tasks are still executing without error. */\r
113 static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;\r
114 static volatile BaseType_t xErrorOccurred = pdFALSE;\r
115 \r
116 /* Each task needs to know the other tasks handle so they can send signals to\r
117 each other.  The handle is obtained from the task's name. */\r
118 static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";\r
119 \r
120 /* The maximum amount of time a task will block for. */\r
121 const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );\r
122 const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );\r
123 \r
124 /* The actual block time is dependent on the priority of other tasks in the\r
125 system so the actual block time might be greater than that expected, but it\r
126 should be within an acceptable upper bound. */\r
127 const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );\r
128 \r
129 /*-----------------------------------------------------------*/\r
130 \r
131 void vCreateAbortDelayTasks( void )\r
132 {\r
133         /* Create the two test tasks described above. */\r
134         xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );\r
135         xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );\r
136 }\r
137 /*-----------------------------------------------------------*/\r
138 \r
139 static void prvControllingTask( void *pvParameters )\r
140 {\r
141 TaskHandle_t xBlockingTask;\r
142 uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;\r
143 TickType_t xTimeAtStart;\r
144 const TickType_t xStartMargin = 2UL;\r
145 \r
146         /* Just to remove compiler warnings. */\r
147         ( void ) pvParameters;\r
148 \r
149         xBlockingTask = xTaskGetHandle( pcBlockingTaskName );\r
150         configASSERT( xBlockingTask );\r
151 \r
152         for( ;; )\r
153         {\r
154                 /* Tell the secondary task to perform the next test. */\r
155                 xTimeAtStart = xTaskGetTickCount();\r
156                 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );\r
157 \r
158                 /* The secondary task has a higher priority, so will now be in the\r
159                 Blocked state to wait for a maximum of xMaxBlockTime.  It expects that\r
160                 period to complete with a timeout.  It will then block for\r
161                 xMaxBlockTimeAgain, but this time it expects to the block time to abort\r
162                 half way through.  Block until it is time to send the abort to the\r
163                 secondary task.  xStartMargin is used because this task takes timing\r
164                 from the beginning of the test, whereas the blocking task takes timing\r
165                 from the entry into the Blocked state - and as the tasks run at\r
166                 different priorities, there may be some discrepancy.  Also, temporarily\r
167                 raise the priority of the controlling task to that of the blocking\r
168                 task to minimise discrepancies. */\r
169                 vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );\r
170                 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );\r
171                 if( xTaskAbortDelay( xBlockingTask ) != pdPASS )\r
172                 {\r
173                         xErrorOccurred = pdTRUE;\r
174                 }\r
175 \r
176                 /* Reset the priority to the normal controlling priority. */\r
177                 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );\r
178 \r
179                 /* Now wait to be notified that the secondary task has completed its\r
180                 test. */\r
181                 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
182 \r
183                 /* Did the entire test run for the expected time, which is two full\r
184                 block times plus the half block time caused by calling\r
185                 xTaskAbortDelay()? */\r
186                 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );\r
187 \r
188                 /* Move onto the next test. */\r
189                 ulTestToPerform++;\r
190 \r
191                 if( ulTestToPerform >= abtMAX_TESTS )\r
192                 {\r
193                         ulTestToPerform = 0;\r
194                 }\r
195 \r
196                 /* To indicate this task is still executing. */\r
197                 xControllingCycles++;\r
198         }\r
199 }\r
200 /*-----------------------------------------------------------*/\r
201 \r
202 static void prvBlockingTask( void *pvParameters )\r
203 {\r
204 TaskHandle_t xControllingTask;\r
205 uint32_t ulNotificationValue;\r
206 const uint32_t ulMax = 0xffffffffUL;\r
207 \r
208         /* Just to remove compiler warnings. */\r
209         ( void ) pvParameters;\r
210 \r
211         xControllingTask = xTaskGetHandle( pcControllingTaskName );\r
212         configASSERT( xControllingTask );\r
213 \r
214         for( ;; )\r
215         {\r
216                 /* Wait to be notified of the test that is to be performed next. */\r
217                 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );\r
218 \r
219                 switch( ulNotificationValue )\r
220                 {\r
221                         case abtNOTIFY_WAIT_ABORTS:\r
222                                 prvTestAbortingTaskNotifyWait();\r
223                                 break;\r
224 \r
225                         case abtNOTIFY_TAKE_ABORTS:\r
226                                 prvTestAbortingTaskNotifyTake();\r
227                                 break;\r
228 \r
229                         case abtDELAY_ABORTS:\r
230                                 prvTestAbortingTaskDelay();\r
231                                 break;\r
232 \r
233                         case abtDELAY_UNTIL_ABORTS:\r
234                                 prvTestAbortingTaskDelayUntil();\r
235                                 break;\r
236 \r
237                         case abtSEMAPHORE_TAKE_ABORTS:\r
238                                 prvTestAbortingSemaphoreTake();\r
239                                 break;\r
240 \r
241                         case abtEVENT_GROUP_ABORTS:\r
242                                 prvTestAbortingEventGroupWait();\r
243                                 break;\r
244 \r
245                         case abtQUEUE_SEND_ABORTS:\r
246                                 prvTestAbortingQueueSend();\r
247                                 break;\r
248 \r
249                         case abtSTREAM_BUFFER_RECEIVE:\r
250                                 prvTestAbortingStreamBufferReceive();\r
251                                 break;\r
252 \r
253                         default:\r
254                                 /* Should not get here. */\r
255                                 break;\r
256                 }\r
257 \r
258                 /* Let the primary task know the test is complete. */\r
259                 xTaskNotifyGive( xControllingTask );\r
260 \r
261                 /* To indicate this task is still executing. */\r
262                 xBlockingCycles++;\r
263         }\r
264 }\r
265 /*-----------------------------------------------------------*/\r
266 \r
267 static void prvTestAbortingTaskDelayUntil( void )\r
268 {\r
269 TickType_t xTimeAtStart, xLastBlockTime;\r
270 \r
271         /* Note the time before the delay so the length of the delay is known. */\r
272         xTimeAtStart = xTaskGetTickCount();\r
273 \r
274         /* Take a copy of the time as it is updated in the call to\r
275         vTaskDelayUntil() but its original value is needed to determine the actual\r
276         time spend in the Blocked state. */\r
277         xLastBlockTime = xTimeAtStart;\r
278 \r
279         /* This first delay should just time out. */\r
280         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
281         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
282 \r
283         /* This second delay should be aborted by the primary task half way\r
284         through.  Again take a copy of the time as it is updated in the call to\r
285         vTaskDelayUntil() buts its original value is needed to determine the amount\r
286         of time actually spent in the Blocked state. */\r
287         xTimeAtStart = xTaskGetTickCount();\r
288         xLastBlockTime = xTimeAtStart;\r
289         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
290         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
291 \r
292         /* As with the other tests, the third block period should not time out. */\r
293         xTimeAtStart = xTaskGetTickCount();\r
294         xLastBlockTime = xTimeAtStart;\r
295         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
296         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
297 }\r
298 /*-----------------------------------------------------------*/\r
299 \r
300 static void prvTestAbortingTaskDelay( void )\r
301 {\r
302 TickType_t xTimeAtStart;\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         /* This first delay should just time out. */\r
308         vTaskDelay( xMaxBlockTime );\r
309         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
310 \r
311         /* Note the time before the delay so the length of the delay is known. */\r
312         xTimeAtStart = xTaskGetTickCount();\r
313 \r
314         /* This second delay should be aborted by the primary task half way\r
315         through. */\r
316         vTaskDelay( xMaxBlockTime );\r
317         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
318 \r
319         /* Note the time before the delay so the length of the delay is known. */\r
320         xTimeAtStart = xTaskGetTickCount();\r
321 \r
322         /* This third delay should just time out again. */\r
323         vTaskDelay( xMaxBlockTime );\r
324         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
325 }\r
326 /*-----------------------------------------------------------*/\r
327 \r
328 static void prvTestAbortingTaskNotifyTake( void )\r
329 {\r
330 TickType_t xTimeAtStart;\r
331 uint32_t ulReturn;\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         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
338         if( ulReturn != 0 )\r
339         {\r
340                 xErrorOccurred = pdTRUE;\r
341         }\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         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
350         if( ulReturn != 0 )\r
351         {\r
352                 xErrorOccurred = pdTRUE;\r
353         }\r
354         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
355 \r
356         /* Note the time before the delay so the length of the delay is known. */\r
357         xTimeAtStart = xTaskGetTickCount();\r
358 \r
359         /* This third delay should just time out again. */\r
360         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
361         if( ulReturn != 0 )\r
362         {\r
363                 xErrorOccurred = pdTRUE;\r
364         }\r
365         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
366 }\r
367 /*-----------------------------------------------------------*/\r
368 \r
369 static void prvTestAbortingEventGroupWait( void )\r
370 {\r
371 TickType_t xTimeAtStart;\r
372 EventGroupHandle_t xEventGroup;\r
373 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;\r
374 \r
375         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
376         {\r
377                 static StaticEventGroup_t xEventGroupBuffer;\r
378 \r
379                 /* Create the event group.  Statically allocated memory is used so the\r
380                 creation cannot fail. */\r
381                 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );\r
382         }\r
383         #else\r
384         {\r
385                 xEventGroup = xEventGroupCreate();\r
386                 configASSERT( xEventGroup );\r
387         }\r
388         #endif\r
389 \r
390         /* Note the time before the delay so the length of the delay is known. */\r
391         xTimeAtStart = xTaskGetTickCount();\r
392 \r
393         /* This first delay should just time out. */\r
394         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
395         if( xReturn != 0x00 )\r
396         {\r
397                 xErrorOccurred = pdTRUE;\r
398         }\r
399         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
400 \r
401         /* Note the time before the delay so the length of the delay is known. */\r
402         xTimeAtStart = xTaskGetTickCount();\r
403 \r
404         /* This second delay should be aborted by the primary task half way\r
405         through. */\r
406         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
407         if( xReturn != 0x00 )\r
408         {\r
409                 xErrorOccurred = pdTRUE;\r
410         }\r
411         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
412 \r
413         /* Note the time before the delay so the length of the delay is known. */\r
414         xTimeAtStart = xTaskGetTickCount();\r
415 \r
416         /* This third delay should just time out again. */\r
417         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
418         if( xReturn != 0x00 )\r
419         {\r
420                 xErrorOccurred = pdTRUE;\r
421         }\r
422         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
423 \r
424         /* Not really necessary in this case, but for completeness. */\r
425         vEventGroupDelete( xEventGroup );\r
426 }\r
427 /*-----------------------------------------------------------*/\r
428 \r
429 static void prvTestAbortingStreamBufferReceive( void )\r
430 {\r
431 TickType_t xTimeAtStart;\r
432 StreamBufferHandle_t xStreamBuffer;\r
433 size_t xReturn;\r
434 const size_t xTriggerLevelBytes = ( size_t ) 1;\r
435 uint8_t uxRxData;\r
436 \r
437         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
438         {\r
439                 /* Defines the memory that will actually hold the streams within the\r
440                 stream buffer. */\r
441                 static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];\r
442 \r
443                 /* The variable used to hold the stream buffer structure. */\r
444                 StaticStreamBuffer_t xStreamBufferStruct;\r
445 \r
446 \r
447                 xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),\r
448                                                                                                    xTriggerLevelBytes,\r
449                                                                                                    ucStorageBuffer,\r
450                                                                                                    &xStreamBufferStruct );\r
451         }\r
452         #else\r
453         {\r
454                 xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );\r
455                 configASSERT( xStreamBuffer );\r
456         }\r
457         #endif\r
458 \r
459         /* Note the time before the delay so the length of the delay is known. */\r
460         xTimeAtStart = xTaskGetTickCount();\r
461 \r
462         /* This first delay should just time out. */\r
463         xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );\r
464         if( xReturn != 0x00 )\r
465         {\r
466                 xErrorOccurred = pdTRUE;\r
467         }\r
468         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
469 \r
470         /* Note the time before the delay so the length of the delay is known. */\r
471         xTimeAtStart = xTaskGetTickCount();\r
472 \r
473         /* This second delay should be aborted by the primary task half way\r
474         through xMaxBlockTime. */\r
475         xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );\r
476         if( xReturn != 0x00 )\r
477         {\r
478                 xErrorOccurred = pdTRUE;\r
479         }\r
480         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
481 \r
482         /* Note the time before the delay so the length of the delay is known. */\r
483         xTimeAtStart = xTaskGetTickCount();\r
484 \r
485         /* This third delay should just time out again. */\r
486         xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );\r
487         if( xReturn != 0x00 )\r
488         {\r
489                 xErrorOccurred = pdTRUE;\r
490         }\r
491         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
492 \r
493         /* Not really necessary in this case, but for completeness. */\r
494         vStreamBufferDelete( xStreamBuffer );\r
495 }\r
496 /*-----------------------------------------------------------*/\r
497 \r
498 static void prvTestAbortingQueueSend( void )\r
499 {\r
500 TickType_t xTimeAtStart;\r
501 BaseType_t xReturn;\r
502 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;\r
503 QueueHandle_t xQueue;\r
504 uint8_t ucItemToQueue;\r
505 \r
506         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
507         {\r
508                 static StaticQueue_t xQueueBuffer;\r
509                 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];\r
510 \r
511                 /* Create the queue.  Statically allocated memory is used so the\r
512                 creation cannot fail. */\r
513                 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );\r
514         }\r
515         #else\r
516         {\r
517                 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );\r
518                 configASSERT( xQueue );\r
519         }\r
520         #endif\r
521 \r
522         /* This function tests aborting when in the blocked state waiting to send,\r
523         so the queue must be full.  There is only one space in the queue. */\r
524         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
525         if( xReturn != pdPASS )\r
526         {\r
527                 xErrorOccurred = pdTRUE;\r
528         }\r
529 \r
530         /* Note the time before the delay so the length of the delay is known. */\r
531         xTimeAtStart = xTaskGetTickCount();\r
532 \r
533         /* This first delay should just time out. */\r
534         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
535         if( xReturn != pdFALSE )\r
536         {\r
537                 xErrorOccurred = pdTRUE;\r
538         }\r
539         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
540 \r
541         /* Note the time before the delay so the length of the delay is known. */\r
542         xTimeAtStart = xTaskGetTickCount();\r
543 \r
544         /* This second delay should be aborted by the primary task half way\r
545         through. */\r
546         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
547         if( xReturn != pdFALSE )\r
548         {\r
549                 xErrorOccurred = pdTRUE;\r
550         }\r
551         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\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 third delay should just time out again. */\r
557         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
558         if( xReturn != pdFALSE )\r
559         {\r
560                 xErrorOccurred = pdTRUE;\r
561         }\r
562         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
563 \r
564         /* Not really necessary in this case, but for completeness. */\r
565         vQueueDelete( xQueue );\r
566 }\r
567 /*-----------------------------------------------------------*/\r
568 \r
569 static void prvTestAbortingSemaphoreTake( void )\r
570 {\r
571 TickType_t xTimeAtStart;\r
572 BaseType_t xReturn;\r
573 SemaphoreHandle_t xSemaphore;\r
574 \r
575         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
576         {\r
577                 static StaticSemaphore_t xSemaphoreBuffer;\r
578 \r
579                 /* Create the semaphore.  Statically allocated memory is used so the\r
580                 creation cannot fail. */\r
581                 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
582         }\r
583         #else\r
584         {\r
585                 xSemaphore = xSemaphoreCreateBinary();\r
586         }\r
587         #endif\r
588 \r
589         /* Note the time before the delay so the length of the delay is known. */\r
590         xTimeAtStart = xTaskGetTickCount();\r
591 \r
592         /* This first delay should just time out. */\r
593         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
594         if( xReturn != pdFALSE )\r
595         {\r
596                 xErrorOccurred = pdTRUE;\r
597         }\r
598         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
599 \r
600         /* Note the time before the delay so the length of the delay is known. */\r
601         xTimeAtStart = xTaskGetTickCount();\r
602 \r
603         /* This second delay should be aborted by the primary task half way\r
604         through xMaxBlockTime. */\r
605         xReturn = xSemaphoreTake( xSemaphore, portMAX_DELAY );\r
606         if( xReturn != pdFALSE )\r
607         {\r
608                 xErrorOccurred = pdTRUE;\r
609         }\r
610         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
611 \r
612         /* Note the time before the delay so the length of the delay is known. */\r
613         xTimeAtStart = xTaskGetTickCount();\r
614 \r
615         /* This third delay should just time out again. */\r
616         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
617         if( xReturn != pdFALSE )\r
618         {\r
619                 xErrorOccurred = pdTRUE;\r
620         }\r
621         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
622 \r
623         /* Not really necessary in this case, but for completeness. */\r
624         vSemaphoreDelete( xSemaphore );\r
625 }\r
626 /*-----------------------------------------------------------*/\r
627 \r
628 static void prvTestAbortingTaskNotifyWait( void )\r
629 {\r
630 TickType_t xTimeAtStart;\r
631 BaseType_t xReturn;\r
632 \r
633         /* Note the time before the delay so the length of the delay is known. */\r
634         xTimeAtStart = xTaskGetTickCount();\r
635 \r
636         /* This first delay should just time out. */\r
637         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
638         if( xReturn != pdFALSE )\r
639         {\r
640                 xErrorOccurred = pdTRUE;\r
641         }\r
642         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
643 \r
644         /* Note the time before the delay so the length of the delay is known. */\r
645         xTimeAtStart = xTaskGetTickCount();\r
646 \r
647         /* This second delay should be aborted by the primary task half way\r
648         through xMaxBlockTime. */\r
649         xReturn = xTaskNotifyWait( 0, 0, NULL, portMAX_DELAY );\r
650         if( xReturn != pdFALSE )\r
651         {\r
652                 xErrorOccurred = pdTRUE;\r
653         }\r
654         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
655 \r
656         /* Note the time before the delay so the length of the delay is known. */\r
657         xTimeAtStart = xTaskGetTickCount();\r
658 \r
659         /* This third delay should just time out again. */\r
660         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
661         if( xReturn != pdFALSE )\r
662         {\r
663                 xErrorOccurred = pdTRUE;\r
664         }\r
665         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
666 }\r
667 /*-----------------------------------------------------------*/\r
668 \r
669 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )\r
670 {\r
671 TickType_t xTimeNow, xActualBlockTime;\r
672 \r
673         xTimeNow = xTaskGetTickCount();\r
674         xActualBlockTime = xTimeNow - xStartTime;\r
675 \r
676         /* The actual block time should not be less than the expected block time. */\r
677         if( xActualBlockTime < xExpectedBlockTime )\r
678         {\r
679                 xErrorOccurred = pdTRUE;\r
680         }\r
681 \r
682         /* The actual block time can be greater than the expected block time, as it\r
683         depends on the priority of the other tasks, but it should be within an\r
684         acceptable margin. */\r
685         if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )\r
686         {\r
687                 xErrorOccurred = pdTRUE;\r
688         }\r
689 }\r
690 /*-----------------------------------------------------------*/\r
691 \r
692 BaseType_t xAreAbortDelayTestTasksStillRunning( void )\r
693 {\r
694 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;\r
695 BaseType_t xReturn = pdPASS;\r
696 \r
697         /* Have both tasks performed at least one cycle since this function was\r
698         last called? */\r
699         if( xControllingCycles == xLastControllingCycleCount )\r
700         {\r
701                 xReturn = pdFAIL;\r
702         }\r
703 \r
704         if( xBlockingCycles == xLastBlockingCycleCount )\r
705         {\r
706                 xReturn = pdFAIL;\r
707         }\r
708 \r
709         if( xErrorOccurred == pdTRUE )\r
710         {\r
711                 xReturn = pdFAIL;\r
712         }\r
713 \r
714         xLastBlockingCycleCount = xBlockingCycles;\r
715         xLastControllingCycleCount = xControllingCycles;\r
716 \r
717         return xReturn;\r
718 }\r
719 \r
720 #endif /* INCLUDE_xTaskAbortDelay == 1 */\r