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