2 FreeRTOS V9.0.0rc2 - Copyright (C) 2016 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_xTaskGetTaskHandle != 1 )
\r
93 #error This test file uses the xTaskGetTaskHandle() API function so INCLUDE_xTaskGetTaskHandle 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 = xTaskGetTaskHandle( 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 xTaskAbortDelay( xBlockingTask );
\r
210 /* Reset the priority to the normal controlling priority. */
\r
211 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
\r
213 /* Now wait to be notified that the secondary task has completed its
\r
215 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
217 /* Did the entire test run for the expected time, which is two full
\r
218 block times plus the half block time caused by calling
\r
219 xTaskAbortDelay()? */
\r
220 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
\r
222 /* Move onto the next test. */
\r
225 if( ulTestToPerform >= abtMAX_TESTS )
\r
227 ulTestToPerform = 0;
\r
230 /* To indicate this task is still executing. */
\r
231 xControllingCycles++;
\r
234 /*-----------------------------------------------------------*/
\r
236 static void prvBlockingTask( void *pvParameters )
\r
238 TaskHandle_t xControllingTask;
\r
239 uint32_t ulNotificationValue;
\r
241 /* Just to remove compiler warnings. */
\r
242 ( void ) pvParameters;
\r
244 xControllingTask = xTaskGetTaskHandle( pcControllingTaskName );
\r
245 configASSERT( xControllingTask );
\r
249 /* Wait to be notified of the test that is to be performed next. */
\r
250 xTaskNotifyWait( 0, ULONG_MAX, &ulNotificationValue, portMAX_DELAY );
\r
252 switch( ulNotificationValue )
\r
254 case abtNOTIFY_WAIT_ABORTS:
\r
255 prvTestAbortingTaskNotifyWait();
\r
258 case abtNOTIFY_TAKE_ABORTS:
\r
259 prvTestAbortingTaskNotifyTake();
\r
262 case abtDELAY_ABORTS:
\r
263 prvTestAbortingTaskDelay();
\r
266 case abtDELAY_UNTIL_ABORTS:
\r
267 prvTestAbortingTaskDelayUntil();
\r
270 case abtSEMAPHORE_TAKE_ABORTS:
\r
271 prvTestAbortingSemaphoreTake();
\r
274 case abtEVENT_GROUP_ABORTS:
\r
275 prvTestAbortingEventGroupWait();
\r
278 case abtQUEUE_SEND_ABORTS:
\r
279 prvTestAbortingQueueSend();
\r
283 /* Should not get here. */
\r
287 /* Let the primary task know the test is complete. */
\r
288 xTaskNotifyGive( xControllingTask );
\r
290 /* To indicate this task is still executing. */
\r
294 /*-----------------------------------------------------------*/
\r
296 static void prvTestAbortingTaskDelayUntil( void )
\r
298 TickType_t xTimeAtStart, xLastBlockTime;
\r
300 /* Note the time before the delay so the length of the delay is known. */
\r
301 xTimeAtStart = xTaskGetTickCount();
\r
303 /* Take a copy of the time as it is updated in the call to
\r
304 vTaskDelayUntil() but its original value is needed to determine the actual
\r
305 time spend in the Blocked state. */
\r
306 xLastBlockTime = xTimeAtStart;
\r
308 /* This first delay should just time out. */
\r
309 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
310 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
312 /* This second delay should be aborted by the primary task half way
\r
313 through. Again take a copy of the time as it is updated in the call to
\r
314 vTaskDelayUntil() buts its original value is needed to determine the amount
\r
315 of time actually spent in the Blocked state. */
\r
316 xTimeAtStart = xTaskGetTickCount();
\r
317 xLastBlockTime = xTimeAtStart;
\r
318 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
319 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
321 /* As with the other tests, the third block period should not time out. */
\r
322 xTimeAtStart = xTaskGetTickCount();
\r
323 xLastBlockTime = xTimeAtStart;
\r
324 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
325 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
327 /*-----------------------------------------------------------*/
\r
329 static void prvTestAbortingTaskDelay( void )
\r
331 TickType_t xTimeAtStart;
\r
333 /* Note the time before the delay so the length of the delay is known. */
\r
334 xTimeAtStart = xTaskGetTickCount();
\r
336 /* This first delay should just time out. */
\r
337 vTaskDelay( xMaxBlockTime );
\r
338 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
340 /* Note the time before the delay so the length of the delay is known. */
\r
341 xTimeAtStart = xTaskGetTickCount();
\r
343 /* This second delay should be aborted by the primary task half way
\r
345 vTaskDelay( xMaxBlockTime );
\r
346 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
348 /* Note the time before the delay so the length of the delay is known. */
\r
349 xTimeAtStart = xTaskGetTickCount();
\r
351 /* This third delay should just time out again. */
\r
352 vTaskDelay( xMaxBlockTime );
\r
353 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
355 /*-----------------------------------------------------------*/
\r
357 static void prvTestAbortingTaskNotifyTake( void )
\r
359 TickType_t xTimeAtStart;
\r
362 /* Note the time before the delay so the length of the delay is known. */
\r
363 xTimeAtStart = xTaskGetTickCount();
\r
365 /* This first delay should just time out. */
\r
366 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
367 if( ulReturn != 0 )
\r
369 xErrorOccurred = pdTRUE;
\r
371 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
373 /* Note the time before the delay so the length of the delay is known. */
\r
374 xTimeAtStart = xTaskGetTickCount();
\r
376 /* This second delay should be aborted by the primary task half way
\r
378 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
379 if( ulReturn != 0 )
\r
381 xErrorOccurred = pdTRUE;
\r
383 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
385 /* Note the time before the delay so the length of the delay is known. */
\r
386 xTimeAtStart = xTaskGetTickCount();
\r
388 /* This third delay should just time out again. */
\r
389 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
390 if( ulReturn != 0 )
\r
392 xErrorOccurred = pdTRUE;
\r
394 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
396 /*-----------------------------------------------------------*/
\r
398 static void prvTestAbortingEventGroupWait( void )
\r
400 TickType_t xTimeAtStart;
\r
401 EventGroupHandle_t xEventGroup;
\r
402 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
404 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
406 static StaticEventGroup_t xEventGroupBuffer;
\r
408 /* Create the event group. Statically allocated memory is used so the
\r
409 creation cannot fail. */
\r
410 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
414 xEventGroup = xEventGroupCreate();
\r
415 configASSERT( xEventGroup );
\r
419 /* Note the time before the delay so the length of the delay is known. */
\r
420 xTimeAtStart = xTaskGetTickCount();
\r
422 /* This first delay should just time out. */
\r
423 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
424 if( xReturn != 0x00 )
\r
426 xErrorOccurred = pdTRUE;
\r
428 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
430 /* Note the time before the delay so the length of the delay is known. */
\r
431 xTimeAtStart = xTaskGetTickCount();
\r
433 /* This second delay should be aborted by the primary task half way
\r
435 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
436 if( xReturn != 0x00 )
\r
438 xErrorOccurred = pdTRUE;
\r
440 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
442 /* Note the time before the delay so the length of the delay is known. */
\r
443 xTimeAtStart = xTaskGetTickCount();
\r
445 /* This third delay should just time out again. */
\r
446 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
447 if( xReturn != 0x00 )
\r
449 xErrorOccurred = pdTRUE;
\r
451 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
453 /* Not really necessary in this case, but for completeness. */
\r
454 vEventGroupDelete( xEventGroup );
\r
456 /*-----------------------------------------------------------*/
\r
458 static void prvTestAbortingQueueSend( void )
\r
460 TickType_t xTimeAtStart;
\r
461 BaseType_t xReturn;
\r
462 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;
\r
463 QueueHandle_t xQueue;
\r
464 uint8_t ucItemToQueue;
\r
466 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
468 static StaticQueue_t xQueueBuffer;
\r
469 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\r
471 /* Create the queue. Statically allocated memory is used so the
\r
472 creation cannot fail. */
\r
473 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
\r
477 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
478 configASSERT( xQueue );
\r
482 /* This function tests aborting when in the blocked state waiting to send,
\r
483 so the queue must be full. There is only one space in the queue. */
\r
484 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
485 if( xReturn != pdPASS )
\r
487 xErrorOccurred = pdTRUE;
\r
490 /* Note the time before the delay so the length of the delay is known. */
\r
491 xTimeAtStart = xTaskGetTickCount();
\r
493 /* This first delay should just time out. */
\r
494 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
495 if( xReturn != pdFALSE )
\r
497 xErrorOccurred = pdTRUE;
\r
499 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
501 /* Note the time before the delay so the length of the delay is known. */
\r
502 xTimeAtStart = xTaskGetTickCount();
\r
504 /* This second delay should be aborted by the primary task half way
\r
506 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
507 if( xReturn != pdFALSE )
\r
509 xErrorOccurred = pdTRUE;
\r
511 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
513 /* Note the time before the delay so the length of the delay is known. */
\r
514 xTimeAtStart = xTaskGetTickCount();
\r
516 /* This third delay should just time out again. */
\r
517 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
518 if( xReturn != pdFALSE )
\r
520 xErrorOccurred = pdTRUE;
\r
522 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
524 /* Not really necessary in this case, but for completeness. */
\r
525 vQueueDelete( xQueue );
\r
527 /*-----------------------------------------------------------*/
\r
529 static void prvTestAbortingSemaphoreTake( void )
\r
531 TickType_t xTimeAtStart;
\r
532 BaseType_t xReturn;
\r
533 SemaphoreHandle_t xSemaphore;
\r
535 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
537 static StaticSemaphore_t xSemaphoreBuffer;
\r
539 /* Create the semaphore. Statically allocated memory is used so the
\r
540 creation cannot fail. */
\r
541 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
545 xSemaphore = xSemaphoreCreateBinary();
\r
549 /* Note the time before the delay so the length of the delay is known. */
\r
550 xTimeAtStart = xTaskGetTickCount();
\r
552 /* This first delay should just time out. */
\r
553 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
554 if( xReturn != pdFALSE )
\r
556 xErrorOccurred = pdTRUE;
\r
558 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
560 /* Note the time before the delay so the length of the delay is known. */
\r
561 xTimeAtStart = xTaskGetTickCount();
\r
563 /* This second delay should be aborted by the primary task half way
\r
565 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
566 if( xReturn != pdFALSE )
\r
568 xErrorOccurred = pdTRUE;
\r
570 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
572 /* Note the time before the delay so the length of the delay is known. */
\r
573 xTimeAtStart = xTaskGetTickCount();
\r
575 /* This third delay should just time out again. */
\r
576 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
577 if( xReturn != pdFALSE )
\r
579 xErrorOccurred = pdTRUE;
\r
581 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
583 /* Not really necessary in this case, but for completeness. */
\r
584 vSemaphoreDelete( xSemaphore );
\r
586 /*-----------------------------------------------------------*/
\r
588 static void prvTestAbortingTaskNotifyWait( void )
\r
590 TickType_t xTimeAtStart;
\r
591 BaseType_t xReturn;
\r
593 /* Note the time before the delay so the length of the delay is known. */
\r
594 xTimeAtStart = xTaskGetTickCount();
\r
596 /* This first delay should just time out. */
\r
597 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
598 if( xReturn != pdFALSE )
\r
600 xErrorOccurred = pdTRUE;
\r
602 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
604 /* Note the time before the delay so the length of the delay is known. */
\r
605 xTimeAtStart = xTaskGetTickCount();
\r
607 /* This second delay should be aborted by the primary task half way
\r
609 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
610 if( xReturn != pdFALSE )
\r
612 xErrorOccurred = pdTRUE;
\r
614 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
616 /* Note the time before the delay so the length of the delay is known. */
\r
617 xTimeAtStart = xTaskGetTickCount();
\r
619 /* This third delay should just time out again. */
\r
620 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
621 if( xReturn != pdFALSE )
\r
623 xErrorOccurred = pdTRUE;
\r
625 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
627 /*-----------------------------------------------------------*/
\r
629 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
631 TickType_t xTimeNow, xActualBlockTime;
\r
633 xTimeNow = xTaskGetTickCount();
\r
634 xActualBlockTime = xTimeNow - xStartTime;
\r
636 /* The actual block time should not be less than the expected block time. */
\r
637 if( xActualBlockTime < xExpectedBlockTime )
\r
639 xErrorOccurred = pdTRUE;
\r
642 /* The actual block time can be greater than the expected block time, as it
\r
643 depends on the priority of the other tasks, but it should be within an
\r
644 acceptable margin. */
\r
645 if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
\r
647 xErrorOccurred = pdTRUE;
\r
650 /*-----------------------------------------------------------*/
\r
652 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
654 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
655 BaseType_t xReturn = pdPASS;
\r
657 /* Have both tasks performed at least one cycle since this function was
\r
659 if( xControllingCycles == xLastControllingCycleCount )
\r
664 if( xBlockingCycles == xLastBlockingCycleCount )
\r
669 if( xErrorOccurred == pdTRUE )
\r
674 xLastBlockingCycleCount = xBlockingCycles;
\r
675 xLastControllingCycleCount = xControllingCycles;
\r
680 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r