2 FreeRTOS V9.0.1 - Copyright (C) 2017 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
72 * Tests the behaviour of direct task notifications.
\r
75 /* Standard includes. */
\r
78 /* Scheduler include files. */
\r
79 #include "FreeRTOS.h"
\r
83 /* Demo program include files. */
\r
84 #include "TaskNotify.h"
\r
86 #define notifyTASK_PRIORITY ( tskIDLE_PRIORITY )
\r
87 #define notifyUINT32_MAX ( ( uint32_t ) 0xffffffff )
\r
88 #define notifySUSPENDED_TEST_TIMER_PERIOD pdMS_TO_TICKS( 50 )
\r
90 /*-----------------------------------------------------------*/
\r
93 * Implementation of the task that gets notified.
\r
95 static void prvNotifiedTask( void *pvParameters );
\r
98 * Performs a few initial tests that can be done prior to creating the second
\r
101 static void prvSingleTaskTests( void );
\r
104 * Software timer callback function from which xTaskNotify() is called.
\r
106 static void prvNotifyingTimer( TimerHandle_t xTimer );
\r
109 * Utility function to create pseudo random numbers.
\r
111 static UBaseType_t prvRand( void );
\r
114 * Callback for a timer that is used during preliminary testing. The timer
\r
115 * tests the behaviour when 1: a task waiting for a notification is suspended
\r
116 * and then resumed without ever receiving a notification, and 2: when a task
\r
117 * waiting for a notification receives a notification while it is suspended.
\r
119 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
\r
121 /*-----------------------------------------------------------*/
\r
123 /* Used to latch errors during the test's execution. */
\r
124 static BaseType_t xErrorStatus = pdPASS;
\r
126 /* Used to ensure the task has not stalled. */
\r
127 static volatile uint32_t ulNotifyCycleCount = 0;
\r
129 /* The handle of the task that receives the notifications. */
\r
130 static TaskHandle_t xTaskToNotify = NULL;
\r
132 /* Used to count the notifications sent to the task from a software timer and
\r
133 the number of notifications received by the task from the software timer. The
\r
134 two should stay synchronised. */
\r
135 static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0UL;
\r
137 /* The timer used to notify the task. */
\r
138 static TimerHandle_t xTimer = NULL;
\r
140 /* Used by the pseudo random number generating function. */
\r
141 static size_t uxNextRand = 0;
\r
143 /*-----------------------------------------------------------*/
\r
145 void vStartTaskNotifyTask( void )
\r
147 /* Create the task that performs some tests by itself, then loops around
\r
148 being notified by both a software timer and an interrupt. */
\r
149 xTaskCreate( prvNotifiedTask, "Notified", configMINIMAL_STACK_SIZE, NULL, notifyTASK_PRIORITY, &xTaskToNotify );
\r
151 /* Pseudo seed the random number generator. */
\r
152 uxNextRand = ( size_t ) prvRand;
\r
154 /*-----------------------------------------------------------*/
\r
156 static void prvSingleTaskTests( void )
\r
158 const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
\r
159 BaseType_t xReturned;
\r
160 uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue;
\r
161 TickType_t xTimeOnEntering;
\r
162 const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;
\r
163 const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
\r
164 TimerHandle_t xSingleTaskTimer;
\r
167 /* ------------------------------------------------------------------------
\r
168 Check blocking when there are no notifications. */
\r
169 xTimeOnEntering = xTaskGetTickCount();
\r
170 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
\r
172 /* Should have blocked for the entire block time. */
\r
173 if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait )
\r
175 xErrorStatus = pdFAIL;
\r
177 configASSERT( xReturned == pdFAIL );
\r
178 configASSERT( ulNotifiedValue == 0UL );
\r
183 /* ------------------------------------------------------------------------
\r
184 Check no blocking when notifications are pending. First notify itself -
\r
185 this would not be a normal thing to do and is done here for test purposes
\r
187 xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
\r
189 /* Even through the 'without overwrite' action was used the update should
\r
190 have been successful. */
\r
191 configASSERT( xReturned == pdPASS );
\r
193 /* No bits should have been pending previously. */
\r
194 configASSERT( ulPreviousValue == 0 );
\r
196 /* The task should now have a notification pending, and so not time out. */
\r
197 xTimeOnEntering = xTaskGetTickCount();
\r
198 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
\r
200 if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait )
\r
202 xErrorStatus = pdFAIL;
\r
205 /* The task should have been notified, and the notified value should
\r
206 be equal to ulFirstNotifiedConst. */
\r
207 configASSERT( xReturned == pdPASS );
\r
208 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
\r
210 /* Incremented to show the task is still running. */
\r
211 ulNotifyCycleCount++;
\r
217 /*-------------------------------------------------------------------------
\r
218 Check the non-overwriting functionality. The notification is done twice
\r
219 using two different notification values. The action says don't overwrite so
\r
220 only the first notification should pass and the value read back should also
\r
221 be that used with the first notification. */
\r
222 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
\r
223 configASSERT( xReturned == pdPASS );
\r
225 xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
\r
226 configASSERT( xReturned == pdFAIL );
\r
228 /* Waiting for the notification should now return immediately so a block
\r
229 time of zero is used. */
\r
230 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
232 configASSERT( xReturned == pdPASS );
\r
233 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
\r
239 /*-------------------------------------------------------------------------
\r
240 Do the same again, only this time use the overwriting version. This time
\r
241 both notifications should pass, and the value written the second time should
\r
242 overwrite the value written the first time, and so be the value that is read
\r
244 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );
\r
245 configASSERT( xReturned == pdPASS );
\r
246 xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
\r
247 configASSERT( xReturned == pdPASS );
\r
248 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
249 configASSERT( xReturned == pdPASS );
\r
250 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
\r
255 /*-------------------------------------------------------------------------
\r
256 Check notifications with no action pass without updating the value. Even
\r
257 though ulFirstNotifiedConst is used as the value the value read back should
\r
258 remain at ulSecondNotifiedConst. */
\r
259 xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );
\r
260 configASSERT( xReturned == pdPASS );
\r
261 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
262 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
\r
267 /*-------------------------------------------------------------------------
\r
268 Check incrementing values. Send ulMaxLoop increment notifications, then
\r
269 ensure the received value is as expected - which should be
\r
270 ulSecondNotificationValueConst plus how ever many times to loop iterated. */
\r
271 for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
\r
273 xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );
\r
274 configASSERT( xReturned == pdPASS );
\r
277 xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
278 configASSERT( xReturned == pdPASS );
\r
279 configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
\r
281 /* Should not be any notifications pending now. */
\r
282 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
\r
283 configASSERT( xReturned == pdFAIL );
\r
288 /*-------------------------------------------------------------------------
\r
289 Check all bits can be set by notifying the task with one additional bit set
\r
290 on each notification, and exiting the loop when all the bits are found to be
\r
291 set. As there are 32-bits the loop should execute 32 times before all the
\r
292 bits are found to be set. */
\r
293 ulNotifyingValue = 0x01;
\r
296 /* Start with all bits clear. */
\r
297 xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
301 /* Set the next bit in the task's notified value. */
\r
302 xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits );
\r
304 /* Wait for the notified value - which of course will already be
\r
305 available. Don't clear the bits on entry or exit as this loop is exited
\r
306 when all the bits are set. */
\r
307 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
\r
308 configASSERT( xReturned == pdPASS );
\r
312 /* Use the next bit on the next iteration around this loop. */
\r
313 ulNotifyingValue <<= 1UL;
\r
315 } while ( ulNotifiedValue != notifyUINT32_MAX );
\r
317 /* As a 32-bit value was used the loop should have executed 32 times before
\r
318 all the bits were set. */
\r
319 configASSERT( ulLoop == 32 );
\r
324 /*-------------------------------------------------------------------------
\r
325 Check bits are cleared on entry but not on exit when a notification fails
\r
326 to arrive before timing out - both with and without a timeout value. Wait
\r
327 for the notification again - but this time it is not given by anything and
\r
328 should return pdFAIL. The parameters are set to clear bit zero on entry and
\r
329 bit one on exit. As no notification was received only the bit cleared on
\r
330 entry should actually get cleared. */
\r
331 xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
\r
332 configASSERT( xReturned == pdFAIL );
\r
334 /* Notify the task with no action so as not to update the bits even though
\r
335 notifyUINT32_MAX is used as the notification value. */
\r
336 xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eNoAction );
\r
338 /* Reading back the value should should find bit 0 is clear, as this was
\r
339 cleared on entry, but bit 1 is not clear as it will not have been cleared on
\r
340 exit as no notification was received. */
\r
341 xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
\r
342 configASSERT( xReturned == pdPASS );
\r
343 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
\r
349 /*-------------------------------------------------------------------------
\r
350 Now try clearing the bit on exit. For that to happen a notification must be
\r
351 received, so the task is notified first. */
\r
352 xTaskNotify( xTaskToNotify, 0, eNoAction );
\r
353 xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 );
\r
355 /* However as the bit is cleared on exit, after the returned notification
\r
356 value is set, the returned notification value should not have the bit
\r
358 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
\r
360 /* ...but reading the value back again should find that the bit was indeed
\r
361 cleared internally. The returned value should be pdFAIL however as nothing
\r
362 has notified the task in the mean time. */
\r
363 xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );
\r
364 configASSERT( xReturned == pdFAIL );
\r
365 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
\r
370 /*-------------------------------------------------------------------------
\r
371 Now try querying the previous value while notifying a task. */
\r
372 xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
\r
373 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
\r
375 /* Clear all bits. */
\r
376 xTaskNotifyWait( 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
\r
377 xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
\r
378 configASSERT( ulPreviousValue == 0 );
\r
380 ulExpectedValue = 0;
\r
381 for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
\r
383 /* Set the next bit up, and expect to receive the last bits set (so
\r
384 the previous value will not yet have the bit being set this time
\r
386 xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue );
\r
387 configASSERT( ulExpectedValue == ulPreviousValue );
\r
388 ulExpectedValue |= ulLoop;
\r
393 /* ------------------------------------------------------------------------
\r
394 Clear the previous notifications. */
\r
395 xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
\r
397 /* The task should not have any notifications pending, so an attempt to clear
\r
398 the notification state should fail. */
\r
399 configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
\r
401 /* Get the task to notify itself. This is not a normal thing to do, and is
\r
402 only done here for test purposes. */
\r
403 xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
\r
405 /* Now the notification state should be eNotified, so it should now be
\r
406 possible to clear the notification state. */
\r
407 configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
\r
408 configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
\r
412 /* ------------------------------------------------------------------------
\r
413 Create a timer that will try notifying this task while it is suspended. */
\r
414 xSingleTaskTimer = xTimerCreate( "SingleNotify", notifySUSPENDED_TEST_TIMER_PERIOD, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
\r
415 configASSERT( xSingleTaskTimer );
\r
417 /* Incremented to show the task is still running. */
\r
418 ulNotifyCycleCount++;
\r
420 /* Ensure no notifications are pending. */
\r
421 xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
\r
423 /* Raise the task's priority so it can suspend itself before the timer
\r
425 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
427 /* Start the timer that will try notifying this task while it is
\r
428 suspended, then wait for a notification. The first time the callback
\r
429 executes the timer will suspend the task, then resume the task, without
\r
430 ever sending a notification to the task. */
\r
431 ulNotifiedValue = 0;
\r
432 xTimerStart( xSingleTaskTimer, portMAX_DELAY );
\r
434 /* Check a notification is not received. */
\r
435 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );
\r
436 configASSERT( xReturned == pdFALSE );
\r
437 configASSERT( ulNotifiedValue == 0 );
\r
439 /* Incremented to show the task is still running. */
\r
440 ulNotifyCycleCount++;
\r
442 /* Start the timer that will try notifying this task while it is
\r
443 suspended, then wait for a notification. The second time the callback
\r
444 executes the timer will suspend the task, notify the task, then resume the
\r
445 task (previously it was suspended and resumed without being notified). */
\r
446 xTimerStart( xSingleTaskTimer, portMAX_DELAY );
\r
448 /* Check a notification is received. */
\r
449 xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );
\r
450 configASSERT( xReturned == pdPASS );
\r
451 configASSERT( ulNotifiedValue != 0 );
\r
453 /* Return the task to its proper priority and delete the timer as it is
\r
455 vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
\r
456 xTimerDelete( xSingleTaskTimer, portMAX_DELAY );
\r
458 /* Incremented to show the task is still running. */
\r
459 ulNotifyCycleCount++;
\r
461 /* Leave all bits cleared. */
\r
462 xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
\r
464 /*-----------------------------------------------------------*/
\r
466 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
\r
468 static uint32_t ulCallCount = 0;
\r
470 /* Remove compiler warnings about unused parameters. */
\r
471 ( void ) xExpiredTimer;
\r
473 /* Callback for a timer that is used during preliminary testing. The timer
\r
474 tests the behaviour when 1: a task waiting for a notification is suspended
\r
475 and then resumed without ever receiving a notification, and 2: when a task
\r
476 waiting for a notification receives a notification while it is suspended. */
\r
478 if( ulCallCount == 0 )
\r
480 vTaskSuspend( xTaskToNotify );
\r
481 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
\r
482 vTaskResume( xTaskToNotify );
\r
486 vTaskSuspend( xTaskToNotify );
\r
488 /* Sending a notification while the task is suspended should pass, but
\r
489 not cause the task to resume. ulCallCount is just used as a convenient
\r
491 xTaskNotify( xTaskToNotify, ulCallCount, eSetValueWithOverwrite );
\r
493 /* Make sure giving the notification didn't resume the task. */
\r
494 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
\r
496 vTaskResume( xTaskToNotify );
\r
501 /*-----------------------------------------------------------*/
\r
503 static void prvNotifyingTimer( TimerHandle_t xNotUsed )
\r
507 xTaskNotifyGive( xTaskToNotify );
\r
509 /* This value is also incremented from an interrupt. */
\r
510 taskENTER_CRITICAL();
\r
512 ulTimerNotificationsSent++;
\r
514 taskEXIT_CRITICAL();
\r
516 /*-----------------------------------------------------------*/
\r
518 static void prvNotifiedTask( void *pvParameters )
\r
520 const TickType_t xMaxPeriod = pdMS_TO_TICKS( 90 ), xMinPeriod = pdMS_TO_TICKS( 10 ), xDontBlock = 0;
\r
521 TickType_t xPeriod;
\r
522 const uint32_t ulCyclesToRaisePriority = 50UL;
\r
524 /* Remove compiler warnings about unused parameters. */
\r
525 ( void ) pvParameters;
\r
527 /* Run a few tests that can be done from a single task before entering the
\r
529 prvSingleTaskTests();
\r
531 /* Create the software timer that is used to send notifications to this
\r
532 task. Notifications are also received from an interrupt. */
\r
533 xTimer = xTimerCreate( "Notifier", xMaxPeriod, pdFALSE, NULL, prvNotifyingTimer );
\r
537 /* Start the timer again with a different period. Sometimes the period
\r
538 will be higher than the task's block time, sometimes it will be lower
\r
539 than the task's block time. */
\r
540 xPeriod = prvRand() % xMaxPeriod;
\r
541 if( xPeriod < xMinPeriod )
\r
543 xPeriod = xMinPeriod;
\r
546 /* Change the timer period and start the timer. */
\r
547 xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );
\r
549 /* Block waiting for the notification again with a different period.
\r
550 Sometimes the period will be higher than the task's block time,
\r
551 sometimes it will be lower than the task's block time. */
\r
552 xPeriod = prvRand() % xMaxPeriod;
\r
553 if( xPeriod < xMinPeriod )
\r
555 xPeriod = xMinPeriod;
\r
558 /* Block to wait for a notification but without clearing the
\r
559 notification count, so only add one to the count of received
\r
560 notifications as any other notifications will remain pending. */
\r
561 if( ulTaskNotifyTake( pdFALSE, xPeriod ) != 0 )
\r
563 ulTimerNotificationsReceived++;
\r
567 /* Take a notification without clearing again, but this time without a
\r
568 block time specified. */
\r
569 if( ulTaskNotifyTake( pdFALSE, xDontBlock ) != 0 )
\r
571 ulTimerNotificationsReceived++;
\r
574 /* Wait for the next notification from the timer, clearing all
\r
575 notifications if one is received, so this time adding the total number
\r
576 of notifications that were pending as none will be left pending after
\r
577 the function call. */
\r
578 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );
\r
580 /* Occasionally raise the priority of the task being notified to test
\r
581 the path where the task is notified from an ISR and becomes the highest
\r
582 priority ready state task, but the pxHigherPriorityTaskWoken parameter
\r
583 is NULL (which it is in the tick hook that sends notifications to this
\r
585 if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )
\r
587 vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );
\r
589 /* Wait for the next notification again, clearing all notifications
\r
590 if one is received, but this time blocking indefinitely. */
\r
591 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
593 /* Reset the priority. */
\r
594 vTaskPrioritySet( xTaskToNotify, notifyTASK_PRIORITY );
\r
598 /* Wait for the next notification again, clearing all notifications
\r
599 if one is received, but this time blocking indefinitely. */
\r
600 ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
603 /* Incremented to show the task is still running. */
\r
604 ulNotifyCycleCount++;
\r
607 /*-----------------------------------------------------------*/
\r
609 void xNotifyTaskFromISR( void )
\r
611 static BaseType_t xCallCount = 0, xAPIToUse = 0;
\r
612 const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
\r
613 uint32_t ulPreviousValue;
\r
614 const uint32_t ulUnexpectedValue = 0xff;
\r
616 /* The task performs some tests before starting the timer that gives the
\r
617 notification from this interrupt. If the timer has not been created yet
\r
618 then the initial tests have not yet completed and the notification should
\r
620 if( xTimer != NULL )
\r
624 if( xCallCount >= xCallInterval )
\r
626 /* It is time to 'give' the notification again. */
\r
629 /* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
\r
630 and xTaskNotifyAndQueryFromISR(). */
\r
631 switch( xAPIToUse )
\r
633 case 0: vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
\r
637 case 1: xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );
\r
641 case 2: ulPreviousValue = ulUnexpectedValue;
\r
642 xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );
\r
643 configASSERT( ulPreviousValue != ulUnexpectedValue );
\r
647 default:/* Should never get here!. */
\r
651 ulTimerNotificationsSent++;
\r
655 /*-----------------------------------------------------------*/
\r
657 /* This is called to check the created tasks are still running and have not
\r
658 detected any errors. */
\r
659 BaseType_t xAreTaskNotificationTasksStillRunning( void )
\r
661 static uint32_t ulLastNotifyCycleCount = 0;
\r
662 const uint32_t ulMaxSendReceiveDeviation = 5UL;
\r
664 /* Check the cycle count is still incrementing to ensure the task is still
\r
665 actually running. */
\r
666 if( ulLastNotifyCycleCount == ulNotifyCycleCount )
\r
668 xErrorStatus = pdFAIL;
\r
672 ulLastNotifyCycleCount = ulNotifyCycleCount;
\r
675 /* Check the count of 'takes' from the software timer is keeping track with
\r
676 the amount of 'gives'. */
\r
677 if( ulTimerNotificationsSent > ulTimerNotificationsReceived )
\r
679 if( ( ulTimerNotificationsSent - ulTimerNotificationsReceived ) > ulMaxSendReceiveDeviation )
\r
681 xErrorStatus = pdFAIL;
\r
685 return xErrorStatus;
\r
687 /*-----------------------------------------------------------*/
\r
689 static UBaseType_t prvRand( void )
\r
691 const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
\r
693 /* Utility function to generate a pseudo random number. */
\r
694 uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
\r
695 return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
\r
697 /*-----------------------------------------------------------*/
\r