2 * FreeRTOS Kernel V10.1.0
\r
3 * Copyright (C) 2018 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
30 * Tests the behaviour of direct task notifications.
\r
33 /* Standard includes. */
\r
36 /* Scheduler include files. */
\r
37 #include "FreeRTOS.h"
\r
41 /* Demo program include files. */
\r
42 #include "TaskNotify.h"
\r
44 #define notifyTASK_PRIORITY ( tskIDLE_PRIORITY )
\r
45 #define notifyUINT32_MAX ( ( uint32_t ) 0xffffffff )
\r
46 #define notifySUSPENDED_TEST_TIMER_PERIOD pdMS_TO_TICKS( 50 )
\r
48 /*-----------------------------------------------------------*/
\r
51 * Implementation of the task that gets notified.
\r
53 static void prvNotifiedTask( void *pvParameters );
\r
56 * Performs a few initial tests that can be done prior to creating the second
\r
59 static void prvSingleTaskTests( void );
\r
62 * Software timer callback function from which xTaskNotify() is called.
\r
64 static void prvNotifyingTimer( TimerHandle_t xTimer );
\r
67 * Utility function to create pseudo random numbers.
\r
69 static UBaseType_t prvRand( void );
\r
72 * Callback for a timer that is used during preliminary testing. The timer
\r
73 * tests the behaviour when 1: a task waiting for a notification is suspended
\r
74 * and then resumed without ever receiving a notification, and 2: when a task
\r
75 * waiting for a notification receives a notification while it is suspended.
\r
77 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
\r
79 /*-----------------------------------------------------------*/
\r
81 /* Used to latch errors during the test's execution. */
\r
82 static BaseType_t xErrorStatus = pdPASS;
\r
84 /* Used to ensure the task has not stalled. */
\r
85 static volatile uint32_t ulNotifyCycleCount = 0;
\r
87 /* The handle of the task that receives the notifications. */
\r
88 static TaskHandle_t xTaskToNotify = NULL;
\r
90 /* Used to count the notifications sent to the task from a software timer and
\r
91 the number of notifications received by the task from the software timer. The
\r
92 two should stay synchronised. */
\r
93 static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0UL;
\r
95 /* The timer used to notify the task. */
\r
96 static TimerHandle_t xTimer = NULL;
\r
98 /* Used by the pseudo random number generating function. */
\r
99 static size_t uxNextRand = 0;
\r
101 /*-----------------------------------------------------------*/
\r
103 void vStartTaskNotifyTask( void )
\r
105 /* Create the task that performs some tests by itself, then loops around
\r
106 being notified by both a software timer and an interrupt. */
\r
107 xTaskCreate( prvNotifiedTask, "Notified", configMINIMAL_STACK_SIZE, NULL, notifyTASK_PRIORITY, &xTaskToNotify );
\r
109 /* Pseudo seed the random number generator. */
\r
110 uxNextRand = ( size_t ) prvRand;
\r
112 /*-----------------------------------------------------------*/
\r
114 static void prvSingleTaskTests( void )
\r
116 const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
\r
117 BaseType_t xReturned;
\r
118 uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue;
\r
119 TickType_t xTimeOnEntering;
\r
120 const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;
\r
121 const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
\r
122 TimerHandle_t xSingleTaskTimer;
\r
125 /* ------------------------------------------------------------------------
\r
126 Check blocking when there are no notifications. */
\r
127 xTimeOnEntering = xTaskGetTickCount();
\r
128 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
\r
129 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
131 /* Should have blocked for the entire block time. */
\r
132 if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait )
\r
134 xErrorStatus = pdFAIL;
\r
136 configASSERT( xReturned == pdFAIL );
\r
137 configASSERT( ulNotifiedValue == 0UL );
\r
138 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
139 ( void ) ulNotifiedValue;
\r
144 /* ------------------------------------------------------------------------
\r
145 Check no blocking when notifications are pending. First notify itself -
\r
146 this would not be a normal thing to do and is done here for test purposes
\r
148 xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
\r
150 /* Even through the 'without overwrite' action was used the update should
\r
151 have been successful. */
\r
152 configASSERT( xReturned == pdPASS );
\r
153 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
155 /* No bits should have been pending previously. */
\r
156 configASSERT( ulPreviousValue == 0 );
\r
157 ( void ) ulPreviousValue;
\r
159 /* The task should now have a notification pending, and so not time out. */
\r
160 xTimeOnEntering = xTaskGetTickCount();
\r
161 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
\r
163 if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait )
\r
165 xErrorStatus = pdFAIL;
\r
168 /* The task should have been notified, and the notified value should
\r
169 be equal to ulFirstNotifiedConst. */
\r
170 configASSERT( xReturned == pdPASS );
\r
171 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
\r
172 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
173 ( void ) ulNotifiedValue;
\r
175 /* Incremented to show the task is still running. */
\r
176 ulNotifyCycleCount++;
\r
182 /*-------------------------------------------------------------------------
\r
183 Check the non-overwriting functionality. The notification is done twice
\r
184 using two different notification values. The action says don't overwrite so
\r
185 only the first notification should pass and the value read back should also
\r
186 be that used with the first notification. */
\r
187 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
\r
188 configASSERT( xReturned == pdPASS );
\r
189 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
191 xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
\r
192 configASSERT( xReturned == pdFAIL );
\r
193 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
195 /* Waiting for the notification should now return immediately so a block
\r
196 time of zero is used. */
\r
197 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
199 configASSERT( xReturned == pdPASS );
\r
200 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
\r
201 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
202 ( void ) ulNotifiedValue;
\r
208 /*-------------------------------------------------------------------------
\r
209 Do the same again, only this time use the overwriting version. This time
\r
210 both notifications should pass, and the value written the second time should
\r
211 overwrite the value written the first time, and so be the value that is read
\r
213 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );
\r
214 configASSERT( xReturned == pdPASS );
\r
215 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
216 xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
\r
217 configASSERT( xReturned == pdPASS );
\r
218 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
219 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
220 configASSERT( xReturned == pdPASS );
\r
221 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
222 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
\r
223 ( void ) ulNotifiedValue;
\r
228 /*-------------------------------------------------------------------------
\r
229 Check notifications with no action pass without updating the value. Even
\r
230 though ulFirstNotifiedConst is used as the value the value read back should
\r
231 remain at ulSecondNotifiedConst. */
\r
232 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );
\r
233 configASSERT( xReturned == pdPASS );
\r
234 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
235 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
236 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
\r
237 ( void ) ulNotifiedValue; /* In case configASSERT() is not defined. */
\r
242 /*-------------------------------------------------------------------------
\r
243 Check incrementing values. Send ulMaxLoop increment notifications, then
\r
244 ensure the received value is as expected - which should be
\r
245 ulSecondNotificationValueConst plus how ever many times to loop iterated. */
\r
246 for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
\r
248 xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );
\r
249 configASSERT( xReturned == pdPASS );
\r
250 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
253 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
254 configASSERT( xReturned == pdPASS );
\r
255 configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
\r
256 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
257 ( void ) ulNotifiedValue;
\r
259 /* Should not be any notifications pending now. */
\r
260 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
\r
261 configASSERT( xReturned == pdFAIL );
\r
262 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
263 ( void ) ulNotifiedValue;
\r
268 /*-------------------------------------------------------------------------
\r
269 Check all bits can be set by notifying the task with one additional bit set
\r
270 on each notification, and exiting the loop when all the bits are found to be
\r
271 set. As there are 32-bits the loop should execute 32 times before all the
\r
272 bits are found to be set. */
\r
273 ulNotifyingValue = 0x01;
\r
276 /* Start with all bits clear. */
\r
277 xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
281 /* Set the next bit in the task's notified value. */
\r
282 xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits );
\r
284 /* Wait for the notified value - which of course will already be
\r
285 available. Don't clear the bits on entry or exit as this loop is exited
\r
286 when all the bits are set. */
\r
287 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
\r
288 configASSERT( xReturned == pdPASS );
\r
289 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
293 /* Use the next bit on the next iteration around this loop. */
\r
294 ulNotifyingValue <<= 1UL;
\r
296 } while ( ulNotifiedValue != notifyUINT32_MAX );
\r
298 /* As a 32-bit value was used the loop should have executed 32 times before
\r
299 all the bits were set. */
\r
300 configASSERT( ulLoop == 32 );
\r
305 /*-------------------------------------------------------------------------
\r
306 Check bits are cleared on entry but not on exit when a notification fails
\r
307 to arrive before timing out - both with and without a timeout value. Wait
\r
308 for the notification again - but this time it is not given by anything and
\r
309 should return pdFAIL. The parameters are set to clear bit zero on entry and
\r
310 bit one on exit. As no notification was received only the bit cleared on
\r
311 entry should actually get cleared. */
\r
312 xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
\r
313 configASSERT( xReturned == pdFAIL );
\r
314 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
316 /* Notify the task with no action so as not to update the bits even though
\r
317 notifyUINT32_MAX is used as the notification value. */
\r
318 xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eNoAction );
\r
320 /* Reading back the value should should find bit 0 is clear, as this was
\r
321 cleared on entry, but bit 1 is not clear as it will not have been cleared on
\r
322 exit as no notification was received. */
\r
323 xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
\r
324 configASSERT( xReturned == pdPASS );
\r
325 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
\r
326 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
332 /*-------------------------------------------------------------------------
\r
333 Now try clearing the bit on exit. For that to happen a notification must be
\r
334 received, so the task is notified first. */
\r
335 xTaskNotify( xTaskToNotify, 0, eNoAction );
\r
336 xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 );
\r
338 /* However as the bit is cleared on exit, after the returned notification
\r
339 value is set, the returned notification value should not have the bit
\r
341 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
\r
343 /* ...but reading the value back again should find that the bit was indeed
\r
344 cleared internally. The returned value should be pdFAIL however as nothing
\r
345 has notified the task in the mean time. */
\r
346 xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );
\r
347 configASSERT( xReturned == pdFAIL );
\r
348 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
\r
349 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
354 /*-------------------------------------------------------------------------
\r
355 Now try querying the previous value while notifying a task. */
\r
356 xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
\r
357 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
\r
359 /* Clear all bits. */
\r
360 xTaskNotifyWait( 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
\r
361 xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
\r
362 configASSERT( ulPreviousValue == 0 );
\r
364 ulExpectedValue = 0;
\r
365 for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
\r
367 /* Set the next bit up, and expect to receive the last bits set (so
\r
368 the previous value will not yet have the bit being set this time
\r
370 xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue );
\r
371 configASSERT( ulExpectedValue == ulPreviousValue );
\r
372 ulExpectedValue |= ulLoop;
\r
377 /* ------------------------------------------------------------------------
\r
378 Clear the previous notifications. */
\r
379 xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
381 /* The task should not have any notifications pending, so an attempt to clear
\r
382 the notification state should fail. */
\r
383 configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
\r
385 /* Get the task to notify itself. This is not a normal thing to do, and is
\r
386 only done here for test purposes. */
\r
387 xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
\r
389 /* Now the notification state should be eNotified, so it should now be
\r
390 possible to clear the notification state. */
\r
391 configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
\r
392 configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
\r
396 /* ------------------------------------------------------------------------
\r
397 Create a timer that will try notifying this task while it is suspended. */
\r
398 xSingleTaskTimer = xTimerCreate( "SingleNotify", notifySUSPENDED_TEST_TIMER_PERIOD, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
\r
399 configASSERT( xSingleTaskTimer );
\r
401 /* Incremented to show the task is still running. */
\r
402 ulNotifyCycleCount++;
\r
404 /* Ensure no notifications are pending. */
\r
405 xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
\r
407 /* Raise the task's priority so it can suspend itself before the timer
\r
409 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
411 /* Start the timer that will try notifying this task while it is
\r
412 suspended, then wait for a notification. The first time the callback
\r
413 executes the timer will suspend the task, then resume the task, without
\r
414 ever sending a notification to the task. */
\r
415 ulNotifiedValue = 0;
\r
416 xTimerStart( xSingleTaskTimer, portMAX_DELAY );
\r
418 /* Check a notification is not received. */
\r
419 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );
\r
420 configASSERT( xReturned == pdFALSE );
\r
421 configASSERT( ulNotifiedValue == 0 );
\r
422 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
424 /* Incremented to show the task is still running. */
\r
425 ulNotifyCycleCount++;
\r
427 /* Start the timer that will try notifying this task while it is
\r
428 suspended, then wait for a notification. The second time the callback
\r
429 executes the timer will suspend the task, notify the task, then resume the
\r
430 task (previously it was suspended and resumed without being notified). */
\r
431 xTimerStart( xSingleTaskTimer, portMAX_DELAY );
\r
433 /* Check a notification is received. */
\r
434 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );
\r
435 configASSERT( xReturned == pdPASS );
\r
436 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
437 configASSERT( ulNotifiedValue != 0 );
\r
439 /* Return the task to its proper priority and delete the timer as it is
\r
441 vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
\r
442 xTimerDelete( xSingleTaskTimer, portMAX_DELAY );
\r
444 /* Incremented to show the task is still running. */
\r
445 ulNotifyCycleCount++;
\r
447 /* Leave all bits cleared. */
\r
448 xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
\r
450 /*-----------------------------------------------------------*/
\r
452 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
\r
454 static uint32_t ulCallCount = 0;
\r
456 /* Remove compiler warnings about unused parameters. */
\r
457 ( void ) xExpiredTimer;
\r
459 /* Callback for a timer that is used during preliminary testing. The timer
\r
460 tests the behaviour when 1: a task waiting for a notification is suspended
\r
461 and then resumed without ever receiving a notification, and 2: when a task
\r
462 waiting for a notification receives a notification while it is suspended. */
\r
464 if( ulCallCount == 0 )
\r
466 vTaskSuspend( xTaskToNotify );
\r
467 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
\r
468 vTaskResume( xTaskToNotify );
\r
472 vTaskSuspend( xTaskToNotify );
\r
474 /* Sending a notification while the task is suspended should pass, but
\r
475 not cause the task to resume. ulCallCount is just used as a convenient
\r
477 xTaskNotify( xTaskToNotify, ulCallCount, eSetValueWithOverwrite );
\r
479 /* Make sure giving the notification didn't resume the task. */
\r
480 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
\r
482 vTaskResume( xTaskToNotify );
\r
487 /*-----------------------------------------------------------*/
\r
489 static void prvNotifyingTimer( TimerHandle_t xNotUsed )
\r
493 xTaskNotifyGive( xTaskToNotify );
\r
495 /* This value is also incremented from an interrupt. */
\r
496 taskENTER_CRITICAL();
\r
498 ulTimerNotificationsSent++;
\r
500 taskEXIT_CRITICAL();
\r
502 /*-----------------------------------------------------------*/
\r
504 static void prvNotifiedTask( void *pvParameters )
\r
506 const TickType_t xMaxPeriod = pdMS_TO_TICKS( 90 ), xMinPeriod = pdMS_TO_TICKS( 10 ), xDontBlock = 0;
\r
507 TickType_t xPeriod;
\r
508 const uint32_t ulCyclesToRaisePriority = 50UL;
\r
510 /* Remove compiler warnings about unused parameters. */
\r
511 ( void ) pvParameters;
\r
513 /* Run a few tests that can be done from a single task before entering the
\r
515 prvSingleTaskTests();
\r
517 /* Create the software timer that is used to send notifications to this
\r
518 task. Notifications are also received from an interrupt. */
\r
519 xTimer = xTimerCreate( "Notifier", xMaxPeriod, pdFALSE, NULL, prvNotifyingTimer );
\r
523 /* Start the timer again with a different period. Sometimes the period
\r
524 will be higher than the task's block time, sometimes it will be lower
\r
525 than the task's block time. */
\r
526 xPeriod = prvRand() % xMaxPeriod;
\r
527 if( xPeriod < xMinPeriod )
\r
529 xPeriod = xMinPeriod;
\r
532 /* Change the timer period and start the timer. */
\r
533 xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );
\r
535 /* Block waiting for the notification again with a different period.
\r
536 Sometimes the period will be higher than the task's block time,
\r
537 sometimes it will be lower than the task's block time. */
\r
538 xPeriod = prvRand() % xMaxPeriod;
\r
539 if( xPeriod < xMinPeriod )
\r
541 xPeriod = xMinPeriod;
\r
544 /* Block to wait for a notification but without clearing the
\r
545 notification count, so only add one to the count of received
\r
546 notifications as any other notifications will remain pending. */
\r
547 if( ulTaskNotifyTake( pdFALSE, xPeriod ) != 0 )
\r
549 ulTimerNotificationsReceived++;
\r
553 /* Take a notification without clearing again, but this time without a
\r
554 block time specified. */
\r
555 if( ulTaskNotifyTake( pdFALSE, xDontBlock ) != 0 )
\r
557 ulTimerNotificationsReceived++;
\r
560 /* Wait for the next notification from the timer, clearing all
\r
561 notifications if one is received, so this time adding the total number
\r
562 of notifications that were pending as none will be left pending after
\r
563 the function call. */
\r
564 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );
\r
566 /* Occasionally raise the priority of the task being notified to test
\r
567 the path where the task is notified from an ISR and becomes the highest
\r
568 priority ready state task, but the pxHigherPriorityTaskWoken parameter
\r
569 is NULL (which it is in the tick hook that sends notifications to this
\r
571 if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )
\r
573 vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );
\r
575 /* Wait for the next notification again, clearing all notifications
\r
576 if one is received, but this time blocking indefinitely. */
\r
577 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
579 /* Reset the priority. */
\r
580 vTaskPrioritySet( xTaskToNotify, notifyTASK_PRIORITY );
\r
584 /* Wait for the next notification again, clearing all notifications
\r
585 if one is received, but this time blocking indefinitely. */
\r
586 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
589 /* Incremented to show the task is still running. */
\r
590 ulNotifyCycleCount++;
\r
593 /*-----------------------------------------------------------*/
\r
595 void xNotifyTaskFromISR( void )
\r
597 static BaseType_t xCallCount = 0, xAPIToUse = 0;
\r
598 const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
\r
599 uint32_t ulPreviousValue;
\r
600 const uint32_t ulUnexpectedValue = 0xff;
\r
602 /* The task performs some tests before starting the timer that gives the
\r
603 notification from this interrupt. If the timer has not been created yet
\r
604 then the initial tests have not yet completed and the notification should
\r
606 if( xTimer != NULL )
\r
610 if( xCallCount >= xCallInterval )
\r
612 /* It is time to 'give' the notification again. */
\r
615 /* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
\r
616 and xTaskNotifyAndQueryFromISR(). */
\r
617 switch( xAPIToUse )
\r
619 case 0: vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
\r
623 case 1: xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );
\r
627 case 2: ulPreviousValue = ulUnexpectedValue;
\r
628 xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );
\r
629 configASSERT( ulPreviousValue != ulUnexpectedValue );
\r
633 default:/* Should never get here!. */
\r
637 ulTimerNotificationsSent++;
\r
641 /*-----------------------------------------------------------*/
\r
643 /* This is called to check the created tasks are still running and have not
\r
644 detected any errors. */
\r
645 BaseType_t xAreTaskNotificationTasksStillRunning( void )
\r
647 static uint32_t ulLastNotifyCycleCount = 0;
\r
648 const uint32_t ulMaxSendReceiveDeviation = 5UL;
\r
650 /* Check the cycle count is still incrementing to ensure the task is still
\r
651 actually running. */
\r
652 if( ulLastNotifyCycleCount == ulNotifyCycleCount )
\r
654 xErrorStatus = pdFAIL;
\r
658 ulLastNotifyCycleCount = ulNotifyCycleCount;
\r
661 /* Check the count of 'takes' from the software timer is keeping track with
\r
662 the amount of 'gives'. */
\r
663 if( ulTimerNotificationsSent > ulTimerNotificationsReceived )
\r
665 if( ( ulTimerNotificationsSent - ulTimerNotificationsReceived ) > ulMaxSendReceiveDeviation )
\r
667 xErrorStatus = pdFAIL;
\r
671 return xErrorStatus;
\r
673 /*-----------------------------------------------------------*/
\r
675 static UBaseType_t prvRand( void )
\r
677 const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
\r
679 /* Utility function to generate a pseudo random number. */
\r
680 uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
\r
681 return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
\r
683 /*-----------------------------------------------------------*/
\r