2 * FreeRTOS Kernel V10.0.0
\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. If you wish to use our Amazon
\r
14 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
31 * Tests the behaviour of direct task notifications.
\r
34 /* Standard includes. */
\r
37 /* Scheduler include files. */
\r
38 #include "FreeRTOS.h"
\r
42 /* Demo program include files. */
\r
43 #include "TaskNotify.h"
\r
45 #define notifyTASK_PRIORITY ( tskIDLE_PRIORITY )
\r
46 #define notifyUINT32_MAX ( ( uint32_t ) 0xffffffff )
\r
47 #define notifySUSPENDED_TEST_TIMER_PERIOD pdMS_TO_TICKS( 50 )
\r
49 /*-----------------------------------------------------------*/
\r
52 * Implementation of the task that gets notified.
\r
54 static void prvNotifiedTask( void *pvParameters );
\r
57 * Performs a few initial tests that can be done prior to creating the second
\r
60 static void prvSingleTaskTests( void );
\r
63 * Software timer callback function from which xTaskNotify() is called.
\r
65 static void prvNotifyingTimer( TimerHandle_t xTimer );
\r
68 * Utility function to create pseudo random numbers.
\r
70 static UBaseType_t prvRand( void );
\r
73 * Callback for a timer that is used during preliminary testing. The timer
\r
74 * tests the behaviour when 1: a task waiting for a notification is suspended
\r
75 * and then resumed without ever receiving a notification, and 2: when a task
\r
76 * waiting for a notification receives a notification while it is suspended.
\r
78 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
\r
80 /*-----------------------------------------------------------*/
\r
82 /* Used to latch errors during the test's execution. */
\r
83 static BaseType_t xErrorStatus = pdPASS;
\r
85 /* Used to ensure the task has not stalled. */
\r
86 static volatile uint32_t ulNotifyCycleCount = 0;
\r
88 /* The handle of the task that receives the notifications. */
\r
89 static TaskHandle_t xTaskToNotify = NULL;
\r
91 /* Used to count the notifications sent to the task from a software timer and
\r
92 the number of notifications received by the task from the software timer. The
\r
93 two should stay synchronised. */
\r
94 static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0UL;
\r
96 /* The timer used to notify the task. */
\r
97 static TimerHandle_t xTimer = NULL;
\r
99 /* Used by the pseudo random number generating function. */
\r
100 static size_t uxNextRand = 0;
\r
102 /*-----------------------------------------------------------*/
\r
104 void vStartTaskNotifyTask( void )
\r
106 /* Create the task that performs some tests by itself, then loops around
\r
107 being notified by both a software timer and an interrupt. */
\r
108 xTaskCreate( prvNotifiedTask, "Notified", configMINIMAL_STACK_SIZE, NULL, notifyTASK_PRIORITY, &xTaskToNotify );
\r
110 /* Pseudo seed the random number generator. */
\r
111 uxNextRand = ( size_t ) prvRand;
\r
113 /*-----------------------------------------------------------*/
\r
115 static void prvSingleTaskTests( void )
\r
117 const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
\r
118 BaseType_t xReturned;
\r
119 uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue;
\r
120 TickType_t xTimeOnEntering;
\r
121 const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;
\r
122 const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
\r
123 TimerHandle_t xSingleTaskTimer;
\r
126 /* ------------------------------------------------------------------------
\r
127 Check blocking when there are no notifications. */
\r
128 xTimeOnEntering = xTaskGetTickCount();
\r
129 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
\r
130 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
132 /* Should have blocked for the entire block time. */
\r
133 if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait )
\r
135 xErrorStatus = pdFAIL;
\r
137 configASSERT( xReturned == pdFAIL );
\r
138 configASSERT( ulNotifiedValue == 0UL );
\r
139 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
140 ( void ) ulNotifiedValue;
\r
145 /* ------------------------------------------------------------------------
\r
146 Check no blocking when notifications are pending. First notify itself -
\r
147 this would not be a normal thing to do and is done here for test purposes
\r
149 xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
\r
151 /* Even through the 'without overwrite' action was used the update should
\r
152 have been successful. */
\r
153 configASSERT( xReturned == pdPASS );
\r
154 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
156 /* No bits should have been pending previously. */
\r
157 configASSERT( ulPreviousValue == 0 );
\r
158 ( void ) ulPreviousValue;
\r
160 /* The task should now have a notification pending, and so not time out. */
\r
161 xTimeOnEntering = xTaskGetTickCount();
\r
162 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
\r
164 if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait )
\r
166 xErrorStatus = pdFAIL;
\r
169 /* The task should have been notified, and the notified value should
\r
170 be equal to ulFirstNotifiedConst. */
\r
171 configASSERT( xReturned == pdPASS );
\r
172 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
\r
173 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
174 ( void ) ulNotifiedValue;
\r
176 /* Incremented to show the task is still running. */
\r
177 ulNotifyCycleCount++;
\r
183 /*-------------------------------------------------------------------------
\r
184 Check the non-overwriting functionality. The notification is done twice
\r
185 using two different notification values. The action says don't overwrite so
\r
186 only the first notification should pass and the value read back should also
\r
187 be that used with the first notification. */
\r
188 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
\r
189 configASSERT( xReturned == pdPASS );
\r
190 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
192 xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
\r
193 configASSERT( xReturned == pdFAIL );
\r
194 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
196 /* Waiting for the notification should now return immediately so a block
\r
197 time of zero is used. */
\r
198 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
200 configASSERT( xReturned == pdPASS );
\r
201 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
\r
202 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
203 ( void ) ulNotifiedValue;
\r
209 /*-------------------------------------------------------------------------
\r
210 Do the same again, only this time use the overwriting version. This time
\r
211 both notifications should pass, and the value written the second time should
\r
212 overwrite the value written the first time, and so be the value that is read
\r
214 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );
\r
215 configASSERT( xReturned == pdPASS );
\r
216 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
217 xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
\r
218 configASSERT( xReturned == pdPASS );
\r
219 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
220 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
221 configASSERT( xReturned == pdPASS );
\r
222 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
223 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
\r
224 ( void ) ulNotifiedValue;
\r
229 /*-------------------------------------------------------------------------
\r
230 Check notifications with no action pass without updating the value. Even
\r
231 though ulFirstNotifiedConst is used as the value the value read back should
\r
232 remain at ulSecondNotifiedConst. */
\r
233 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );
\r
234 configASSERT( xReturned == pdPASS );
\r
235 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
236 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
237 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
\r
238 ( void ) ulNotifiedValue; /* In case configASSERT() is not defined. */
\r
243 /*-------------------------------------------------------------------------
\r
244 Check incrementing values. Send ulMaxLoop increment notifications, then
\r
245 ensure the received value is as expected - which should be
\r
246 ulSecondNotificationValueConst plus how ever many times to loop iterated. */
\r
247 for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
\r
249 xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );
\r
250 configASSERT( xReturned == pdPASS );
\r
251 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
254 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
255 configASSERT( xReturned == pdPASS );
\r
256 configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
\r
257 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
258 ( void ) ulNotifiedValue;
\r
260 /* Should not be any notifications pending now. */
\r
261 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
\r
262 configASSERT( xReturned == pdFAIL );
\r
263 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
264 ( void ) ulNotifiedValue;
\r
269 /*-------------------------------------------------------------------------
\r
270 Check all bits can be set by notifying the task with one additional bit set
\r
271 on each notification, and exiting the loop when all the bits are found to be
\r
272 set. As there are 32-bits the loop should execute 32 times before all the
\r
273 bits are found to be set. */
\r
274 ulNotifyingValue = 0x01;
\r
277 /* Start with all bits clear. */
\r
278 xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
282 /* Set the next bit in the task's notified value. */
\r
283 xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits );
\r
285 /* Wait for the notified value - which of course will already be
\r
286 available. Don't clear the bits on entry or exit as this loop is exited
\r
287 when all the bits are set. */
\r
288 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
\r
289 configASSERT( xReturned == pdPASS );
\r
290 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
294 /* Use the next bit on the next iteration around this loop. */
\r
295 ulNotifyingValue <<= 1UL;
\r
297 } while ( ulNotifiedValue != notifyUINT32_MAX );
\r
299 /* As a 32-bit value was used the loop should have executed 32 times before
\r
300 all the bits were set. */
\r
301 configASSERT( ulLoop == 32 );
\r
306 /*-------------------------------------------------------------------------
\r
307 Check bits are cleared on entry but not on exit when a notification fails
\r
308 to arrive before timing out - both with and without a timeout value. Wait
\r
309 for the notification again - but this time it is not given by anything and
\r
310 should return pdFAIL. The parameters are set to clear bit zero on entry and
\r
311 bit one on exit. As no notification was received only the bit cleared on
\r
312 entry should actually get cleared. */
\r
313 xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
\r
314 configASSERT( xReturned == pdFAIL );
\r
315 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
317 /* Notify the task with no action so as not to update the bits even though
\r
318 notifyUINT32_MAX is used as the notification value. */
\r
319 xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eNoAction );
\r
321 /* Reading back the value should should find bit 0 is clear, as this was
\r
322 cleared on entry, but bit 1 is not clear as it will not have been cleared on
\r
323 exit as no notification was received. */
\r
324 xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
\r
325 configASSERT( xReturned == pdPASS );
\r
326 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
\r
327 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
333 /*-------------------------------------------------------------------------
\r
334 Now try clearing the bit on exit. For that to happen a notification must be
\r
335 received, so the task is notified first. */
\r
336 xTaskNotify( xTaskToNotify, 0, eNoAction );
\r
337 xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 );
\r
339 /* However as the bit is cleared on exit, after the returned notification
\r
340 value is set, the returned notification value should not have the bit
\r
342 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
\r
344 /* ...but reading the value back again should find that the bit was indeed
\r
345 cleared internally. The returned value should be pdFAIL however as nothing
\r
346 has notified the task in the mean time. */
\r
347 xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );
\r
348 configASSERT( xReturned == pdFAIL );
\r
349 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
\r
350 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
355 /*-------------------------------------------------------------------------
\r
356 Now try querying the previous value while notifying a task. */
\r
357 xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
\r
358 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
\r
360 /* Clear all bits. */
\r
361 xTaskNotifyWait( 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
\r
362 xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
\r
363 configASSERT( ulPreviousValue == 0 );
\r
365 ulExpectedValue = 0;
\r
366 for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
\r
368 /* Set the next bit up, and expect to receive the last bits set (so
\r
369 the previous value will not yet have the bit being set this time
\r
371 xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue );
\r
372 configASSERT( ulExpectedValue == ulPreviousValue );
\r
373 ulExpectedValue |= ulLoop;
\r
378 /* ------------------------------------------------------------------------
\r
379 Clear the previous notifications. */
\r
380 xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
382 /* The task should not have any notifications pending, so an attempt to clear
\r
383 the notification state should fail. */
\r
384 configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
\r
386 /* Get the task to notify itself. This is not a normal thing to do, and is
\r
387 only done here for test purposes. */
\r
388 xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
\r
390 /* Now the notification state should be eNotified, so it should now be
\r
391 possible to clear the notification state. */
\r
392 configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
\r
393 configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
\r
397 /* ------------------------------------------------------------------------
\r
398 Create a timer that will try notifying this task while it is suspended. */
\r
399 xSingleTaskTimer = xTimerCreate( "SingleNotify", notifySUSPENDED_TEST_TIMER_PERIOD, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
\r
400 configASSERT( xSingleTaskTimer );
\r
402 /* Incremented to show the task is still running. */
\r
403 ulNotifyCycleCount++;
\r
405 /* Ensure no notifications are pending. */
\r
406 xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
\r
408 /* Raise the task's priority so it can suspend itself before the timer
\r
410 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
412 /* Start the timer that will try notifying this task while it is
\r
413 suspended, then wait for a notification. The first time the callback
\r
414 executes the timer will suspend the task, then resume the task, without
\r
415 ever sending a notification to the task. */
\r
416 ulNotifiedValue = 0;
\r
417 xTimerStart( xSingleTaskTimer, portMAX_DELAY );
\r
419 /* Check a notification is not received. */
\r
420 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );
\r
421 configASSERT( xReturned == pdFALSE );
\r
422 configASSERT( ulNotifiedValue == 0 );
\r
423 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
425 /* Incremented to show the task is still running. */
\r
426 ulNotifyCycleCount++;
\r
428 /* Start the timer that will try notifying this task while it is
\r
429 suspended, then wait for a notification. The second time the callback
\r
430 executes the timer will suspend the task, notify the task, then resume the
\r
431 task (previously it was suspended and resumed without being notified). */
\r
432 xTimerStart( xSingleTaskTimer, portMAX_DELAY );
\r
434 /* Check a notification is received. */
\r
435 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );
\r
436 configASSERT( xReturned == pdPASS );
\r
437 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
438 configASSERT( ulNotifiedValue != 0 );
\r
440 /* Return the task to its proper priority and delete the timer as it is
\r
442 vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
\r
443 xTimerDelete( xSingleTaskTimer, portMAX_DELAY );
\r
445 /* Incremented to show the task is still running. */
\r
446 ulNotifyCycleCount++;
\r
448 /* Leave all bits cleared. */
\r
449 xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
\r
451 /*-----------------------------------------------------------*/
\r
453 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
\r
455 static uint32_t ulCallCount = 0;
\r
457 /* Remove compiler warnings about unused parameters. */
\r
458 ( void ) xExpiredTimer;
\r
460 /* Callback for a timer that is used during preliminary testing. The timer
\r
461 tests the behaviour when 1: a task waiting for a notification is suspended
\r
462 and then resumed without ever receiving a notification, and 2: when a task
\r
463 waiting for a notification receives a notification while it is suspended. */
\r
465 if( ulCallCount == 0 )
\r
467 vTaskSuspend( xTaskToNotify );
\r
468 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
\r
469 vTaskResume( xTaskToNotify );
\r
473 vTaskSuspend( xTaskToNotify );
\r
475 /* Sending a notification while the task is suspended should pass, but
\r
476 not cause the task to resume. ulCallCount is just used as a convenient
\r
478 xTaskNotify( xTaskToNotify, ulCallCount, eSetValueWithOverwrite );
\r
480 /* Make sure giving the notification didn't resume the task. */
\r
481 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
\r
483 vTaskResume( xTaskToNotify );
\r
488 /*-----------------------------------------------------------*/
\r
490 static void prvNotifyingTimer( TimerHandle_t xNotUsed )
\r
494 xTaskNotifyGive( xTaskToNotify );
\r
496 /* This value is also incremented from an interrupt. */
\r
497 taskENTER_CRITICAL();
\r
499 ulTimerNotificationsSent++;
\r
501 taskEXIT_CRITICAL();
\r
503 /*-----------------------------------------------------------*/
\r
505 static void prvNotifiedTask( void *pvParameters )
\r
507 const TickType_t xMaxPeriod = pdMS_TO_TICKS( 90 ), xMinPeriod = pdMS_TO_TICKS( 10 ), xDontBlock = 0;
\r
508 TickType_t xPeriod;
\r
509 const uint32_t ulCyclesToRaisePriority = 50UL;
\r
511 /* Remove compiler warnings about unused parameters. */
\r
512 ( void ) pvParameters;
\r
514 /* Run a few tests that can be done from a single task before entering the
\r
516 prvSingleTaskTests();
\r
518 /* Create the software timer that is used to send notifications to this
\r
519 task. Notifications are also received from an interrupt. */
\r
520 xTimer = xTimerCreate( "Notifier", xMaxPeriod, pdFALSE, NULL, prvNotifyingTimer );
\r
524 /* Start the timer again with a different period. Sometimes the period
\r
525 will be higher than the task's block time, sometimes it will be lower
\r
526 than the task's block time. */
\r
527 xPeriod = prvRand() % xMaxPeriod;
\r
528 if( xPeriod < xMinPeriod )
\r
530 xPeriod = xMinPeriod;
\r
533 /* Change the timer period and start the timer. */
\r
534 xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );
\r
536 /* Block waiting for the notification again with a different period.
\r
537 Sometimes the period will be higher than the task's block time,
\r
538 sometimes it will be lower than the task's block time. */
\r
539 xPeriod = prvRand() % xMaxPeriod;
\r
540 if( xPeriod < xMinPeriod )
\r
542 xPeriod = xMinPeriod;
\r
545 /* Block to wait for a notification but without clearing the
\r
546 notification count, so only add one to the count of received
\r
547 notifications as any other notifications will remain pending. */
\r
548 if( ulTaskNotifyTake( pdFALSE, xPeriod ) != 0 )
\r
550 ulTimerNotificationsReceived++;
\r
554 /* Take a notification without clearing again, but this time without a
\r
555 block time specified. */
\r
556 if( ulTaskNotifyTake( pdFALSE, xDontBlock ) != 0 )
\r
558 ulTimerNotificationsReceived++;
\r
561 /* Wait for the next notification from the timer, clearing all
\r
562 notifications if one is received, so this time adding the total number
\r
563 of notifications that were pending as none will be left pending after
\r
564 the function call. */
\r
565 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );
\r
567 /* Occasionally raise the priority of the task being notified to test
\r
568 the path where the task is notified from an ISR and becomes the highest
\r
569 priority ready state task, but the pxHigherPriorityTaskWoken parameter
\r
570 is NULL (which it is in the tick hook that sends notifications to this
\r
572 if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )
\r
574 vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );
\r
576 /* Wait for the next notification again, clearing all notifications
\r
577 if one is received, but this time blocking indefinitely. */
\r
578 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
580 /* Reset the priority. */
\r
581 vTaskPrioritySet( xTaskToNotify, notifyTASK_PRIORITY );
\r
585 /* Wait for the next notification again, clearing all notifications
\r
586 if one is received, but this time blocking indefinitely. */
\r
587 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
590 /* Incremented to show the task is still running. */
\r
591 ulNotifyCycleCount++;
\r
594 /*-----------------------------------------------------------*/
\r
596 void xNotifyTaskFromISR( void )
\r
598 static BaseType_t xCallCount = 0, xAPIToUse = 0;
\r
599 const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
\r
600 uint32_t ulPreviousValue;
\r
601 const uint32_t ulUnexpectedValue = 0xff;
\r
603 /* The task performs some tests before starting the timer that gives the
\r
604 notification from this interrupt. If the timer has not been created yet
\r
605 then the initial tests have not yet completed and the notification should
\r
607 if( xTimer != NULL )
\r
611 if( xCallCount >= xCallInterval )
\r
613 /* It is time to 'give' the notification again. */
\r
616 /* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
\r
617 and xTaskNotifyAndQueryFromISR(). */
\r
618 switch( xAPIToUse )
\r
620 case 0: vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
\r
624 case 1: xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );
\r
628 case 2: ulPreviousValue = ulUnexpectedValue;
\r
629 xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );
\r
630 configASSERT( ulPreviousValue != ulUnexpectedValue );
\r
634 default:/* Should never get here!. */
\r
638 ulTimerNotificationsSent++;
\r
642 /*-----------------------------------------------------------*/
\r
644 /* This is called to check the created tasks are still running and have not
\r
645 detected any errors. */
\r
646 BaseType_t xAreTaskNotificationTasksStillRunning( void )
\r
648 static uint32_t ulLastNotifyCycleCount = 0;
\r
649 const uint32_t ulMaxSendReceiveDeviation = 5UL;
\r
651 /* Check the cycle count is still incrementing to ensure the task is still
\r
652 actually running. */
\r
653 if( ulLastNotifyCycleCount == ulNotifyCycleCount )
\r
655 xErrorStatus = pdFAIL;
\r
659 ulLastNotifyCycleCount = ulNotifyCycleCount;
\r
662 /* Check the count of 'takes' from the software timer is keeping track with
\r
663 the amount of 'gives'. */
\r
664 if( ulTimerNotificationsSent > ulTimerNotificationsReceived )
\r
666 if( ( ulTimerNotificationsSent - ulTimerNotificationsReceived ) > ulMaxSendReceiveDeviation )
\r
668 xErrorStatus = pdFAIL;
\r
672 return xErrorStatus;
\r
674 /*-----------------------------------------------------------*/
\r
676 static UBaseType_t prvRand( void )
\r
678 const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
\r
680 /* Utility function to generate a pseudo random number. */
\r
681 uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
\r
682 return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
\r
684 /*-----------------------------------------------------------*/
\r