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_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 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
240 const uint32_t ulMax = 0xffffffffUL;
\r
242 /* Just to remove compiler warnings. */
\r
243 ( void ) pvParameters;
\r
245 xControllingTask = xTaskGetHandle( pcControllingTaskName );
\r
246 configASSERT( xControllingTask );
\r
250 /* Wait to be notified of the test that is to be performed next. */
\r
251 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );
\r
253 switch( ulNotificationValue )
\r
255 case abtNOTIFY_WAIT_ABORTS:
\r
256 prvTestAbortingTaskNotifyWait();
\r
259 case abtNOTIFY_TAKE_ABORTS:
\r
260 prvTestAbortingTaskNotifyTake();
\r
263 case abtDELAY_ABORTS:
\r
264 prvTestAbortingTaskDelay();
\r
267 case abtDELAY_UNTIL_ABORTS:
\r
268 prvTestAbortingTaskDelayUntil();
\r
271 case abtSEMAPHORE_TAKE_ABORTS:
\r
272 prvTestAbortingSemaphoreTake();
\r
275 case abtEVENT_GROUP_ABORTS:
\r
276 prvTestAbortingEventGroupWait();
\r
279 case abtQUEUE_SEND_ABORTS:
\r
280 prvTestAbortingQueueSend();
\r
284 /* Should not get here. */
\r
288 /* Let the primary task know the test is complete. */
\r
289 xTaskNotifyGive( xControllingTask );
\r
291 /* To indicate this task is still executing. */
\r
295 /*-----------------------------------------------------------*/
\r
297 static void prvTestAbortingTaskDelayUntil( void )
\r
299 TickType_t xTimeAtStart, xLastBlockTime;
\r
301 /* Note the time before the delay so the length of the delay is known. */
\r
302 xTimeAtStart = xTaskGetTickCount();
\r
304 /* Take a copy of the time as it is updated in the call to
\r
305 vTaskDelayUntil() but its original value is needed to determine the actual
\r
306 time spend in the Blocked state. */
\r
307 xLastBlockTime = xTimeAtStart;
\r
309 /* This first delay should just time out. */
\r
310 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
311 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
313 /* This second delay should be aborted by the primary task half way
\r
314 through. Again take a copy of the time as it is updated in the call to
\r
315 vTaskDelayUntil() buts its original value is needed to determine the amount
\r
316 of time actually spent in the Blocked state. */
\r
317 xTimeAtStart = xTaskGetTickCount();
\r
318 xLastBlockTime = xTimeAtStart;
\r
319 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
320 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
322 /* As with the other tests, the third block period should not time out. */
\r
323 xTimeAtStart = xTaskGetTickCount();
\r
324 xLastBlockTime = xTimeAtStart;
\r
325 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
326 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
328 /*-----------------------------------------------------------*/
\r
330 static void prvTestAbortingTaskDelay( void )
\r
332 TickType_t xTimeAtStart;
\r
334 /* Note the time before the delay so the length of the delay is known. */
\r
335 xTimeAtStart = xTaskGetTickCount();
\r
337 /* This first delay should just time out. */
\r
338 vTaskDelay( xMaxBlockTime );
\r
339 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
341 /* Note the time before the delay so the length of the delay is known. */
\r
342 xTimeAtStart = xTaskGetTickCount();
\r
344 /* This second delay should be aborted by the primary task half way
\r
346 vTaskDelay( xMaxBlockTime );
\r
347 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
349 /* Note the time before the delay so the length of the delay is known. */
\r
350 xTimeAtStart = xTaskGetTickCount();
\r
352 /* This third delay should just time out again. */
\r
353 vTaskDelay( xMaxBlockTime );
\r
354 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
356 /*-----------------------------------------------------------*/
\r
358 static void prvTestAbortingTaskNotifyTake( void )
\r
360 TickType_t xTimeAtStart;
\r
363 /* Note the time before the delay so the length of the delay is known. */
\r
364 xTimeAtStart = xTaskGetTickCount();
\r
366 /* This first delay should just time out. */
\r
367 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
368 if( ulReturn != 0 )
\r
370 xErrorOccurred = pdTRUE;
\r
372 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
374 /* Note the time before the delay so the length of the delay is known. */
\r
375 xTimeAtStart = xTaskGetTickCount();
\r
377 /* This second delay should be aborted by the primary task half way
\r
379 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
380 if( ulReturn != 0 )
\r
382 xErrorOccurred = pdTRUE;
\r
384 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
386 /* Note the time before the delay so the length of the delay is known. */
\r
387 xTimeAtStart = xTaskGetTickCount();
\r
389 /* This third delay should just time out again. */
\r
390 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
391 if( ulReturn != 0 )
\r
393 xErrorOccurred = pdTRUE;
\r
395 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
397 /*-----------------------------------------------------------*/
\r
399 static void prvTestAbortingEventGroupWait( void )
\r
401 TickType_t xTimeAtStart;
\r
402 EventGroupHandle_t xEventGroup;
\r
403 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
405 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
407 static StaticEventGroup_t xEventGroupBuffer;
\r
409 /* Create the event group. Statically allocated memory is used so the
\r
410 creation cannot fail. */
\r
411 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
415 xEventGroup = xEventGroupCreate();
\r
416 configASSERT( xEventGroup );
\r
420 /* Note the time before the delay so the length of the delay is known. */
\r
421 xTimeAtStart = xTaskGetTickCount();
\r
423 /* This first delay should just time out. */
\r
424 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
425 if( xReturn != 0x00 )
\r
427 xErrorOccurred = pdTRUE;
\r
429 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
431 /* Note the time before the delay so the length of the delay is known. */
\r
432 xTimeAtStart = xTaskGetTickCount();
\r
434 /* This second delay should be aborted by the primary task half way
\r
436 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
437 if( xReturn != 0x00 )
\r
439 xErrorOccurred = pdTRUE;
\r
441 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
443 /* Note the time before the delay so the length of the delay is known. */
\r
444 xTimeAtStart = xTaskGetTickCount();
\r
446 /* This third delay should just time out again. */
\r
447 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
448 if( xReturn != 0x00 )
\r
450 xErrorOccurred = pdTRUE;
\r
452 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
454 /* Not really necessary in this case, but for completeness. */
\r
455 vEventGroupDelete( xEventGroup );
\r
457 /*-----------------------------------------------------------*/
\r
459 static void prvTestAbortingQueueSend( void )
\r
461 TickType_t xTimeAtStart;
\r
462 BaseType_t xReturn;
\r
463 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;
\r
464 QueueHandle_t xQueue;
\r
465 uint8_t ucItemToQueue;
\r
467 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
469 static StaticQueue_t xQueueBuffer;
\r
470 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\r
472 /* Create the queue. Statically allocated memory is used so the
\r
473 creation cannot fail. */
\r
474 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
\r
478 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
479 configASSERT( xQueue );
\r
483 /* This function tests aborting when in the blocked state waiting to send,
\r
484 so the queue must be full. There is only one space in the queue. */
\r
485 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
486 if( xReturn != pdPASS )
\r
488 xErrorOccurred = pdTRUE;
\r
491 /* Note the time before the delay so the length of the delay is known. */
\r
492 xTimeAtStart = xTaskGetTickCount();
\r
494 /* This first delay should just time out. */
\r
495 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
496 if( xReturn != pdFALSE )
\r
498 xErrorOccurred = pdTRUE;
\r
500 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
502 /* Note the time before the delay so the length of the delay is known. */
\r
503 xTimeAtStart = xTaskGetTickCount();
\r
505 /* This second delay should be aborted by the primary task half way
\r
507 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
508 if( xReturn != pdFALSE )
\r
510 xErrorOccurred = pdTRUE;
\r
512 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
514 /* Note the time before the delay so the length of the delay is known. */
\r
515 xTimeAtStart = xTaskGetTickCount();
\r
517 /* This third delay should just time out again. */
\r
518 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
519 if( xReturn != pdFALSE )
\r
521 xErrorOccurred = pdTRUE;
\r
523 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
525 /* Not really necessary in this case, but for completeness. */
\r
526 vQueueDelete( xQueue );
\r
528 /*-----------------------------------------------------------*/
\r
530 static void prvTestAbortingSemaphoreTake( void )
\r
532 TickType_t xTimeAtStart;
\r
533 BaseType_t xReturn;
\r
534 SemaphoreHandle_t xSemaphore;
\r
536 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
538 static StaticSemaphore_t xSemaphoreBuffer;
\r
540 /* Create the semaphore. Statically allocated memory is used so the
\r
541 creation cannot fail. */
\r
542 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
546 xSemaphore = xSemaphoreCreateBinary();
\r
550 /* Note the time before the delay so the length of the delay is known. */
\r
551 xTimeAtStart = xTaskGetTickCount();
\r
553 /* This first delay should just time out. */
\r
554 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
555 if( xReturn != pdFALSE )
\r
557 xErrorOccurred = pdTRUE;
\r
559 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
561 /* Note the time before the delay so the length of the delay is known. */
\r
562 xTimeAtStart = xTaskGetTickCount();
\r
564 /* This second delay should be aborted by the primary task half way
\r
566 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
567 if( xReturn != pdFALSE )
\r
569 xErrorOccurred = pdTRUE;
\r
571 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
573 /* Note the time before the delay so the length of the delay is known. */
\r
574 xTimeAtStart = xTaskGetTickCount();
\r
576 /* This third delay should just time out again. */
\r
577 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
578 if( xReturn != pdFALSE )
\r
580 xErrorOccurred = pdTRUE;
\r
582 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
584 /* Not really necessary in this case, but for completeness. */
\r
585 vSemaphoreDelete( xSemaphore );
\r
587 /*-----------------------------------------------------------*/
\r
589 static void prvTestAbortingTaskNotifyWait( void )
\r
591 TickType_t xTimeAtStart;
\r
592 BaseType_t xReturn;
\r
594 /* Note the time before the delay so the length of the delay is known. */
\r
595 xTimeAtStart = xTaskGetTickCount();
\r
597 /* This first delay should just time out. */
\r
598 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
599 if( xReturn != pdFALSE )
\r
601 xErrorOccurred = pdTRUE;
\r
603 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
605 /* Note the time before the delay so the length of the delay is known. */
\r
606 xTimeAtStart = xTaskGetTickCount();
\r
608 /* This second delay should be aborted by the primary task half way
\r
610 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
611 if( xReturn != pdFALSE )
\r
613 xErrorOccurred = pdTRUE;
\r
615 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
617 /* Note the time before the delay so the length of the delay is known. */
\r
618 xTimeAtStart = xTaskGetTickCount();
\r
620 /* This third delay should just time out again. */
\r
621 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
622 if( xReturn != pdFALSE )
\r
624 xErrorOccurred = pdTRUE;
\r
626 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
628 /*-----------------------------------------------------------*/
\r
630 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
632 TickType_t xTimeNow, xActualBlockTime;
\r
634 xTimeNow = xTaskGetTickCount();
\r
635 xActualBlockTime = xTimeNow - xStartTime;
\r
637 /* The actual block time should not be less than the expected block time. */
\r
638 if( xActualBlockTime < xExpectedBlockTime )
\r
640 xErrorOccurred = pdTRUE;
\r
643 /* The actual block time can be greater than the expected block time, as it
\r
644 depends on the priority of the other tasks, but it should be within an
\r
645 acceptable margin. */
\r
646 if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
\r
648 xErrorOccurred = pdTRUE;
\r
651 /*-----------------------------------------------------------*/
\r
653 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
655 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
656 BaseType_t xReturn = pdPASS;
\r
658 /* Have both tasks performed at least one cycle since this function was
\r
660 if( xControllingCycles == xLastControllingCycleCount )
\r
665 if( xBlockingCycles == xLastBlockingCycleCount )
\r
670 if( xErrorOccurred == pdTRUE )
\r
675 xLastBlockingCycleCount = xBlockingCycles;
\r
676 xLastControllingCycleCount = xControllingCycles;
\r
681 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r