]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/AbortDelay.c
Update libraries and sundry check-ins ready for the V10.3.0 kernel release.
[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  * Performs a few tests to cover code paths not otherwise covered by the continuous\r
106  * tests.\r
107  */\r
108 static void prvPerformSingleTaskTests( void );\r
109 \r
110 /*\r
111  * Checks the amount of time a task spent in the Blocked state is within the\r
112  * expected bounds.\r
113  */\r
114 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );\r
115 \r
116 /*-----------------------------------------------------------*/\r
117 \r
118 /* Used to ensure that tasks are still executing without error. */\r
119 static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;\r
120 static volatile BaseType_t xErrorOccurred = pdFALSE;\r
121 \r
122 /* Each task needs to know the other tasks handle so they can send signals to\r
123 each other.  The handle is obtained from the task's name. */\r
124 static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";\r
125 \r
126 /* The maximum amount of time a task will block for. */\r
127 const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );\r
128 const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );\r
129 \r
130 /* The actual block time is dependent on the priority of other tasks in the\r
131 system so the actual block time might be greater than that expected, but it\r
132 should be within an acceptable upper bound. */\r
133 const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );\r
134 \r
135 /*-----------------------------------------------------------*/\r
136 \r
137 void vCreateAbortDelayTasks( void )\r
138 {\r
139         /* Create the two test tasks described above. */\r
140         xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );\r
141         xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );\r
142 }\r
143 /*-----------------------------------------------------------*/\r
144 \r
145 static void prvControllingTask( void *pvParameters )\r
146 {\r
147 TaskHandle_t xBlockingTask;\r
148 uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;\r
149 TickType_t xTimeAtStart;\r
150 const TickType_t xStartMargin = 2UL;\r
151 \r
152         /* Just to remove compiler warnings. */\r
153         ( void ) pvParameters;\r
154 \r
155         xBlockingTask = xTaskGetHandle( pcBlockingTaskName );\r
156         configASSERT( xBlockingTask );\r
157 \r
158         for( ;; )\r
159         {\r
160                 /* Tell the secondary task to perform the next test. */\r
161                 xTimeAtStart = xTaskGetTickCount();\r
162                 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );\r
163 \r
164                 /* The secondary task has a higher priority, so will now be in the\r
165                 Blocked state to wait for a maximum of xMaxBlockTime.  It expects that\r
166                 period to complete with a timeout.  It will then block for\r
167                 xMaxBlockTimeAgain, but this time it expects to the block time to abort\r
168                 half way through.  Block until it is time to send the abort to the\r
169                 secondary task.  xStartMargin is used because this task takes timing\r
170                 from the beginning of the test, whereas the blocking task takes timing\r
171                 from the entry into the Blocked state - and as the tasks run at\r
172                 different priorities, there may be some discrepancy.  Also, temporarily\r
173                 raise the priority of the controlling task to that of the blocking\r
174                 task to minimise discrepancies. */\r
175                 vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );\r
176                 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );\r
177                 if( xTaskAbortDelay( xBlockingTask ) != pdPASS )\r
178                 {\r
179                         xErrorOccurred = pdTRUE;\r
180                 }\r
181 \r
182                 /* Reset the priority to the normal controlling priority. */\r
183                 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );\r
184 \r
185                 /* Now wait to be notified that the secondary task has completed its\r
186                 test. */\r
187                 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
188 \r
189                 /* Did the entire test run for the expected time, which is two full\r
190                 block times plus the half block time caused by calling\r
191                 xTaskAbortDelay()? */\r
192                 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );\r
193 \r
194                 /* Move onto the next test. */\r
195                 ulTestToPerform++;\r
196 \r
197                 if( ulTestToPerform >= abtMAX_TESTS )\r
198                 {\r
199                         ulTestToPerform = 0;\r
200                 }\r
201 \r
202                 /* To indicate this task is still executing. */\r
203                 xControllingCycles++;\r
204         }\r
205 }\r
206 /*-----------------------------------------------------------*/\r
207 \r
208 static void prvBlockingTask( void *pvParameters )\r
209 {\r
210 TaskHandle_t xControllingTask;\r
211 uint32_t ulNotificationValue;\r
212 const uint32_t ulMax = 0xffffffffUL;\r
213 \r
214         /* Just to remove compiler warnings. */\r
215         ( void ) pvParameters;\r
216 \r
217         /* Start by performing a few tests to cover code not exercised in the loops\r
218         below. */\r
219         prvPerformSingleTaskTests();\r
220 \r
221         xControllingTask = xTaskGetHandle( pcControllingTaskName );\r
222         configASSERT( xControllingTask );\r
223 \r
224         for( ;; )\r
225         {\r
226                 /* Wait to be notified of the test that is to be performed next. */\r
227                 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );\r
228 \r
229                 switch( ulNotificationValue )\r
230                 {\r
231                         case abtNOTIFY_WAIT_ABORTS:\r
232                                 prvTestAbortingTaskNotifyWait();\r
233                                 break;\r
234 \r
235                         case abtNOTIFY_TAKE_ABORTS:\r
236                                 prvTestAbortingTaskNotifyTake();\r
237                                 break;\r
238 \r
239                         case abtDELAY_ABORTS:\r
240                                 prvTestAbortingTaskDelay();\r
241                                 break;\r
242 \r
243                         case abtDELAY_UNTIL_ABORTS:\r
244                                 prvTestAbortingTaskDelayUntil();\r
245                                 break;\r
246 \r
247                         case abtSEMAPHORE_TAKE_ABORTS:\r
248                                 prvTestAbortingSemaphoreTake();\r
249                                 break;\r
250 \r
251                         case abtEVENT_GROUP_ABORTS:\r
252                                 prvTestAbortingEventGroupWait();\r
253                                 break;\r
254 \r
255                         case abtQUEUE_SEND_ABORTS:\r
256                                 prvTestAbortingQueueSend();\r
257                                 break;\r
258 \r
259                         case abtSTREAM_BUFFER_RECEIVE:\r
260                                 prvTestAbortingStreamBufferReceive();\r
261                                 break;\r
262 \r
263                         default:\r
264                                 /* Should not get here. */\r
265                                 break;\r
266                 }\r
267 \r
268                 /* Let the primary task know the test is complete. */\r
269                 xTaskNotifyGive( xControllingTask );\r
270 \r
271                 /* To indicate this task is still executing. */\r
272                 xBlockingCycles++;\r
273         }\r
274 }\r
275 /*-----------------------------------------------------------*/\r
276 \r
277 static void prvPerformSingleTaskTests( void )\r
278 {\r
279 TaskHandle_t xThisTask;\r
280 BaseType_t xReturned;\r
281 \r
282         /* Try unblocking this task using both the task and ISR versions of the API -\r
283         both should return false as this task is not blocked. */\r
284         xThisTask = xTaskGetCurrentTaskHandle();\r
285 \r
286         xReturned = xTaskAbortDelay( xThisTask );\r
287         if( xReturned != pdFALSE )\r
288         {\r
289                 xErrorOccurred = pdTRUE;\r
290         }\r
291 }\r
292 /*-----------------------------------------------------------*/\r
293 \r
294 static void prvTestAbortingTaskDelayUntil( void )\r
295 {\r
296 TickType_t xTimeAtStart, xLastBlockTime;\r
297 \r
298         /* Note the time before the delay so the length of the delay is known. */\r
299         xTimeAtStart = xTaskGetTickCount();\r
300 \r
301         /* Take a copy of the time as it is updated in the call to\r
302         vTaskDelayUntil() but its original value is needed to determine the actual\r
303         time spend in the Blocked state. */\r
304         xLastBlockTime = xTimeAtStart;\r
305 \r
306         /* This first delay should just time out. */\r
307         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
308         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
309 \r
310         /* This second delay should be aborted by the primary task half way\r
311         through.  Again take a copy of the time as it is updated in the call to\r
312         vTaskDelayUntil() buts its original value is needed to determine the amount\r
313         of time actually spent in the Blocked state. */\r
314         xTimeAtStart = xTaskGetTickCount();\r
315         xLastBlockTime = xTimeAtStart;\r
316         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
317         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
318 \r
319         /* As with the other tests, the third block period should not time out. */\r
320         xTimeAtStart = xTaskGetTickCount();\r
321         xLastBlockTime = xTimeAtStart;\r
322         vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );\r
323         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
324 }\r
325 /*-----------------------------------------------------------*/\r
326 \r
327 static void prvTestAbortingTaskDelay( void )\r
328 {\r
329 TickType_t xTimeAtStart;\r
330 \r
331         /* Note the time before the delay so the length of the delay is known. */\r
332         xTimeAtStart = xTaskGetTickCount();\r
333 \r
334         /* This first delay should just time out. */\r
335         vTaskDelay( xMaxBlockTime );\r
336         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
337 \r
338         /* Note the time before the delay so the length of the delay is known. */\r
339         xTimeAtStart = xTaskGetTickCount();\r
340 \r
341         /* This second delay should be aborted by the primary task half way\r
342         through. */\r
343         vTaskDelay( xMaxBlockTime );\r
344         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
345 \r
346         /* Note the time before the delay so the length of the delay is known. */\r
347         xTimeAtStart = xTaskGetTickCount();\r
348 \r
349         /* This third delay should just time out again. */\r
350         vTaskDelay( xMaxBlockTime );\r
351         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
352 }\r
353 /*-----------------------------------------------------------*/\r
354 \r
355 static void prvTestAbortingTaskNotifyTake( void )\r
356 {\r
357 TickType_t xTimeAtStart;\r
358 uint32_t ulReturn;\r
359 \r
360         /* Note the time before the delay so the length of the delay is known. */\r
361         xTimeAtStart = xTaskGetTickCount();\r
362 \r
363         /* This first delay should just time out. */\r
364         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
365         if( ulReturn != 0 )\r
366         {\r
367                 xErrorOccurred = pdTRUE;\r
368         }\r
369         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
370 \r
371         /* Note the time before the delay so the length of the delay is known. */\r
372         xTimeAtStart = xTaskGetTickCount();\r
373 \r
374         /* This second delay should be aborted by the primary task half way\r
375         through. */\r
376         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
377         if( ulReturn != 0 )\r
378         {\r
379                 xErrorOccurred = pdTRUE;\r
380         }\r
381         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
382 \r
383         /* Note the time before the delay so the length of the delay is known. */\r
384         xTimeAtStart = xTaskGetTickCount();\r
385 \r
386         /* This third delay should just time out again. */\r
387         ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );\r
388         if( ulReturn != 0 )\r
389         {\r
390                 xErrorOccurred = pdTRUE;\r
391         }\r
392         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
393 }\r
394 /*-----------------------------------------------------------*/\r
395 \r
396 static void prvTestAbortingEventGroupWait( void )\r
397 {\r
398 TickType_t xTimeAtStart;\r
399 EventGroupHandle_t xEventGroup;\r
400 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;\r
401 \r
402         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
403         {\r
404                 static StaticEventGroup_t xEventGroupBuffer;\r
405 \r
406                 /* Create the event group.  Statically allocated memory is used so the\r
407                 creation cannot fail. */\r
408                 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );\r
409         }\r
410         #else\r
411         {\r
412                 xEventGroup = xEventGroupCreate();\r
413                 configASSERT( xEventGroup );\r
414         }\r
415         #endif\r
416 \r
417         /* Note the time before the delay so the length of the delay is known. */\r
418         xTimeAtStart = xTaskGetTickCount();\r
419 \r
420         /* This first delay should just time out. */\r
421         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
422         if( xReturn != 0x00 )\r
423         {\r
424                 xErrorOccurred = pdTRUE;\r
425         }\r
426         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
427 \r
428         /* Note the time before the delay so the length of the delay is known. */\r
429         xTimeAtStart = xTaskGetTickCount();\r
430 \r
431         /* This second delay should be aborted by the primary task half way\r
432         through. */\r
433         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
434         if( xReturn != 0x00 )\r
435         {\r
436                 xErrorOccurred = pdTRUE;\r
437         }\r
438         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
439 \r
440         /* Note the time before the delay so the length of the delay is known. */\r
441         xTimeAtStart = xTaskGetTickCount();\r
442 \r
443         /* This third delay should just time out again. */\r
444         xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );\r
445         if( xReturn != 0x00 )\r
446         {\r
447                 xErrorOccurred = pdTRUE;\r
448         }\r
449         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
450 \r
451         /* Not really necessary in this case, but for completeness. */\r
452         vEventGroupDelete( xEventGroup );\r
453 }\r
454 /*-----------------------------------------------------------*/\r
455 \r
456 static void prvTestAbortingStreamBufferReceive( void )\r
457 {\r
458 TickType_t xTimeAtStart;\r
459 StreamBufferHandle_t xStreamBuffer;\r
460 size_t xReturn;\r
461 const size_t xTriggerLevelBytes = ( size_t ) 1;\r
462 uint8_t uxRxData;\r
463 \r
464         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
465         {\r
466                 /* Defines the memory that will actually hold the streams within the\r
467                 stream buffer. */\r
468                 static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];\r
469 \r
470                 /* The variable used to hold the stream buffer structure. */\r
471                 StaticStreamBuffer_t xStreamBufferStruct;\r
472 \r
473 \r
474                 xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),\r
475                                                                                                    xTriggerLevelBytes,\r
476                                                                                                    ucStorageBuffer,\r
477                                                                                                    &xStreamBufferStruct );\r
478         }\r
479         #else\r
480         {\r
481                 xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );\r
482                 configASSERT( xStreamBuffer );\r
483         }\r
484         #endif\r
485 \r
486         /* Note the time before the delay so the length of the delay is known. */\r
487         xTimeAtStart = xTaskGetTickCount();\r
488 \r
489         /* This first delay should just time out. */\r
490         xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );\r
491         if( xReturn != 0x00 )\r
492         {\r
493                 xErrorOccurred = pdTRUE;\r
494         }\r
495         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
496 \r
497         /* Note the time before the delay so the length of the delay is known. */\r
498         xTimeAtStart = xTaskGetTickCount();\r
499 \r
500         /* This second delay should be aborted by the primary task half way\r
501         through xMaxBlockTime. */\r
502         xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );\r
503         if( xReturn != 0x00 )\r
504         {\r
505                 xErrorOccurred = pdTRUE;\r
506         }\r
507         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
508 \r
509         /* Note the time before the delay so the length of the delay is known. */\r
510         xTimeAtStart = xTaskGetTickCount();\r
511 \r
512         /* This third delay should just time out again. */\r
513         xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );\r
514         if( xReturn != 0x00 )\r
515         {\r
516                 xErrorOccurred = pdTRUE;\r
517         }\r
518         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
519 \r
520         /* Not really necessary in this case, but for completeness. */\r
521         vStreamBufferDelete( xStreamBuffer );\r
522 }\r
523 /*-----------------------------------------------------------*/\r
524 \r
525 static void prvTestAbortingQueueSend( void )\r
526 {\r
527 TickType_t xTimeAtStart;\r
528 BaseType_t xReturn;\r
529 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;\r
530 QueueHandle_t xQueue;\r
531 uint8_t ucItemToQueue;\r
532 \r
533         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
534         {\r
535                 static StaticQueue_t xQueueBuffer;\r
536                 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];\r
537 \r
538                 /* Create the queue.  Statically allocated memory is used so the\r
539                 creation cannot fail. */\r
540                 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );\r
541         }\r
542         #else\r
543         {\r
544                 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );\r
545                 configASSERT( xQueue );\r
546         }\r
547         #endif\r
548 \r
549         /* This function tests aborting when in the blocked state waiting to send,\r
550         so the queue must be full.  There is only one space in the queue. */\r
551         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
552         if( xReturn != pdPASS )\r
553         {\r
554                 xErrorOccurred = pdTRUE;\r
555         }\r
556 \r
557         /* Note the time before the delay so the length of the delay is known. */\r
558         xTimeAtStart = xTaskGetTickCount();\r
559 \r
560         /* This first delay should just time out. */\r
561         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
562         if( xReturn != pdFALSE )\r
563         {\r
564                 xErrorOccurred = pdTRUE;\r
565         }\r
566         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
567 \r
568         /* Note the time before the delay so the length of the delay is known. */\r
569         xTimeAtStart = xTaskGetTickCount();\r
570 \r
571         /* This second delay should be aborted by the primary task half way\r
572         through. */\r
573         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
574         if( xReturn != pdFALSE )\r
575         {\r
576                 xErrorOccurred = pdTRUE;\r
577         }\r
578         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
579 \r
580         /* Note the time before the delay so the length of the delay is known. */\r
581         xTimeAtStart = xTaskGetTickCount();\r
582 \r
583         /* This third delay should just time out again. */\r
584         xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );\r
585         if( xReturn != pdFALSE )\r
586         {\r
587                 xErrorOccurred = pdTRUE;\r
588         }\r
589         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
590 \r
591         /* Not really necessary in this case, but for completeness. */\r
592         vQueueDelete( xQueue );\r
593 }\r
594 /*-----------------------------------------------------------*/\r
595 \r
596 static void prvTestAbortingSemaphoreTake( void )\r
597 {\r
598 TickType_t xTimeAtStart;\r
599 BaseType_t xReturn;\r
600 SemaphoreHandle_t xSemaphore;\r
601 \r
602         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
603         {\r
604                 static StaticSemaphore_t xSemaphoreBuffer;\r
605 \r
606                 /* Create the semaphore.  Statically allocated memory is used so the\r
607                 creation cannot fail. */\r
608                 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
609         }\r
610         #else\r
611         {\r
612                 xSemaphore = xSemaphoreCreateBinary();\r
613         }\r
614         #endif\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 first delay should just time out. */\r
620         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
621         if( xReturn != pdFALSE )\r
622         {\r
623                 xErrorOccurred = pdTRUE;\r
624         }\r
625         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
626 \r
627         /* Note the time before the delay so the length of the delay is known. */\r
628         xTimeAtStart = xTaskGetTickCount();\r
629 \r
630         /* This second delay should be aborted by the primary task half way\r
631         through xMaxBlockTime. */\r
632         xReturn = xSemaphoreTake( xSemaphore, portMAX_DELAY );\r
633         if( xReturn != pdFALSE )\r
634         {\r
635                 xErrorOccurred = pdTRUE;\r
636         }\r
637         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
638 \r
639         /* Note the time before the delay so the length of the delay is known. */\r
640         xTimeAtStart = xTaskGetTickCount();\r
641 \r
642         /* This third delay should just time out again. */\r
643         xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );\r
644         if( xReturn != pdFALSE )\r
645         {\r
646                 xErrorOccurred = pdTRUE;\r
647         }\r
648         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
649 \r
650         /* Not really necessary in this case, but for completeness. */\r
651         vSemaphoreDelete( xSemaphore );\r
652 }\r
653 /*-----------------------------------------------------------*/\r
654 \r
655 static void prvTestAbortingTaskNotifyWait( void )\r
656 {\r
657 TickType_t xTimeAtStart;\r
658 BaseType_t xReturn;\r
659 \r
660         /* Note the time before the delay so the length of the delay is known. */\r
661         xTimeAtStart = xTaskGetTickCount();\r
662 \r
663         /* This first delay should just time out. */\r
664         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
665         if( xReturn != pdFALSE )\r
666         {\r
667                 xErrorOccurred = pdTRUE;\r
668         }\r
669         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
670 \r
671         /* Note the time before the delay so the length of the delay is known. */\r
672         xTimeAtStart = xTaskGetTickCount();\r
673 \r
674         /* This second delay should be aborted by the primary task half way\r
675         through xMaxBlockTime. */\r
676         xReturn = xTaskNotifyWait( 0, 0, NULL, portMAX_DELAY );\r
677         if( xReturn != pdFALSE )\r
678         {\r
679                 xErrorOccurred = pdTRUE;\r
680         }\r
681         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );\r
682 \r
683         /* Note the time before the delay so the length of the delay is known. */\r
684         xTimeAtStart = xTaskGetTickCount();\r
685 \r
686         /* This third delay should just time out again. */\r
687         xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );\r
688         if( xReturn != pdFALSE )\r
689         {\r
690                 xErrorOccurred = pdTRUE;\r
691         }\r
692         prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );\r
693 }\r
694 /*-----------------------------------------------------------*/\r
695 \r
696 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )\r
697 {\r
698 TickType_t xTimeNow, xActualBlockTime;\r
699 \r
700         xTimeNow = xTaskGetTickCount();\r
701         xActualBlockTime = xTimeNow - xStartTime;\r
702 \r
703         /* The actual block time should not be less than the expected block time. */\r
704         if( xActualBlockTime < xExpectedBlockTime )\r
705         {\r
706                 xErrorOccurred = pdTRUE;\r
707         }\r
708 \r
709         /* The actual block time can be greater than the expected block time, as it\r
710         depends on the priority of the other tasks, but it should be within an\r
711         acceptable margin. */\r
712         if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )\r
713         {\r
714                 xErrorOccurred = pdTRUE;\r
715         }\r
716 }\r
717 /*-----------------------------------------------------------*/\r
718 \r
719 BaseType_t xAreAbortDelayTestTasksStillRunning( void )\r
720 {\r
721 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;\r
722 BaseType_t xReturn = pdPASS;\r
723 \r
724         /* Have both tasks performed at least one cycle since this function was\r
725         last called? */\r
726         if( xControllingCycles == xLastControllingCycleCount )\r
727         {\r
728                 xReturn = pdFAIL;\r
729         }\r
730 \r
731         if( xBlockingCycles == xLastBlockingCycleCount )\r
732         {\r
733                 xReturn = pdFAIL;\r
734         }\r
735 \r
736         if( xErrorOccurred == pdTRUE )\r
737         {\r
738                 xReturn = pdFAIL;\r
739         }\r
740 \r
741         xLastBlockingCycleCount = xBlockingCycles;\r
742         xLastControllingCycleCount = xControllingCycles;\r
743 \r
744         return xReturn;\r
745 }\r
746 \r
747 #endif /* INCLUDE_xTaskAbortDelay == 1 */\r