2 FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 This file is part of the FreeRTOS distribution.
\r
9 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
10 the terms of the GNU General Public License (version 2) as published by the
\r
11 Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
\r
13 ***************************************************************************
\r
14 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
15 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
16 >>! obliged to provide the source code for proprietary components !<<
\r
17 >>! outside of the FreeRTOS kernel. !<<
\r
18 ***************************************************************************
\r
20 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
22 FOR A PARTICULAR PURPOSE. Full license text is available on the following
\r
23 link: http://www.freertos.org/a00114.html
\r
25 ***************************************************************************
\r
27 * FreeRTOS provides completely free yet professionally developed, *
\r
28 * robust, strictly quality controlled, supported, and cross *
\r
29 * platform software that is more than just the market leader, it *
\r
30 * is the industry's de facto standard. *
\r
32 * Help yourself get started quickly while simultaneously helping *
\r
33 * to support the FreeRTOS project by purchasing a FreeRTOS *
\r
34 * tutorial book, reference manual, or both: *
\r
35 * http://www.FreeRTOS.org/Documentation *
\r
37 ***************************************************************************
\r
39 http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
\r
40 the FAQ page "My application does not run, what could be wrong?". Have you
\r
41 defined configASSERT()?
\r
43 http://www.FreeRTOS.org/support - In return for receiving this top quality
\r
44 embedded software for free we request you assist our global community by
\r
45 participating in the support forum.
\r
47 http://www.FreeRTOS.org/training - Investing in training allows your team to
\r
48 be as productive as possible as early as possible. Now you can receive
\r
49 FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
\r
50 Ltd, and the world's leading authority on the world's leading RTOS.
\r
52 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
53 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
54 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
56 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
\r
57 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
\r
59 http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
\r
60 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
61 licenses offer ticketed support, indemnification and commercial middleware.
\r
63 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
64 engineered and independently SIL3 certified version for use in safety and
\r
65 mission critical applications that require provable dependability.
\r
71 * This file contains some test scenarios that ensure tasks respond correctly
\r
72 * to xTaskAbortDelay() calls.
\r
75 /* Standard includes. */
\r
78 /* Kernel includes. */
\r
79 #include "FreeRTOS.h"
\r
83 #include "event_groups.h"
\r
85 /* Demo includes. */
\r
86 #include "AbortDelay.h"
\r
88 /* This file can only be used if the functionality it tests is included in the
\r
89 build. Remove the whole file if this is not the case. */
\r
90 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
92 #if( INCLUDE_xTaskGetHandle != 1 )
\r
93 #error This test file uses the xTaskGetHandle() API function so INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h.
\r
96 /* Task priorities. Allow these to be overridden. */
\r
97 #ifndef abtCONTROLLING_PRIORITY
\r
98 #define abtCONTROLLING_PRIORITY ( configMAX_PRIORITIES - 3 )
\r
101 #ifndef abtBLOCKING_PRIORITY
\r
102 #define abtBLOCKING_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
105 /* The tests that are performed. */
\r
106 #define abtNOTIFY_WAIT_ABORTS 0
\r
107 #define abtNOTIFY_TAKE_ABORTS 1
\r
108 #define abtDELAY_ABORTS 2
\r
109 #define abtDELAY_UNTIL_ABORTS 3
\r
110 #define abtSEMAPHORE_TAKE_ABORTS 4
\r
111 #define abtEVENT_GROUP_ABORTS 5
\r
112 #define abtQUEUE_SEND_ABORTS 6
\r
113 #define abtMAX_TESTS 7
\r
115 /*-----------------------------------------------------------*/
\r
118 * The two test tasks. The controlling task specifies which test to executed.
\r
119 * More information is provided in the comments within the tasks.
\r
121 static void prvControllingTask( void *pvParameters );
\r
122 static void prvBlockingTask( void *pvParameters );
\r
125 * Test functions called by the blocking task. Each function follows the same
\r
126 * pattern, but the way the task blocks is different in each case.
\r
128 * In each function three blocking calls are made. The first and third
\r
129 * blocking call is expected to time out, while the middle blocking call is
\r
130 * expected to be aborted by the controlling task half way through the block
\r
133 static void prvTestAbortingTaskNotifyWait( void );
\r
134 static void prvTestAbortingTaskNotifyTake( void );
\r
135 static void prvTestAbortingTaskDelay( void );
\r
136 static void prvTestAbortingTaskDelayUntil( void );
\r
137 static void prvTestAbortingSemaphoreTake( void );
\r
138 static void prvTestAbortingEventGroupWait( void );
\r
139 static void prvTestAbortingQueueSend( void );
\r
142 * Checks the amount of time a task spent in the Blocked state is within the
\r
145 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );
\r
147 /*-----------------------------------------------------------*/
\r
149 /* Used to ensure that tasks are still executing without error. */
\r
150 static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;
\r
151 static volatile BaseType_t xErrorOccurred = pdFALSE;
\r
153 /* Each task needs to know the other tasks handle so they can send signals to
\r
154 each other. The handle is obtained from the task's name. */
\r
155 static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";
\r
157 /* The maximum amount of time a task will block for. */
\r
158 const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );
\r
159 const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );
\r
161 /* The actual block time is dependent on the priority of other tasks in the
\r
162 system so the actual block time might be greater than that expected, but it
\r
163 should be within an acceptable upper bound. */
\r
164 const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );
\r
166 /*-----------------------------------------------------------*/
\r
168 void vCreateAbortDelayTasks( void )
\r
170 /* Create the two test tasks described above. */
\r
171 xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );
\r
172 xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );
\r
174 /*-----------------------------------------------------------*/
\r
176 static void prvControllingTask( void *pvParameters )
\r
178 TaskHandle_t xBlockingTask;
\r
179 uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;
\r
180 TickType_t xTimeAtStart;
\r
181 const TickType_t xStartMargin = 2UL;
\r
183 /* Just to remove compiler warnings. */
\r
184 ( void ) pvParameters;
\r
186 xBlockingTask = xTaskGetHandle( pcBlockingTaskName );
\r
187 configASSERT( xBlockingTask );
\r
191 /* Tell the secondary task to perform the next test. */
\r
192 xTimeAtStart = xTaskGetTickCount();
\r
193 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
\r
195 /* The secondary task has a higher priority, so will now be in the
\r
196 Blocked state to wait for a maximum of xMaxBlockTime. It expects that
\r
197 period to complete with a timeout. It will then block for
\r
198 xMaxBlockTimeAgain, but this time it expects to the block time to abort
\r
199 half way through. Block until it is time to send the abort to the
\r
200 secondary task. xStartMargin is used because this task takes timing
\r
201 from the beginning of the test, whereas the blocking task takes timing
\r
202 from the entry into the Blocked state - and as the tasks run at
\r
203 different priorities, there may be some discrepancy. Also, temporarily
\r
204 raise the priority of the controlling task to that of the blocking
\r
205 task to minimise discrepancies. */
\r
206 vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );
\r
207 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
\r
208 if( xTaskAbortDelay( xBlockingTask ) != pdPASS )
\r
210 xErrorOccurred = pdTRUE;
\r
213 /* Reset the priority to the normal controlling priority. */
\r
214 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
\r
216 /* Now wait to be notified that the secondary task has completed its
\r
218 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
220 /* Did the entire test run for the expected time, which is two full
\r
221 block times plus the half block time caused by calling
\r
222 xTaskAbortDelay()? */
\r
223 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
\r
225 /* Move onto the next test. */
\r
228 if( ulTestToPerform >= abtMAX_TESTS )
\r
230 ulTestToPerform = 0;
\r
233 /* To indicate this task is still executing. */
\r
234 xControllingCycles++;
\r
237 /*-----------------------------------------------------------*/
\r
239 static void prvBlockingTask( void *pvParameters )
\r
241 TaskHandle_t xControllingTask;
\r
242 uint32_t ulNotificationValue;
\r
243 const uint32_t ulMax = 0xffffffffUL;
\r
245 /* Just to remove compiler warnings. */
\r
246 ( void ) pvParameters;
\r
248 xControllingTask = xTaskGetHandle( pcControllingTaskName );
\r
249 configASSERT( xControllingTask );
\r
253 /* Wait to be notified of the test that is to be performed next. */
\r
254 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );
\r
256 switch( ulNotificationValue )
\r
258 case abtNOTIFY_WAIT_ABORTS:
\r
259 prvTestAbortingTaskNotifyWait();
\r
262 case abtNOTIFY_TAKE_ABORTS:
\r
263 prvTestAbortingTaskNotifyTake();
\r
266 case abtDELAY_ABORTS:
\r
267 prvTestAbortingTaskDelay();
\r
270 case abtDELAY_UNTIL_ABORTS:
\r
271 prvTestAbortingTaskDelayUntil();
\r
274 case abtSEMAPHORE_TAKE_ABORTS:
\r
275 prvTestAbortingSemaphoreTake();
\r
278 case abtEVENT_GROUP_ABORTS:
\r
279 prvTestAbortingEventGroupWait();
\r
282 case abtQUEUE_SEND_ABORTS:
\r
283 prvTestAbortingQueueSend();
\r
287 /* Should not get here. */
\r
291 /* Let the primary task know the test is complete. */
\r
292 xTaskNotifyGive( xControllingTask );
\r
294 /* To indicate this task is still executing. */
\r
298 /*-----------------------------------------------------------*/
\r
300 static void prvTestAbortingTaskDelayUntil( void )
\r
302 TickType_t xTimeAtStart, xLastBlockTime;
\r
304 /* Note the time before the delay so the length of the delay is known. */
\r
305 xTimeAtStart = xTaskGetTickCount();
\r
307 /* Take a copy of the time as it is updated in the call to
\r
308 vTaskDelayUntil() but its original value is needed to determine the actual
\r
309 time spend in the Blocked state. */
\r
310 xLastBlockTime = xTimeAtStart;
\r
312 /* This first delay should just time out. */
\r
313 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
314 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
316 /* This second delay should be aborted by the primary task half way
\r
317 through. Again take a copy of the time as it is updated in the call to
\r
318 vTaskDelayUntil() buts its original value is needed to determine the amount
\r
319 of time actually spent in the Blocked state. */
\r
320 xTimeAtStart = xTaskGetTickCount();
\r
321 xLastBlockTime = xTimeAtStart;
\r
322 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
323 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
325 /* As with the other tests, the third block period should not time out. */
\r
326 xTimeAtStart = xTaskGetTickCount();
\r
327 xLastBlockTime = xTimeAtStart;
\r
328 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
329 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
331 /*-----------------------------------------------------------*/
\r
333 static void prvTestAbortingTaskDelay( void )
\r
335 TickType_t xTimeAtStart;
\r
337 /* Note the time before the delay so the length of the delay is known. */
\r
338 xTimeAtStart = xTaskGetTickCount();
\r
340 /* This first delay should just time out. */
\r
341 vTaskDelay( xMaxBlockTime );
\r
342 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
344 /* Note the time before the delay so the length of the delay is known. */
\r
345 xTimeAtStart = xTaskGetTickCount();
\r
347 /* This second delay should be aborted by the primary task half way
\r
349 vTaskDelay( xMaxBlockTime );
\r
350 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
352 /* Note the time before the delay so the length of the delay is known. */
\r
353 xTimeAtStart = xTaskGetTickCount();
\r
355 /* This third delay should just time out again. */
\r
356 vTaskDelay( xMaxBlockTime );
\r
357 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
359 /*-----------------------------------------------------------*/
\r
361 static void prvTestAbortingTaskNotifyTake( void )
\r
363 TickType_t xTimeAtStart;
\r
366 /* Note the time before the delay so the length of the delay is known. */
\r
367 xTimeAtStart = xTaskGetTickCount();
\r
369 /* This first delay should just time out. */
\r
370 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
371 if( ulReturn != 0 )
\r
373 xErrorOccurred = pdTRUE;
\r
375 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
377 /* Note the time before the delay so the length of the delay is known. */
\r
378 xTimeAtStart = xTaskGetTickCount();
\r
380 /* This second delay should be aborted by the primary task half way
\r
382 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
383 if( ulReturn != 0 )
\r
385 xErrorOccurred = pdTRUE;
\r
387 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
389 /* Note the time before the delay so the length of the delay is known. */
\r
390 xTimeAtStart = xTaskGetTickCount();
\r
392 /* This third delay should just time out again. */
\r
393 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
394 if( ulReturn != 0 )
\r
396 xErrorOccurred = pdTRUE;
\r
398 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
400 /*-----------------------------------------------------------*/
\r
402 static void prvTestAbortingEventGroupWait( void )
\r
404 TickType_t xTimeAtStart;
\r
405 EventGroupHandle_t xEventGroup;
\r
406 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
408 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
410 static StaticEventGroup_t xEventGroupBuffer;
\r
412 /* Create the event group. Statically allocated memory is used so the
\r
413 creation cannot fail. */
\r
414 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
418 xEventGroup = xEventGroupCreate();
\r
419 configASSERT( xEventGroup );
\r
423 /* Note the time before the delay so the length of the delay is known. */
\r
424 xTimeAtStart = xTaskGetTickCount();
\r
426 /* This first delay should just time out. */
\r
427 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
428 if( xReturn != 0x00 )
\r
430 xErrorOccurred = pdTRUE;
\r
432 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
434 /* Note the time before the delay so the length of the delay is known. */
\r
435 xTimeAtStart = xTaskGetTickCount();
\r
437 /* This second delay should be aborted by the primary task half way
\r
439 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
440 if( xReturn != 0x00 )
\r
442 xErrorOccurred = pdTRUE;
\r
444 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
446 /* Note the time before the delay so the length of the delay is known. */
\r
447 xTimeAtStart = xTaskGetTickCount();
\r
449 /* This third delay should just time out again. */
\r
450 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
451 if( xReturn != 0x00 )
\r
453 xErrorOccurred = pdTRUE;
\r
455 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
457 /* Not really necessary in this case, but for completeness. */
\r
458 vEventGroupDelete( xEventGroup );
\r
460 /*-----------------------------------------------------------*/
\r
462 static void prvTestAbortingQueueSend( void )
\r
464 TickType_t xTimeAtStart;
\r
465 BaseType_t xReturn;
\r
466 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;
\r
467 QueueHandle_t xQueue;
\r
468 uint8_t ucItemToQueue;
\r
470 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
472 static StaticQueue_t xQueueBuffer;
\r
473 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\r
475 /* Create the queue. Statically allocated memory is used so the
\r
476 creation cannot fail. */
\r
477 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
\r
481 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
482 configASSERT( xQueue );
\r
486 /* This function tests aborting when in the blocked state waiting to send,
\r
487 so the queue must be full. There is only one space in the queue. */
\r
488 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
489 if( xReturn != pdPASS )
\r
491 xErrorOccurred = pdTRUE;
\r
494 /* Note the time before the delay so the length of the delay is known. */
\r
495 xTimeAtStart = xTaskGetTickCount();
\r
497 /* This first delay should just time out. */
\r
498 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
499 if( xReturn != pdFALSE )
\r
501 xErrorOccurred = pdTRUE;
\r
503 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
505 /* Note the time before the delay so the length of the delay is known. */
\r
506 xTimeAtStart = xTaskGetTickCount();
\r
508 /* This second delay should be aborted by the primary task half way
\r
510 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
511 if( xReturn != pdFALSE )
\r
513 xErrorOccurred = pdTRUE;
\r
515 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
517 /* Note the time before the delay so the length of the delay is known. */
\r
518 xTimeAtStart = xTaskGetTickCount();
\r
520 /* This third delay should just time out again. */
\r
521 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
522 if( xReturn != pdFALSE )
\r
524 xErrorOccurred = pdTRUE;
\r
526 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
528 /* Not really necessary in this case, but for completeness. */
\r
529 vQueueDelete( xQueue );
\r
531 /*-----------------------------------------------------------*/
\r
533 static void prvTestAbortingSemaphoreTake( void )
\r
535 TickType_t xTimeAtStart;
\r
536 BaseType_t xReturn;
\r
537 SemaphoreHandle_t xSemaphore;
\r
539 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
541 static StaticSemaphore_t xSemaphoreBuffer;
\r
543 /* Create the semaphore. Statically allocated memory is used so the
\r
544 creation cannot fail. */
\r
545 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
549 xSemaphore = xSemaphoreCreateBinary();
\r
553 /* Note the time before the delay so the length of the delay is known. */
\r
554 xTimeAtStart = xTaskGetTickCount();
\r
556 /* This first delay should just time out. */
\r
557 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
558 if( xReturn != pdFALSE )
\r
560 xErrorOccurred = pdTRUE;
\r
562 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
564 /* Note the time before the delay so the length of the delay is known. */
\r
565 xTimeAtStart = xTaskGetTickCount();
\r
567 /* This second delay should be aborted by the primary task half way
\r
569 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
570 if( xReturn != pdFALSE )
\r
572 xErrorOccurred = pdTRUE;
\r
574 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
576 /* Note the time before the delay so the length of the delay is known. */
\r
577 xTimeAtStart = xTaskGetTickCount();
\r
579 /* This third delay should just time out again. */
\r
580 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
581 if( xReturn != pdFALSE )
\r
583 xErrorOccurred = pdTRUE;
\r
585 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
587 /* Not really necessary in this case, but for completeness. */
\r
588 vSemaphoreDelete( xSemaphore );
\r
590 /*-----------------------------------------------------------*/
\r
592 static void prvTestAbortingTaskNotifyWait( void )
\r
594 TickType_t xTimeAtStart;
\r
595 BaseType_t xReturn;
\r
597 /* Note the time before the delay so the length of the delay is known. */
\r
598 xTimeAtStart = xTaskGetTickCount();
\r
600 /* This first delay should just time out. */
\r
601 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
602 if( xReturn != pdFALSE )
\r
604 xErrorOccurred = pdTRUE;
\r
606 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
608 /* Note the time before the delay so the length of the delay is known. */
\r
609 xTimeAtStart = xTaskGetTickCount();
\r
611 /* This second delay should be aborted by the primary task half way
\r
613 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
614 if( xReturn != pdFALSE )
\r
616 xErrorOccurred = pdTRUE;
\r
618 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
620 /* Note the time before the delay so the length of the delay is known. */
\r
621 xTimeAtStart = xTaskGetTickCount();
\r
623 /* This third delay should just time out again. */
\r
624 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
625 if( xReturn != pdFALSE )
\r
627 xErrorOccurred = pdTRUE;
\r
629 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
631 /*-----------------------------------------------------------*/
\r
633 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
635 TickType_t xTimeNow, xActualBlockTime;
\r
637 xTimeNow = xTaskGetTickCount();
\r
638 xActualBlockTime = xTimeNow - xStartTime;
\r
640 /* The actual block time should not be less than the expected block time. */
\r
641 if( xActualBlockTime < xExpectedBlockTime )
\r
643 xErrorOccurred = pdTRUE;
\r
646 /* The actual block time can be greater than the expected block time, as it
\r
647 depends on the priority of the other tasks, but it should be within an
\r
648 acceptable margin. */
\r
649 if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
\r
651 xErrorOccurred = pdTRUE;
\r
654 /*-----------------------------------------------------------*/
\r
656 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
658 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
659 BaseType_t xReturn = pdPASS;
\r
661 /* Have both tasks performed at least one cycle since this function was
\r
663 if( xControllingCycles == xLastControllingCycleCount )
\r
668 if( xBlockingCycles == xLastBlockingCycleCount )
\r
673 if( xErrorOccurred == pdTRUE )
\r
678 xLastBlockingCycleCount = xBlockingCycles;
\r
679 xLastControllingCycleCount = xControllingCycles;
\r
684 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r