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 /* Just to remove compiler warnings. */
\r
153 ( void ) pvParameters;
\r
155 xBlockingTask = xTaskGetHandle( pcBlockingTaskName );
\r
156 configASSERT( xBlockingTask );
\r
160 /* Tell the secondary task to perform the next test. */
\r
161 xTimeAtStart = xTaskGetTickCount();
\r
162 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
\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
179 xErrorOccurred = pdTRUE;
\r
182 /* Reset the priority to the normal controlling priority. */
\r
183 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
\r
185 /* Now wait to be notified that the secondary task has completed its
\r
187 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\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
194 /* Move onto the next test. */
\r
197 if( ulTestToPerform >= abtMAX_TESTS )
\r
199 ulTestToPerform = 0;
\r
202 /* To indicate this task is still executing. */
\r
203 xControllingCycles++;
\r
206 /*-----------------------------------------------------------*/
\r
208 static void prvBlockingTask( void *pvParameters )
\r
210 TaskHandle_t xControllingTask;
\r
211 uint32_t ulNotificationValue;
\r
212 const uint32_t ulMax = 0xffffffffUL;
\r
214 /* Just to remove compiler warnings. */
\r
215 ( void ) pvParameters;
\r
217 /* Start by performing a few tests to cover code not exercised in the loops
\r
219 prvPerformSingleTaskTests();
\r
221 xControllingTask = xTaskGetHandle( pcControllingTaskName );
\r
222 configASSERT( xControllingTask );
\r
226 /* Wait to be notified of the test that is to be performed next. */
\r
227 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );
\r
229 switch( ulNotificationValue )
\r
231 case abtNOTIFY_WAIT_ABORTS:
\r
232 prvTestAbortingTaskNotifyWait();
\r
235 case abtNOTIFY_TAKE_ABORTS:
\r
236 prvTestAbortingTaskNotifyTake();
\r
239 case abtDELAY_ABORTS:
\r
240 prvTestAbortingTaskDelay();
\r
243 case abtDELAY_UNTIL_ABORTS:
\r
244 prvTestAbortingTaskDelayUntil();
\r
247 case abtSEMAPHORE_TAKE_ABORTS:
\r
248 prvTestAbortingSemaphoreTake();
\r
251 case abtEVENT_GROUP_ABORTS:
\r
252 prvTestAbortingEventGroupWait();
\r
255 case abtQUEUE_SEND_ABORTS:
\r
256 prvTestAbortingQueueSend();
\r
259 case abtSTREAM_BUFFER_RECEIVE:
\r
260 prvTestAbortingStreamBufferReceive();
\r
264 /* Should not get here. */
\r
268 /* Let the primary task know the test is complete. */
\r
269 xTaskNotifyGive( xControllingTask );
\r
271 /* To indicate this task is still executing. */
\r
275 /*-----------------------------------------------------------*/
\r
277 static void prvPerformSingleTaskTests( void )
\r
279 TaskHandle_t xThisTask;
\r
280 BaseType_t xReturned;
\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
286 xReturned = xTaskAbortDelay( xThisTask );
\r
287 if( xReturned != pdFALSE )
\r
289 xErrorOccurred = pdTRUE;
\r
292 /*-----------------------------------------------------------*/
\r
294 static void prvTestAbortingTaskDelayUntil( void )
\r
296 TickType_t xTimeAtStart, xLastBlockTime;
\r
298 /* Note the time before the delay so the length of the delay is known. */
\r
299 xTimeAtStart = xTaskGetTickCount();
\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
306 /* This first delay should just time out. */
\r
307 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
308 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\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
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
325 /*-----------------------------------------------------------*/
\r
327 static void prvTestAbortingTaskDelay( void )
\r
329 TickType_t xTimeAtStart;
\r
331 /* Note the time before the delay so the length of the delay is known. */
\r
332 xTimeAtStart = xTaskGetTickCount();
\r
334 /* This first delay should just time out. */
\r
335 vTaskDelay( xMaxBlockTime );
\r
336 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
338 /* Note the time before the delay so the length of the delay is known. */
\r
339 xTimeAtStart = xTaskGetTickCount();
\r
341 /* This second delay should be aborted by the primary task half way
\r
343 vTaskDelay( xMaxBlockTime );
\r
344 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
346 /* Note the time before the delay so the length of the delay is known. */
\r
347 xTimeAtStart = xTaskGetTickCount();
\r
349 /* This third delay should just time out again. */
\r
350 vTaskDelay( xMaxBlockTime );
\r
351 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
353 /*-----------------------------------------------------------*/
\r
355 static void prvTestAbortingTaskNotifyTake( void )
\r
357 TickType_t xTimeAtStart;
\r
360 /* Note the time before the delay so the length of the delay is known. */
\r
361 xTimeAtStart = xTaskGetTickCount();
\r
363 /* This first delay should just time out. */
\r
364 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
365 if( ulReturn != 0 )
\r
367 xErrorOccurred = pdTRUE;
\r
369 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
371 /* Note the time before the delay so the length of the delay is known. */
\r
372 xTimeAtStart = xTaskGetTickCount();
\r
374 /* This second delay should be aborted by the primary task half way
\r
376 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
377 if( ulReturn != 0 )
\r
379 xErrorOccurred = pdTRUE;
\r
381 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
383 /* Note the time before the delay so the length of the delay is known. */
\r
384 xTimeAtStart = xTaskGetTickCount();
\r
386 /* This third delay should just time out again. */
\r
387 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
388 if( ulReturn != 0 )
\r
390 xErrorOccurred = pdTRUE;
\r
392 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
394 /*-----------------------------------------------------------*/
\r
396 static void prvTestAbortingEventGroupWait( void )
\r
398 TickType_t xTimeAtStart;
\r
399 EventGroupHandle_t xEventGroup;
\r
400 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
402 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
404 static StaticEventGroup_t xEventGroupBuffer;
\r
406 /* Create the event group. Statically allocated memory is used so the
\r
407 creation cannot fail. */
\r
408 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
412 xEventGroup = xEventGroupCreate();
\r
413 configASSERT( xEventGroup );
\r
417 /* Note the time before the delay so the length of the delay is known. */
\r
418 xTimeAtStart = xTaskGetTickCount();
\r
420 /* This first delay should just time out. */
\r
421 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
422 if( xReturn != 0x00 )
\r
424 xErrorOccurred = pdTRUE;
\r
426 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
428 /* Note the time before the delay so the length of the delay is known. */
\r
429 xTimeAtStart = xTaskGetTickCount();
\r
431 /* This second delay should be aborted by the primary task half way
\r
433 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
434 if( xReturn != 0x00 )
\r
436 xErrorOccurred = pdTRUE;
\r
438 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
440 /* Note the time before the delay so the length of the delay is known. */
\r
441 xTimeAtStart = xTaskGetTickCount();
\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
447 xErrorOccurred = pdTRUE;
\r
449 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
451 /* Not really necessary in this case, but for completeness. */
\r
452 vEventGroupDelete( xEventGroup );
\r
454 /*-----------------------------------------------------------*/
\r
456 static void prvTestAbortingStreamBufferReceive( void )
\r
458 TickType_t xTimeAtStart;
\r
459 StreamBufferHandle_t xStreamBuffer;
\r
461 const size_t xTriggerLevelBytes = ( size_t ) 1;
\r
464 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
466 /* Defines the memory that will actually hold the streams within the
\r
468 static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];
\r
470 /* The variable used to hold the stream buffer structure. */
\r
471 StaticStreamBuffer_t xStreamBufferStruct;
\r
474 xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),
\r
475 xTriggerLevelBytes,
\r
477 &xStreamBufferStruct );
\r
481 xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );
\r
482 configASSERT( xStreamBuffer );
\r
486 /* Note the time before the delay so the length of the delay is known. */
\r
487 xTimeAtStart = xTaskGetTickCount();
\r
489 /* This first delay should just time out. */
\r
490 xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
\r
491 if( xReturn != 0x00 )
\r
493 xErrorOccurred = pdTRUE;
\r
495 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
497 /* Note the time before the delay so the length of the delay is known. */
\r
498 xTimeAtStart = xTaskGetTickCount();
\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
505 xErrorOccurred = pdTRUE;
\r
507 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
509 /* Note the time before the delay so the length of the delay is known. */
\r
510 xTimeAtStart = xTaskGetTickCount();
\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
516 xErrorOccurred = pdTRUE;
\r
518 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
520 /* Not really necessary in this case, but for completeness. */
\r
521 vStreamBufferDelete( xStreamBuffer );
\r
523 /*-----------------------------------------------------------*/
\r
525 static void prvTestAbortingQueueSend( void )
\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
533 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
535 static StaticQueue_t xQueueBuffer;
\r
536 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\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
544 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
545 configASSERT( xQueue );
\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
554 xErrorOccurred = pdTRUE;
\r
557 /* Note the time before the delay so the length of the delay is known. */
\r
558 xTimeAtStart = xTaskGetTickCount();
\r
560 /* This first delay should just time out. */
\r
561 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
562 if( xReturn != pdFALSE )
\r
564 xErrorOccurred = pdTRUE;
\r
566 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
568 /* Note the time before the delay so the length of the delay is known. */
\r
569 xTimeAtStart = xTaskGetTickCount();
\r
571 /* This second delay should be aborted by the primary task half way
\r
573 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
574 if( xReturn != pdFALSE )
\r
576 xErrorOccurred = pdTRUE;
\r
578 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
580 /* Note the time before the delay so the length of the delay is known. */
\r
581 xTimeAtStart = xTaskGetTickCount();
\r
583 /* This third delay should just time out again. */
\r
584 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
585 if( xReturn != pdFALSE )
\r
587 xErrorOccurred = pdTRUE;
\r
589 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
591 /* Not really necessary in this case, but for completeness. */
\r
592 vQueueDelete( xQueue );
\r
594 /*-----------------------------------------------------------*/
\r
596 static void prvTestAbortingSemaphoreTake( void )
\r
598 TickType_t xTimeAtStart;
\r
599 BaseType_t xReturn;
\r
600 SemaphoreHandle_t xSemaphore;
\r
602 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
604 static StaticSemaphore_t xSemaphoreBuffer;
\r
606 /* Create the semaphore. Statically allocated memory is used so the
\r
607 creation cannot fail. */
\r
608 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
612 xSemaphore = xSemaphoreCreateBinary();
\r
616 /* Note the time before the delay so the length of the delay is known. */
\r
617 xTimeAtStart = xTaskGetTickCount();
\r
619 /* This first delay should just time out. */
\r
620 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
621 if( xReturn != pdFALSE )
\r
623 xErrorOccurred = pdTRUE;
\r
625 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
627 /* Note the time before the delay so the length of the delay is known. */
\r
628 xTimeAtStart = xTaskGetTickCount();
\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
635 xErrorOccurred = pdTRUE;
\r
637 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
639 /* Note the time before the delay so the length of the delay is known. */
\r
640 xTimeAtStart = xTaskGetTickCount();
\r
642 /* This third delay should just time out again. */
\r
643 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
644 if( xReturn != pdFALSE )
\r
646 xErrorOccurred = pdTRUE;
\r
648 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
650 /* Not really necessary in this case, but for completeness. */
\r
651 vSemaphoreDelete( xSemaphore );
\r
653 /*-----------------------------------------------------------*/
\r
655 static void prvTestAbortingTaskNotifyWait( void )
\r
657 TickType_t xTimeAtStart;
\r
658 BaseType_t xReturn;
\r
660 /* Note the time before the delay so the length of the delay is known. */
\r
661 xTimeAtStart = xTaskGetTickCount();
\r
663 /* This first delay should just time out. */
\r
664 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
665 if( xReturn != pdFALSE )
\r
667 xErrorOccurred = pdTRUE;
\r
669 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
671 /* Note the time before the delay so the length of the delay is known. */
\r
672 xTimeAtStart = xTaskGetTickCount();
\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
679 xErrorOccurred = pdTRUE;
\r
681 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
683 /* Note the time before the delay so the length of the delay is known. */
\r
684 xTimeAtStart = xTaskGetTickCount();
\r
686 /* This third delay should just time out again. */
\r
687 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
688 if( xReturn != pdFALSE )
\r
690 xErrorOccurred = pdTRUE;
\r
692 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
694 /*-----------------------------------------------------------*/
\r
696 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
698 TickType_t xTimeNow, xActualBlockTime;
\r
700 xTimeNow = xTaskGetTickCount();
\r
701 xActualBlockTime = xTimeNow - xStartTime;
\r
703 /* The actual block time should not be less than the expected block time. */
\r
704 if( xActualBlockTime < xExpectedBlockTime )
\r
706 xErrorOccurred = pdTRUE;
\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
714 xErrorOccurred = pdTRUE;
\r
717 /*-----------------------------------------------------------*/
\r
719 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
721 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
722 BaseType_t xReturn = pdPASS;
\r
724 /* Have both tasks performed at least one cycle since this function was
\r
726 if( xControllingCycles == xLastControllingCycleCount )
\r
731 if( xBlockingCycles == xLastBlockingCycleCount )
\r
736 if( xErrorOccurred == pdTRUE )
\r
741 xLastBlockingCycleCount = xBlockingCycles;
\r
742 xLastControllingCycleCount = xControllingCycles;
\r
747 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r