2 * FreeRTOS Kernel V10.0.1
\r
3 * Copyright (C) 2017 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 * Checks the amount of time a task spent in the Blocked state is within the
\r
108 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );
\r
110 /*-----------------------------------------------------------*/
\r
112 /* Used to ensure that tasks are still executing without error. */
\r
113 static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;
\r
114 static volatile BaseType_t xErrorOccurred = pdFALSE;
\r
116 /* Each task needs to know the other tasks handle so they can send signals to
\r
117 each other. The handle is obtained from the task's name. */
\r
118 static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";
\r
120 /* The maximum amount of time a task will block for. */
\r
121 const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );
\r
122 const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );
\r
124 /* The actual block time is dependent on the priority of other tasks in the
\r
125 system so the actual block time might be greater than that expected, but it
\r
126 should be within an acceptable upper bound. */
\r
127 const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );
\r
129 /*-----------------------------------------------------------*/
\r
131 void vCreateAbortDelayTasks( void )
\r
133 /* Create the two test tasks described above. */
\r
134 xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );
\r
135 xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );
\r
137 /*-----------------------------------------------------------*/
\r
139 static void prvControllingTask( void *pvParameters )
\r
141 TaskHandle_t xBlockingTask;
\r
142 uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;
\r
143 TickType_t xTimeAtStart;
\r
144 const TickType_t xStartMargin = 2UL;
\r
146 /* Just to remove compiler warnings. */
\r
147 ( void ) pvParameters;
\r
149 xBlockingTask = xTaskGetHandle( pcBlockingTaskName );
\r
150 configASSERT( xBlockingTask );
\r
154 /* Tell the secondary task to perform the next test. */
\r
155 xTimeAtStart = xTaskGetTickCount();
\r
156 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
\r
158 /* The secondary task has a higher priority, so will now be in the
\r
159 Blocked state to wait for a maximum of xMaxBlockTime. It expects that
\r
160 period to complete with a timeout. It will then block for
\r
161 xMaxBlockTimeAgain, but this time it expects to the block time to abort
\r
162 half way through. Block until it is time to send the abort to the
\r
163 secondary task. xStartMargin is used because this task takes timing
\r
164 from the beginning of the test, whereas the blocking task takes timing
\r
165 from the entry into the Blocked state - and as the tasks run at
\r
166 different priorities, there may be some discrepancy. Also, temporarily
\r
167 raise the priority of the controlling task to that of the blocking
\r
168 task to minimise discrepancies. */
\r
169 vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );
\r
170 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
\r
171 if( xTaskAbortDelay( xBlockingTask ) != pdPASS )
\r
173 xErrorOccurred = pdTRUE;
\r
176 /* Reset the priority to the normal controlling priority. */
\r
177 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
\r
179 /* Now wait to be notified that the secondary task has completed its
\r
181 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
183 /* Did the entire test run for the expected time, which is two full
\r
184 block times plus the half block time caused by calling
\r
185 xTaskAbortDelay()? */
\r
186 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
\r
188 /* Move onto the next test. */
\r
191 if( ulTestToPerform >= abtMAX_TESTS )
\r
193 ulTestToPerform = 0;
\r
196 /* To indicate this task is still executing. */
\r
197 xControllingCycles++;
\r
200 /*-----------------------------------------------------------*/
\r
202 static void prvBlockingTask( void *pvParameters )
\r
204 TaskHandle_t xControllingTask;
\r
205 uint32_t ulNotificationValue;
\r
206 const uint32_t ulMax = 0xffffffffUL;
\r
208 /* Just to remove compiler warnings. */
\r
209 ( void ) pvParameters;
\r
211 xControllingTask = xTaskGetHandle( pcControllingTaskName );
\r
212 configASSERT( xControllingTask );
\r
216 /* Wait to be notified of the test that is to be performed next. */
\r
217 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );
\r
219 switch( ulNotificationValue )
\r
221 case abtNOTIFY_WAIT_ABORTS:
\r
222 prvTestAbortingTaskNotifyWait();
\r
225 case abtNOTIFY_TAKE_ABORTS:
\r
226 prvTestAbortingTaskNotifyTake();
\r
229 case abtDELAY_ABORTS:
\r
230 prvTestAbortingTaskDelay();
\r
233 case abtDELAY_UNTIL_ABORTS:
\r
234 prvTestAbortingTaskDelayUntil();
\r
237 case abtSEMAPHORE_TAKE_ABORTS:
\r
238 prvTestAbortingSemaphoreTake();
\r
241 case abtEVENT_GROUP_ABORTS:
\r
242 prvTestAbortingEventGroupWait();
\r
245 case abtQUEUE_SEND_ABORTS:
\r
246 prvTestAbortingQueueSend();
\r
249 case abtSTREAM_BUFFER_RECEIVE:
\r
250 prvTestAbortingStreamBufferReceive();
\r
254 /* Should not get here. */
\r
258 /* Let the primary task know the test is complete. */
\r
259 xTaskNotifyGive( xControllingTask );
\r
261 /* To indicate this task is still executing. */
\r
265 /*-----------------------------------------------------------*/
\r
267 static void prvTestAbortingTaskDelayUntil( void )
\r
269 TickType_t xTimeAtStart, xLastBlockTime;
\r
271 /* Note the time before the delay so the length of the delay is known. */
\r
272 xTimeAtStart = xTaskGetTickCount();
\r
274 /* Take a copy of the time as it is updated in the call to
\r
275 vTaskDelayUntil() but its original value is needed to determine the actual
\r
276 time spend in the Blocked state. */
\r
277 xLastBlockTime = xTimeAtStart;
\r
279 /* This first delay should just time out. */
\r
280 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
281 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
283 /* This second delay should be aborted by the primary task half way
\r
284 through. Again take a copy of the time as it is updated in the call to
\r
285 vTaskDelayUntil() buts its original value is needed to determine the amount
\r
286 of time actually spent in the Blocked state. */
\r
287 xTimeAtStart = xTaskGetTickCount();
\r
288 xLastBlockTime = xTimeAtStart;
\r
289 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
290 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
292 /* As with the other tests, the third block period should not time out. */
\r
293 xTimeAtStart = xTaskGetTickCount();
\r
294 xLastBlockTime = xTimeAtStart;
\r
295 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
296 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
298 /*-----------------------------------------------------------*/
\r
300 static void prvTestAbortingTaskDelay( void )
\r
302 TickType_t xTimeAtStart;
\r
304 /* Note the time before the delay so the length of the delay is known. */
\r
305 xTimeAtStart = xTaskGetTickCount();
\r
307 /* This first delay should just time out. */
\r
308 vTaskDelay( xMaxBlockTime );
\r
309 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
311 /* Note the time before the delay so the length of the delay is known. */
\r
312 xTimeAtStart = xTaskGetTickCount();
\r
314 /* This second delay should be aborted by the primary task half way
\r
316 vTaskDelay( xMaxBlockTime );
\r
317 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
319 /* Note the time before the delay so the length of the delay is known. */
\r
320 xTimeAtStart = xTaskGetTickCount();
\r
322 /* This third delay should just time out again. */
\r
323 vTaskDelay( xMaxBlockTime );
\r
324 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
326 /*-----------------------------------------------------------*/
\r
328 static void prvTestAbortingTaskNotifyTake( void )
\r
330 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 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
338 if( ulReturn != 0 )
\r
340 xErrorOccurred = pdTRUE;
\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 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
350 if( ulReturn != 0 )
\r
352 xErrorOccurred = pdTRUE;
\r
354 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
356 /* Note the time before the delay so the length of the delay is known. */
\r
357 xTimeAtStart = xTaskGetTickCount();
\r
359 /* This third delay should just time out again. */
\r
360 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
361 if( ulReturn != 0 )
\r
363 xErrorOccurred = pdTRUE;
\r
365 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
367 /*-----------------------------------------------------------*/
\r
369 static void prvTestAbortingEventGroupWait( void )
\r
371 TickType_t xTimeAtStart;
\r
372 EventGroupHandle_t xEventGroup;
\r
373 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
375 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
377 static StaticEventGroup_t xEventGroupBuffer;
\r
379 /* Create the event group. Statically allocated memory is used so the
\r
380 creation cannot fail. */
\r
381 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
385 xEventGroup = xEventGroupCreate();
\r
386 configASSERT( xEventGroup );
\r
390 /* Note the time before the delay so the length of the delay is known. */
\r
391 xTimeAtStart = xTaskGetTickCount();
\r
393 /* This first delay should just time out. */
\r
394 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
395 if( xReturn != 0x00 )
\r
397 xErrorOccurred = pdTRUE;
\r
399 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
401 /* Note the time before the delay so the length of the delay is known. */
\r
402 xTimeAtStart = xTaskGetTickCount();
\r
404 /* This second delay should be aborted by the primary task half way
\r
406 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
407 if( xReturn != 0x00 )
\r
409 xErrorOccurred = pdTRUE;
\r
411 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
413 /* Note the time before the delay so the length of the delay is known. */
\r
414 xTimeAtStart = xTaskGetTickCount();
\r
416 /* This third delay should just time out again. */
\r
417 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
418 if( xReturn != 0x00 )
\r
420 xErrorOccurred = pdTRUE;
\r
422 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
424 /* Not really necessary in this case, but for completeness. */
\r
425 vEventGroupDelete( xEventGroup );
\r
427 /*-----------------------------------------------------------*/
\r
429 static void prvTestAbortingStreamBufferReceive( void )
\r
431 TickType_t xTimeAtStart;
\r
432 StreamBufferHandle_t xStreamBuffer;
\r
433 EventBits_t xReturn;
\r
434 const size_t xTriggerLevelBytes = ( size_t ) 1;
\r
437 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
439 /* Defines the memory that will actually hold the streams within the
\r
441 static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];
\r
443 /* The variable used to hold the stream buffer structure. */
\r
444 StaticStreamBuffer_t xStreamBufferStruct;
\r
447 xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),
\r
448 xTriggerLevelBytes,
\r
450 &xStreamBufferStruct );
\r
454 xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );
\r
455 configASSERT( xStreamBuffer );
\r
459 /* Note the time before the delay so the length of the delay is known. */
\r
460 xTimeAtStart = xTaskGetTickCount();
\r
462 /* This first delay should just time out. */
\r
463 xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
\r
464 if( xReturn != 0x00 )
\r
466 xErrorOccurred = pdTRUE;
\r
468 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
470 /* Note the time before the delay so the length of the delay is known. */
\r
471 xTimeAtStart = xTaskGetTickCount();
\r
473 /* This second delay should be aborted by the primary task half way
\r
474 through xMaxBlockTime. */
\r
475 xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
\r
476 if( xReturn != 0x00 )
\r
478 xErrorOccurred = pdTRUE;
\r
480 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
482 /* Note the time before the delay so the length of the delay is known. */
\r
483 xTimeAtStart = xTaskGetTickCount();
\r
485 /* This third delay should just time out again. */
\r
486 xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
\r
487 if( xReturn != 0x00 )
\r
489 xErrorOccurred = pdTRUE;
\r
491 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
493 /* Not really necessary in this case, but for completeness. */
\r
494 vStreamBufferDelete( xStreamBuffer );
\r
496 /*-----------------------------------------------------------*/
\r
498 static void prvTestAbortingQueueSend( void )
\r
500 TickType_t xTimeAtStart;
\r
501 BaseType_t xReturn;
\r
502 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;
\r
503 QueueHandle_t xQueue;
\r
504 uint8_t ucItemToQueue;
\r
506 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
508 static StaticQueue_t xQueueBuffer;
\r
509 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\r
511 /* Create the queue. Statically allocated memory is used so the
\r
512 creation cannot fail. */
\r
513 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
\r
517 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
518 configASSERT( xQueue );
\r
522 /* This function tests aborting when in the blocked state waiting to send,
\r
523 so the queue must be full. There is only one space in the queue. */
\r
524 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
525 if( xReturn != pdPASS )
\r
527 xErrorOccurred = pdTRUE;
\r
530 /* Note the time before the delay so the length of the delay is known. */
\r
531 xTimeAtStart = xTaskGetTickCount();
\r
533 /* This first delay should just time out. */
\r
534 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
535 if( xReturn != pdFALSE )
\r
537 xErrorOccurred = pdTRUE;
\r
539 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
541 /* Note the time before the delay so the length of the delay is known. */
\r
542 xTimeAtStart = xTaskGetTickCount();
\r
544 /* This second delay should be aborted by the primary task half way
\r
546 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
547 if( xReturn != pdFALSE )
\r
549 xErrorOccurred = pdTRUE;
\r
551 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
553 /* Note the time before the delay so the length of the delay is known. */
\r
554 xTimeAtStart = xTaskGetTickCount();
\r
556 /* This third delay should just time out again. */
\r
557 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
558 if( xReturn != pdFALSE )
\r
560 xErrorOccurred = pdTRUE;
\r
562 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
564 /* Not really necessary in this case, but for completeness. */
\r
565 vQueueDelete( xQueue );
\r
567 /*-----------------------------------------------------------*/
\r
569 static void prvTestAbortingSemaphoreTake( void )
\r
571 TickType_t xTimeAtStart;
\r
572 BaseType_t xReturn;
\r
573 SemaphoreHandle_t xSemaphore;
\r
575 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
577 static StaticSemaphore_t xSemaphoreBuffer;
\r
579 /* Create the semaphore. Statically allocated memory is used so the
\r
580 creation cannot fail. */
\r
581 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
585 xSemaphore = xSemaphoreCreateBinary();
\r
589 /* Note the time before the delay so the length of the delay is known. */
\r
590 xTimeAtStart = xTaskGetTickCount();
\r
592 /* This first delay should just time out. */
\r
593 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
594 if( xReturn != pdFALSE )
\r
596 xErrorOccurred = pdTRUE;
\r
598 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
600 /* Note the time before the delay so the length of the delay is known. */
\r
601 xTimeAtStart = xTaskGetTickCount();
\r
603 /* This second delay should be aborted by the primary task half way
\r
604 through xMaxBlockTime. */
\r
605 xReturn = xSemaphoreTake( xSemaphore, portMAX_DELAY );
\r
606 if( xReturn != pdFALSE )
\r
608 xErrorOccurred = pdTRUE;
\r
610 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
612 /* Note the time before the delay so the length of the delay is known. */
\r
613 xTimeAtStart = xTaskGetTickCount();
\r
615 /* This third delay should just time out again. */
\r
616 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
617 if( xReturn != pdFALSE )
\r
619 xErrorOccurred = pdTRUE;
\r
621 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
623 /* Not really necessary in this case, but for completeness. */
\r
624 vSemaphoreDelete( xSemaphore );
\r
626 /*-----------------------------------------------------------*/
\r
628 static void prvTestAbortingTaskNotifyWait( void )
\r
630 TickType_t xTimeAtStart;
\r
631 BaseType_t xReturn;
\r
633 /* Note the time before the delay so the length of the delay is known. */
\r
634 xTimeAtStart = xTaskGetTickCount();
\r
636 /* This first delay should just time out. */
\r
637 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
638 if( xReturn != pdFALSE )
\r
640 xErrorOccurred = pdTRUE;
\r
642 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
644 /* Note the time before the delay so the length of the delay is known. */
\r
645 xTimeAtStart = xTaskGetTickCount();
\r
647 /* This second delay should be aborted by the primary task half way
\r
648 through xMaxBlockTime. */
\r
649 xReturn = xTaskNotifyWait( 0, 0, NULL, portMAX_DELAY );
\r
650 if( xReturn != pdFALSE )
\r
652 xErrorOccurred = pdTRUE;
\r
654 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
656 /* Note the time before the delay so the length of the delay is known. */
\r
657 xTimeAtStart = xTaskGetTickCount();
\r
659 /* This third delay should just time out again. */
\r
660 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
661 if( xReturn != pdFALSE )
\r
663 xErrorOccurred = pdTRUE;
\r
665 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
667 /*-----------------------------------------------------------*/
\r
669 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
671 TickType_t xTimeNow, xActualBlockTime;
\r
673 xTimeNow = xTaskGetTickCount();
\r
674 xActualBlockTime = xTimeNow - xStartTime;
\r
676 /* The actual block time should not be less than the expected block time. */
\r
677 if( xActualBlockTime < xExpectedBlockTime )
\r
679 xErrorOccurred = pdTRUE;
\r
682 /* The actual block time can be greater than the expected block time, as it
\r
683 depends on the priority of the other tasks, but it should be within an
\r
684 acceptable margin. */
\r
685 if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
\r
687 xErrorOccurred = pdTRUE;
\r
690 /*-----------------------------------------------------------*/
\r
692 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
694 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
695 BaseType_t xReturn = pdPASS;
\r
697 /* Have both tasks performed at least one cycle since this function was
\r
699 if( xControllingCycles == xLastControllingCycleCount )
\r
704 if( xBlockingCycles == xLastBlockingCycleCount )
\r
709 if( xErrorOccurred == pdTRUE )
\r
714 xLastBlockingCycleCount = xBlockingCycles;
\r
715 xLastControllingCycleCount = xControllingCycles;
\r
720 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r