2 * FreeRTOS Kernel V10.2.1
\r
3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\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
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\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
35 /* Standard includes. */
\r
38 /* Kernel includes. */
\r
39 #include "FreeRTOS.h"
\r
43 #include "event_groups.h"
\r
44 #include "stream_buffer.h"
\r
46 /* Demo includes. */
\r
47 #include "AbortDelay.h"
\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
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
57 /* Task priorities. Allow these to be overridden. */
\r
58 #ifndef abtCONTROLLING_PRIORITY
\r
59 #define abtCONTROLLING_PRIORITY ( configMAX_PRIORITIES - 3 )
\r
62 #ifndef abtBLOCKING_PRIORITY
\r
63 #define abtBLOCKING_PRIORITY ( configMAX_PRIORITIES - 2 )
\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
77 /*-----------------------------------------------------------*/
\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
83 static void prvControllingTask( void *pvParameters );
\r
84 static void prvBlockingTask( void *pvParameters );
\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
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
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
105 * Performs a few tests to cover code paths not otherwise covered by the continuous
\r
108 static void prvPerformSingleTaskTests( void );
\r
111 * Checks the amount of time a task spent in the Blocked state is within the
\r
114 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );
\r
116 /*-----------------------------------------------------------*/
\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
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
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
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
135 /*-----------------------------------------------------------*/
\r
137 void vCreateAbortDelayTasks( void )
\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
143 /*-----------------------------------------------------------*/
\r
145 static void prvControllingTask( void *pvParameters )
\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
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
156 /* Just to remove compiler warnings. */
\r
157 ( void ) pvParameters;
\r
159 xBlockingTask = xTaskGetHandle( pcBlockingTaskName );
\r
160 configASSERT( xBlockingTask );
\r
164 /* Tell the secondary task to perform the next test. */
\r
165 xTimeAtStart = xTaskGetTickCount();
\r
166 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
\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
181 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
\r
183 /* For test coverage sometimes xTaskAbortDelay() is used and sometimes
\r
184 xTaskAbortDelayFromISR() is used. */
\r
185 if( xUseFromISRVersion == pdFALSE )
\r
187 if( xTaskAbortDelay( xBlockingTask ) != pdPASS )
\r
189 xErrorOccurred = pdTRUE;
\r
194 xHigherPriorityTaskWoken = pdFALSE;
\r
196 /* For test coverage, sometimes xHigherPriorityTaskWoken is used, and
\r
197 sometimes NULL is used. */
\r
199 if( ( xControllingCycles % 2 ) == 0 )
\r
201 if( xTaskAbortDelayFromISR( xBlockingTask, &xHigherPriorityTaskWoken ) != pdPASS )
\r
203 xErrorOccurred = pdTRUE;
\r
208 if( xTaskAbortDelayFromISR( xBlockingTask, NULL ) != pdPASS )
\r
210 xErrorOccurred = pdTRUE;
\r
214 /* The tasks have the same priority so xHigherPriorityTaskWoken should
\r
216 if( xHigherPriorityTaskWoken != pdFALSE )
\r
218 xErrorOccurred = pdTRUE;
\r
222 /* Reset the priority to the normal controlling priority. */
\r
223 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
\r
225 /* Now wait to be notified that the secondary task has completed its
\r
227 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\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
234 /* Move onto the next test. */
\r
237 if( ulTestToPerform >= abtMAX_TESTS )
\r
239 ulTestToPerform = 0;
\r
242 /* To indicate this task is still executing. */
\r
243 xControllingCycles++;
\r
245 if( ( xControllingCycles % abtMAX_TESTS ) == 0 )
\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
253 /*-----------------------------------------------------------*/
\r
255 static void prvBlockingTask( void *pvParameters )
\r
257 TaskHandle_t xControllingTask;
\r
258 uint32_t ulNotificationValue;
\r
259 const uint32_t ulMax = 0xffffffffUL;
\r
261 /* Just to remove compiler warnings. */
\r
262 ( void ) pvParameters;
\r
264 /* Start by performing a few tests to cover code not exercised in the loops
\r
266 prvPerformSingleTaskTests();
\r
268 xControllingTask = xTaskGetHandle( pcControllingTaskName );
\r
269 configASSERT( xControllingTask );
\r
273 /* Wait to be notified of the test that is to be performed next. */
\r
274 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );
\r
276 switch( ulNotificationValue )
\r
278 case abtNOTIFY_WAIT_ABORTS:
\r
279 prvTestAbortingTaskNotifyWait();
\r
282 case abtNOTIFY_TAKE_ABORTS:
\r
283 prvTestAbortingTaskNotifyTake();
\r
286 case abtDELAY_ABORTS:
\r
287 prvTestAbortingTaskDelay();
\r
290 case abtDELAY_UNTIL_ABORTS:
\r
291 prvTestAbortingTaskDelayUntil();
\r
294 case abtSEMAPHORE_TAKE_ABORTS:
\r
295 prvTestAbortingSemaphoreTake();
\r
298 case abtEVENT_GROUP_ABORTS:
\r
299 prvTestAbortingEventGroupWait();
\r
302 case abtQUEUE_SEND_ABORTS:
\r
303 prvTestAbortingQueueSend();
\r
306 case abtSTREAM_BUFFER_RECEIVE:
\r
307 prvTestAbortingStreamBufferReceive();
\r
311 /* Should not get here. */
\r
315 /* Let the primary task know the test is complete. */
\r
316 xTaskNotifyGive( xControllingTask );
\r
318 /* To indicate this task is still executing. */
\r
322 /*-----------------------------------------------------------*/
\r
324 static void prvPerformSingleTaskTests( void )
\r
326 TaskHandle_t xThisTask;
\r
327 BaseType_t xReturned;
\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
333 xReturned = xTaskAbortDelay( xThisTask );
\r
334 if( xReturned != pdFALSE )
\r
336 xErrorOccurred = pdTRUE;
\r
339 xReturned = xTaskAbortDelayFromISR( xThisTask, NULL );
\r
340 if( xReturned != pdFALSE )
\r
342 xErrorOccurred = pdTRUE;
\r
345 /*-----------------------------------------------------------*/
\r
347 static void prvTestAbortingTaskDelayUntil( void )
\r
349 TickType_t xTimeAtStart, xLastBlockTime;
\r
351 /* Note the time before the delay so the length of the delay is known. */
\r
352 xTimeAtStart = xTaskGetTickCount();
\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
359 /* This first delay should just time out. */
\r
360 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
361 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\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
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
378 /*-----------------------------------------------------------*/
\r
380 static void prvTestAbortingTaskDelay( void )
\r
382 TickType_t xTimeAtStart;
\r
384 /* Note the time before the delay so the length of the delay is known. */
\r
385 xTimeAtStart = xTaskGetTickCount();
\r
387 /* This first delay should just time out. */
\r
388 vTaskDelay( xMaxBlockTime );
\r
389 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
391 /* Note the time before the delay so the length of the delay is known. */
\r
392 xTimeAtStart = xTaskGetTickCount();
\r
394 /* This second delay should be aborted by the primary task half way
\r
396 vTaskDelay( xMaxBlockTime );
\r
397 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
399 /* Note the time before the delay so the length of the delay is known. */
\r
400 xTimeAtStart = xTaskGetTickCount();
\r
402 /* This third delay should just time out again. */
\r
403 vTaskDelay( xMaxBlockTime );
\r
404 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
406 /*-----------------------------------------------------------*/
\r
408 static void prvTestAbortingTaskNotifyTake( void )
\r
410 TickType_t xTimeAtStart;
\r
413 /* Note the time before the delay so the length of the delay is known. */
\r
414 xTimeAtStart = xTaskGetTickCount();
\r
416 /* This first delay should just time out. */
\r
417 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
418 if( ulReturn != 0 )
\r
420 xErrorOccurred = pdTRUE;
\r
422 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
424 /* Note the time before the delay so the length of the delay is known. */
\r
425 xTimeAtStart = xTaskGetTickCount();
\r
427 /* This second delay should be aborted by the primary task half way
\r
429 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
430 if( ulReturn != 0 )
\r
432 xErrorOccurred = pdTRUE;
\r
434 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
436 /* Note the time before the delay so the length of the delay is known. */
\r
437 xTimeAtStart = xTaskGetTickCount();
\r
439 /* This third delay should just time out again. */
\r
440 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
441 if( ulReturn != 0 )
\r
443 xErrorOccurred = pdTRUE;
\r
445 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
447 /*-----------------------------------------------------------*/
\r
449 static void prvTestAbortingEventGroupWait( void )
\r
451 TickType_t xTimeAtStart;
\r
452 EventGroupHandle_t xEventGroup;
\r
453 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
455 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
457 static StaticEventGroup_t xEventGroupBuffer;
\r
459 /* Create the event group. Statically allocated memory is used so the
\r
460 creation cannot fail. */
\r
461 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
465 xEventGroup = xEventGroupCreate();
\r
466 configASSERT( xEventGroup );
\r
470 /* Note the time before the delay so the length of the delay is known. */
\r
471 xTimeAtStart = xTaskGetTickCount();
\r
473 /* This first delay should just time out. */
\r
474 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
475 if( xReturn != 0x00 )
\r
477 xErrorOccurred = pdTRUE;
\r
479 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
481 /* Note the time before the delay so the length of the delay is known. */
\r
482 xTimeAtStart = xTaskGetTickCount();
\r
484 /* This second delay should be aborted by the primary task half way
\r
486 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
487 if( xReturn != 0x00 )
\r
489 xErrorOccurred = pdTRUE;
\r
491 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
493 /* Note the time before the delay so the length of the delay is known. */
\r
494 xTimeAtStart = xTaskGetTickCount();
\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
500 xErrorOccurred = pdTRUE;
\r
502 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
504 /* Not really necessary in this case, but for completeness. */
\r
505 vEventGroupDelete( xEventGroup );
\r
507 /*-----------------------------------------------------------*/
\r
509 static void prvTestAbortingStreamBufferReceive( void )
\r
511 TickType_t xTimeAtStart;
\r
512 StreamBufferHandle_t xStreamBuffer;
\r
514 const size_t xTriggerLevelBytes = ( size_t ) 1;
\r
517 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
519 /* Defines the memory that will actually hold the streams within the
\r
521 static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];
\r
523 /* The variable used to hold the stream buffer structure. */
\r
524 StaticStreamBuffer_t xStreamBufferStruct;
\r
527 xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),
\r
528 xTriggerLevelBytes,
\r
530 &xStreamBufferStruct );
\r
534 xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );
\r
535 configASSERT( xStreamBuffer );
\r
539 /* Note the time before the delay so the length of the delay is known. */
\r
540 xTimeAtStart = xTaskGetTickCount();
\r
542 /* This first delay should just time out. */
\r
543 xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
\r
544 if( xReturn != 0x00 )
\r
546 xErrorOccurred = pdTRUE;
\r
548 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
550 /* Note the time before the delay so the length of the delay is known. */
\r
551 xTimeAtStart = xTaskGetTickCount();
\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
558 xErrorOccurred = pdTRUE;
\r
560 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
562 /* Note the time before the delay so the length of the delay is known. */
\r
563 xTimeAtStart = xTaskGetTickCount();
\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
569 xErrorOccurred = pdTRUE;
\r
571 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
573 /* Not really necessary in this case, but for completeness. */
\r
574 vStreamBufferDelete( xStreamBuffer );
\r
576 /*-----------------------------------------------------------*/
\r
578 static void prvTestAbortingQueueSend( void )
\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
586 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
588 static StaticQueue_t xQueueBuffer;
\r
589 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\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
597 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
598 configASSERT( xQueue );
\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
607 xErrorOccurred = pdTRUE;
\r
610 /* Note the time before the delay so the length of the delay is known. */
\r
611 xTimeAtStart = xTaskGetTickCount();
\r
613 /* This first delay should just time out. */
\r
614 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
615 if( xReturn != pdFALSE )
\r
617 xErrorOccurred = pdTRUE;
\r
619 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
621 /* Note the time before the delay so the length of the delay is known. */
\r
622 xTimeAtStart = xTaskGetTickCount();
\r
624 /* This second delay should be aborted by the primary task half way
\r
626 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
627 if( xReturn != pdFALSE )
\r
629 xErrorOccurred = pdTRUE;
\r
631 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
633 /* Note the time before the delay so the length of the delay is known. */
\r
634 xTimeAtStart = xTaskGetTickCount();
\r
636 /* This third delay should just time out again. */
\r
637 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
638 if( xReturn != pdFALSE )
\r
640 xErrorOccurred = pdTRUE;
\r
642 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
644 /* Not really necessary in this case, but for completeness. */
\r
645 vQueueDelete( xQueue );
\r
647 /*-----------------------------------------------------------*/
\r
649 static void prvTestAbortingSemaphoreTake( void )
\r
651 TickType_t xTimeAtStart;
\r
652 BaseType_t xReturn;
\r
653 SemaphoreHandle_t xSemaphore;
\r
655 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
657 static StaticSemaphore_t xSemaphoreBuffer;
\r
659 /* Create the semaphore. Statically allocated memory is used so the
\r
660 creation cannot fail. */
\r
661 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
665 xSemaphore = xSemaphoreCreateBinary();
\r
669 /* Note the time before the delay so the length of the delay is known. */
\r
670 xTimeAtStart = xTaskGetTickCount();
\r
672 /* This first delay should just time out. */
\r
673 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
674 if( xReturn != pdFALSE )
\r
676 xErrorOccurred = pdTRUE;
\r
678 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
680 /* Note the time before the delay so the length of the delay is known. */
\r
681 xTimeAtStart = xTaskGetTickCount();
\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
688 xErrorOccurred = pdTRUE;
\r
690 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
692 /* Note the time before the delay so the length of the delay is known. */
\r
693 xTimeAtStart = xTaskGetTickCount();
\r
695 /* This third delay should just time out again. */
\r
696 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
697 if( xReturn != pdFALSE )
\r
699 xErrorOccurred = pdTRUE;
\r
701 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
703 /* Not really necessary in this case, but for completeness. */
\r
704 vSemaphoreDelete( xSemaphore );
\r
706 /*-----------------------------------------------------------*/
\r
708 static void prvTestAbortingTaskNotifyWait( void )
\r
710 TickType_t xTimeAtStart;
\r
711 BaseType_t xReturn;
\r
713 /* Note the time before the delay so the length of the delay is known. */
\r
714 xTimeAtStart = xTaskGetTickCount();
\r
716 /* This first delay should just time out. */
\r
717 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
718 if( xReturn != pdFALSE )
\r
720 xErrorOccurred = pdTRUE;
\r
722 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
724 /* Note the time before the delay so the length of the delay is known. */
\r
725 xTimeAtStart = xTaskGetTickCount();
\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
732 xErrorOccurred = pdTRUE;
\r
734 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
736 /* Note the time before the delay so the length of the delay is known. */
\r
737 xTimeAtStart = xTaskGetTickCount();
\r
739 /* This third delay should just time out again. */
\r
740 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
741 if( xReturn != pdFALSE )
\r
743 xErrorOccurred = pdTRUE;
\r
745 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
747 /*-----------------------------------------------------------*/
\r
749 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
751 TickType_t xTimeNow, xActualBlockTime;
\r
753 xTimeNow = xTaskGetTickCount();
\r
754 xActualBlockTime = xTimeNow - xStartTime;
\r
756 /* The actual block time should not be less than the expected block time. */
\r
757 if( xActualBlockTime < xExpectedBlockTime )
\r
759 xErrorOccurred = pdTRUE;
\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
767 xErrorOccurred = pdTRUE;
\r
770 /*-----------------------------------------------------------*/
\r
772 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
774 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
775 BaseType_t xReturn = pdPASS;
\r
777 /* Have both tasks performed at least one cycle since this function was
\r
779 if( xControllingCycles == xLastControllingCycleCount )
\r
784 if( xBlockingCycles == xLastBlockingCycleCount )
\r
789 if( xErrorOccurred == pdTRUE )
\r
794 xLastBlockingCycleCount = xBlockingCycles;
\r
795 xLastControllingCycleCount = xControllingCycles;
\r
800 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r