3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
29 * Tests the behaviour of arrays of task notifications per task. The tests in this
30 * file are additive to those implemented in FreeRTOS/Demo/Common/Minimal/TaskNotify.c.
33 /* Standard includes. */
36 /* Scheduler include files. */
41 /* Demo program include files. */
42 #include "TaskNotifyArray.h"
44 #if ( configTASK_NOTIFICATION_ARRAY_ENTRIES < 3 )
45 #error This file tests direct to task notification arrays and needs configTASK_NOTIFICATION_ARRAY_ENTRIES to be at least 3.
48 /* Allow parameters to be overridden on a demo by demo basis. */
49 #ifndef notifyNOTIFY_ARRAY_TASK_STACK_SIZE
50 #define notifyNOTIFY_ARRAY_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
53 #define notifyTASK_PRIORITY ( tskIDLE_PRIORITY )
55 /* Constants used in tests when setting/clearing bits. */
56 #define notifyUINT32_MAX ( ( uint32_t ) 0xffffffff )
57 #define notifyUINT32_HIGH_BYTE ( ( uint32_t ) 0xff000000 )
58 #define notifyUINT32_LOW_BYTE ( ( uint32_t ) 0x000000ff )
60 /*-----------------------------------------------------------*/
63 * Implementation of the task that runs the tests - the task runs some tests
64 * itself, and others where notifications are sent from a software timer or
65 * an interrupt (specifically the tick hook function).
67 static void prvNotifiedTask( void * pvParameters );
70 * Performs the tests that don't require notifications to be sent from a
73 static void prvSingleTaskTests( void );
76 * Uses a software timer to send notifications to the task while the task is
79 static void prvTestNotifyTaskWhileSuspended( void );
82 * Uses a software timer to send notifications to the index within the array of
83 * task notifications on which the task is blocked. The task should unblock and
84 * the state of all the other task notifications within the array should remain
87 static void prvBlockOnTheNotifiedIndexed( void );
90 * As per prvBlockOnTheNotifiedIndexed(), but this time the notification comes from
91 * the tick hook function, so from an interrupt rather than from a software timer.
93 static void prvBlockOnNotificationsComingFromInterrupts( void );
96 * As per prvBlockOnTheNotifiedIndexed(), except this time the notification is
97 * sent to an index within the task notification array on which the task is not
98 * blocked, so this time the task should not unblock and the state of all the
99 * task notifications other than the one to which the notification was actually
100 * sent should remain unchanged.
102 static void prvBlockOnANonNotifiedIndexed( void );
105 * Callback of the software timer used to send notifications for the
106 * prvBlockOnTheNotifiedIndexed() and prvBlockOnANonNotifiedIndexed() tests.
108 static void prvNotifyingTimerCallback( TimerHandle_t xTimer );
111 * Callback for a timer that is used by the prvTestNotifyTaskWhileSuspended()
114 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
117 * Utility function to create pseudo random numbers.
119 static UBaseType_t prvRand( void );
122 /*-----------------------------------------------------------*/
124 /* Counters used to check the task has not stalled. ulFineCycleCount is
125 * incremented within each test. ulCourseCycleCounter is incremented one every
126 * loop of all the tests to ensure each test is actually executing. The check task
127 * calls xAreTaskNotificationArrayTasksStillRunning() (implemented within this
128 * file) to check both counters are changing. */
129 static volatile uint32_t ulFineCycleCount = 0, ulCourseCycleCounter = 0;
131 /* The handle of the task that runs the tests and receives the notifications
132 * from the software timers and interrupts. */
133 static TaskHandle_t xTaskToNotify = NULL;
135 /* The software timers used to send notifications to the main test task. */
136 static TimerHandle_t xIncrementingIndexTimer = NULL;
137 static TimerHandle_t xNotifyWhileSuspendedTimer = NULL;
139 /* Used by the pseudo random number generating function. */
140 static size_t uxNextRand = 0;
142 /* Used to communicate when to send a task notification to the tick hook tests. */
143 static volatile BaseType_t xSendNotificationFromISR = pdFALSE;
145 /*-----------------------------------------------------------*/
147 void vStartTaskNotifyArrayTask( void )
149 const TickType_t xIncrementingIndexTimerPeriod = pdMS_TO_TICKS( 100 );
150 const TickType_t xSuspendTimerPeriod = pdMS_TO_TICKS( 50 );
152 /* Create the software timers used for these tests. The timer callbacks send
153 * notifications to this task. */
154 xNotifyWhileSuspendedTimer = xTimerCreate( "SingleNotify", xSuspendTimerPeriod, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
155 xIncrementingIndexTimer = xTimerCreate( "Notifier", xIncrementingIndexTimerPeriod, pdFALSE, NULL, prvNotifyingTimerCallback );
156 configASSERT( xNotifyWhileSuspendedTimer );
157 configASSERT( xIncrementingIndexTimer );
159 /* Create the task that performs some tests by itself, then loops around
160 * being notified by both a software timer and an interrupt. */
161 xTaskCreate( prvNotifiedTask, /* Function that implements the task. */
162 "ArrayNotifed", /* Text name for the task - for debugging only - not used by the kernel. */
163 notifyNOTIFY_ARRAY_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */
164 NULL, /* Task parameter, not used in this case. */
165 notifyTASK_PRIORITY, /* Task priority, 0 is the lowest. */
166 &xTaskToNotify ); /* Used to pass a handle to the task out if needed, otherwise set to NULL. */
168 /* Pseudo seed the random number generator. */
169 uxNextRand = ( size_t ) prvRand;
171 /*-----------------------------------------------------------*/
173 static void prvNotifiedTask( void * pvParameters )
175 /* Remove compiler warnings about unused parameters. */
176 ( void ) pvParameters;
178 /* Loop through each set of test functions in turn. See the comments above
179 * the respective function prototypes above for more details. */
182 prvSingleTaskTests();
183 prvTestNotifyTaskWhileSuspended();
184 prvBlockOnTheNotifiedIndexed();
185 prvBlockOnANonNotifiedIndexed();
186 prvBlockOnNotificationsComingFromInterrupts();
187 ulCourseCycleCounter++;
190 /*-----------------------------------------------------------*/
192 static void prvSingleTaskTests( void )
194 const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
195 BaseType_t xReturned;
196 uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue;
197 TickType_t xTimeOnEntering, xTimeNow, xTimeDifference;
198 const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;
199 const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
200 UBaseType_t uxIndexToTest, uxOtherIndexes;
203 /* ------------------------------------------------------------------------
204 * Check blocking when there are no notifications. */
205 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
207 /* Send notifications to the task notification in each index of the
208 * task notification array other than the one on which this task will
210 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
212 if( uxOtherIndexes != uxIndexToTest )
214 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, 0, eNoAction );
218 xTimeOnEntering = xTaskGetTickCount();
219 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
220 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
222 /* Should have blocked for the entire block time. */
223 xTimeNow = xTaskGetTickCount();
224 xTimeDifference = xTimeNow - xTimeOnEntering;
225 configASSERT( xTimeDifference >= xTicksToWait );
226 configASSERT( xReturned == pdFAIL );
227 configASSERT( ulNotifiedValue == 0UL );
228 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
229 ( void ) ulNotifiedValue;
231 /* Clear all the other notifications within the array of task
232 * notifications again ready for the next round. */
233 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
235 if( uxOtherIndexes != uxIndexToTest )
237 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
239 /* The notification state was set above so expect it to still be
241 configASSERT( xReturned == pdTRUE );
242 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
247 /* ------------------------------------------------------------------------
248 * Check no blocking when notifications are pending. */
249 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
251 /* First notify the task notification at index uxIndexToTest within this
252 * task's own array of task notifications - this would not be a normal
253 * thing to do and is done here for test purposes only. */
254 xReturned = xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
256 /* Even through the 'without overwrite' action was used the update should
257 * have been successful. */
258 configASSERT( xReturned == pdPASS );
259 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
261 /* No bits should have been pending previously. */
262 configASSERT( ulPreviousValue == 0 );
263 ( void ) ulPreviousValue;
265 /* The task should now have a notification pending in the task
266 * notification at index uxIndexToTest within the task notification array,
267 * and so not time out. */
268 xTimeOnEntering = xTaskGetTickCount();
269 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
270 xTimeNow = xTaskGetTickCount();
271 xTimeDifference = xTimeNow - xTimeOnEntering;
272 configASSERT( xTimeDifference < xTicksToWait );
274 /* The task should have been notified, and the notified value should
275 * be equal to ulFirstNotifiedConst. */
276 configASSERT( xReturned == pdPASS );
277 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
278 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
279 ( void ) ulNotifiedValue;
282 /*-------------------------------------------------------------------------
283 * Check the non-overwriting functionality. */
284 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
286 /* Send notifications to all indexes with the array of task
287 * notifications other than the one on which this task will block. */
288 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
290 if( uxOtherIndexes != uxIndexToTest )
292 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
293 configASSERT( xReturned == pdPASS );
294 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
298 /* The notification is performed twice using two different notification
299 * values. The action says don't overwrite so only the first notification
300 * should pass and the value read back should also be that used with the
301 * first notification. The notification is sent to the task notification at
302 * index uxIndexToTest within the array of task notifications. */
303 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
304 configASSERT( xReturned == pdPASS );
305 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
307 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
308 configASSERT( xReturned == pdFAIL );
309 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
311 /* Waiting for the notification should now return immediately so a block
312 * time of zero is used. */
313 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
315 configASSERT( xReturned == pdPASS );
316 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
317 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
318 ( void ) ulNotifiedValue;
320 /* Clear all the other task notifications within the array of task
321 * notifications again ready for the next round. */
322 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
324 if( uxOtherIndexes != uxIndexToTest )
326 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
327 configASSERT( xReturned == pdTRUE );
328 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
330 ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
332 /* The notification value was set to ulFirstNotifiedConst in all
333 * the other indexes, so expect it to still have that value. */
334 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
335 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
340 /*-------------------------------------------------------------------------
341 * Do the same again, only this time use the overwriting version. This time
342 * both notifications should pass, and the value written the second time should
343 * overwrite the value written the first time, and so be the value that is read
345 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
347 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
349 if( uxOtherIndexes != uxIndexToTest )
351 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
355 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithOverwrite );
356 configASSERT( xReturned == pdPASS );
357 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
358 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
359 configASSERT( xReturned == pdPASS );
360 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
361 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, notifyUINT32_MAX, &ulNotifiedValue, 0 );
362 configASSERT( xReturned == pdPASS );
363 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
364 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
365 ( void ) ulNotifiedValue;
367 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
369 if( uxOtherIndexes != uxIndexToTest )
371 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
372 configASSERT( xReturned == pdTRUE );
373 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
374 ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
375 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
376 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
381 /*-------------------------------------------------------------------------
382 * For each task notification within the array of task notifications, check
383 * notifications with no action pass without updating the value. */
384 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
386 /* First set the notification values of the task notification at index
387 * uxIndexToTest of the array of task notification to
388 * ulSecondNotifiedValueConst. */
389 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
390 configASSERT( xReturned == pdPASS );
391 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
393 /* Even though ulFirstNotifiedConst is used as the value next, the value
394 * read back should remain at ulSecondNotifiedConst as the action is set
396 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eNoAction );
397 configASSERT( xReturned == pdPASS );
398 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
400 /* All task notifications in the array of task notifications up to and
401 * including index uxIndexToTest should still contain the same value. */
402 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
404 /* First zero is bits to clear on entry, the second is bits to clear on
405 * exist, the last 0 is the block time. */
406 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
407 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
408 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
411 /* All array indexes in the array of task notifications after index
412 * uxIndexToTest should still contain 0 as they have not been set in this
413 * loop yet. This time use ulTaskNotifyValueClearIndexed() instead of
414 * xTaskNotifyWaitIndexed(), just for test coverage. */
415 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
417 /* This time 0 is the bits to clear parameter - so clearing no bits. */
418 ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
419 configASSERT( ulNotifiedValue == 0 );
420 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
424 /*-------------------------------------------------------------------------
425 * Check incrementing values. For each task notification in the array of task
426 * notifications in turn, send ulMaxLoop increment notifications, then ensure
427 * the received value is as expected - which should be
428 * ulSecondNotificationValueConst plus how ever many times to loop iterated. */
429 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
431 for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
433 /* Increment the value of the task notification at index
434 * uxIndexToTest within the array of task notifications. */
435 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eIncrement );
436 configASSERT( xReturned == pdPASS );
437 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
440 /* All array indexes up to and including uxIndexToTest should still
441 * contain the updated value. */
442 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
444 /* First zero is bits to clear on entry, the second is bits to clear on
445 * exist, the last 0 is the block time. */
446 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
447 configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
448 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
451 /* Should not be any notifications pending now. */
452 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, 0 );
453 configASSERT( xReturned == pdFAIL );
454 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
455 ( void ) ulNotifiedValue;
457 /* All notifications values in the array of task notifications after
458 * index uxIndexToTest should still contain the un-incremented
459 * ulSecondNotifiedValueConst as they have not been set in this loop yet.
460 * This time use ulTaskNotifyValueClearIndexed() instead of xTaskNotifyWaitIndexed(),
461 * just for test coverage. */
462 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
464 /* This time 0 is the bits to clear parameter - so clearing no bits. */
465 ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
466 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
467 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
471 /* Clear all bits ready for next test. */
472 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
474 /* Start with all bits clear. */
475 ulTaskNotifyValueClearIndexed( NULL, uxIndexToTest, notifyUINT32_MAX );
478 /*-------------------------------------------------------------------------
479 * For each task notification in the array of task notifications in turn, check
480 * all bits in the notification's value can be set by notifying the task with
481 * one additional bit set on each notification, and exiting the loop when all
482 * the bits are found to be set. As there are 32-bits the loop should execute
483 * 32 times before all the bits are found to be set. */
484 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
486 ulNotifyingValue = 0x01;
491 /* Set the next bit in the value of the task notification at index
492 * uxIndexToTest within the array of task notifications. */
493 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulNotifyingValue, eSetBits );
495 /* Wait for the notified value - which of course will already be
496 * available. Don't clear the bits on entry or exit as this loop is
497 * exited when all the bits are set. */
498 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, 0 );
499 configASSERT( xReturned == pdPASS );
500 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
504 /* Use the next bit on the next iteration around this loop. */
505 ulNotifyingValue <<= 1UL;
506 } while( ulNotifiedValue != notifyUINT32_MAX );
508 /* As a 32-bit value was used the loop should have executed 32 times before
509 * all the bits were set. */
510 configASSERT( ulLoop == 32 );
512 /* The value of each task notification within the array of task
513 * notifications up to and including index uxIndexToTest should still have
515 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
517 /* First zero is bits to clear on entry, the second is bits to clear on
518 * exist, the last 0 is the block time. */
519 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
520 configASSERT( ulNotifiedValue == notifyUINT32_MAX );
521 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
524 /* The value of each task notification within the array of task
525 * notifications after index uxIndexToTest should still contain 0 as they
526 * have not been set in this loop yet. This time use ulTaskNotifyValueClearIndexed()
527 * instead of xTaskNotifyWaitIndexed(), just for test coverage. */
528 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
530 /* This time 0 is the bits to clear parameter - so clearing no bits. */
531 ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
532 configASSERT( ulNotifiedValue == 0 );
533 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
537 /*-------------------------------------------------------------------------
538 * For each task notification within the array of task notifications in turn,
539 * check bits are cleared on entry but not on exit when a notification fails
540 * to arrive before timing out - both with and without a timeout value. */
541 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
543 /* Wait for the notification - but this time it is not given by anything
544 * and should return pdFAIL. The parameters are set to clear bit zero on
545 * entry and bit one on exit. As no notification was received only the bit
546 * cleared on entry should actually get cleared. */
547 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
548 configASSERT( xReturned == pdFAIL );
549 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
551 /* Send a notification with no action to the task notification at index
552 * uxIndexToTest within the array of task notifications. This should not
553 * update the bits even though notifyUINT32_MAX is used as the notification
555 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eNoAction );
557 /* All array indexes up to and including uxIndexToTest within the array
558 * of task notifications should have the modified value. */
559 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
561 /* Reading back the value should find bit 0 is clear, as this was cleared
562 * on entry, but bit 1 is not clear as it will not have been cleared on exit
563 * as no notification was received. */
564 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
566 if( uxOtherIndexes == uxIndexToTest )
568 /* This is the index being used this time round the loop and its
569 * notification state was set immediately above. */
570 configASSERT( xReturned == pdPASS );
574 /* Nothing should have set this index's notification state again. */
575 configASSERT( xReturned == pdFAIL );
578 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
579 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
582 /* All array indexes after uxIndexToTest should still contain notifyUINT32_MAX
583 * left over from the previous test. This time use xTaskNotifyValueClear()
584 * instead of xTaskNotifyWaitIndexed(), just for test coverage. */
585 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
587 /* This time 0 is the bits to clear parameter - so clearing no bits. */
588 ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
589 configASSERT( ulNotifiedValue == notifyUINT32_MAX );
590 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
594 /*-------------------------------------------------------------------------
595 * Now try clearing the bit on exit. */
596 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
598 /* The task is notified first using the task notification at index
599 * uxIndexToTest within the array of task notifications. */
600 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eNoAction );
601 xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, ulBit1, &ulNotifiedValue, 0 );
603 /* However as the bit is cleared on exit, after the returned notification
604 * value is set, the returned notification value should not have the bit
606 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
608 /* ...but reading the value back again should find that the bit was indeed
609 * cleared internally. The returned value should be pdFAIL however as nothing
610 * has notified the task in the mean time. */
611 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, 0x00, &ulNotifiedValue, 0 );
612 configASSERT( xReturned == pdFAIL );
613 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
614 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
616 /* No other indexes should have a notification pending. */
617 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
619 if( uxOtherIndexes != uxIndexToTest )
621 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
622 configASSERT( xReturned == pdFAIL );
623 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
628 /*-------------------------------------------------------------------------
629 * For each task notification within the array of task notifications, try
630 * querying the previous value while notifying a task. */
631 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
633 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
634 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
636 /* Clear all bits. */
637 xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
638 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
639 configASSERT( ulPreviousValue == 0 );
643 for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
645 /* Set the next bit up, and expect to receive the last bits set (so
646 * the previous value will not yet have the bit being set this time
648 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulLoop, eSetBits, &ulPreviousValue );
649 configASSERT( ulExpectedValue == ulPreviousValue );
650 ulExpectedValue |= ulLoop;
654 /* ---------------------------------------------------------------------- */
655 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
657 /* Clear the previous notifications. */
658 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
661 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
663 /* No task notification within the array of task notifications should
664 * have any notification pending, so an attempt to clear the notification
665 * state should fail. */
666 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
668 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
671 /* Get the task to notify itself using the task notification at index
672 * uxIndexToTest within the array of task notifications. This is not a
673 * normal thing to do, and is only done here for test purposes. */
674 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
676 /* Now the notification state should be eNotified, so it should now be
677 * possible to clear the notification state. Other indexes should still
678 * not have a notification pending - likewise uxIndexToTest should not have
679 * a notification pending once it has been cleared. */
680 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
682 if( uxOtherIndexes == uxIndexToTest )
684 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdTRUE );
687 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
691 /* ------------------------------------------------------------------------
692 * For each task notification within the array of task notifications, clear
693 * bits in the notification value. */
694 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
696 /* Get the task to set all bits in its task notification at index
697 * uxIndexToTest within its array of task notifications. This is not a
698 * normal thing to do, and is only done here for test purposes. */
699 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eSetBits );
701 /* Now clear the top bytes - the returned value from the first call
702 * should indicate that previously all bits were set. */
703 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );
705 /* Next clear the bottom bytes - the returned value this time should
706 * indicate that the top byte was clear (before the bottom byte was
708 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
710 /* Next clear all bytes - the returned value should indicate that previously the
711 * high and low bytes were clear. */
712 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );
714 /* Now all bits should be clear. */
715 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == 0 );
716 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, 0UL ) == 0 );
717 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == 0 );
719 /* Now the notification state should be eNotified, so it should now be
720 * possible to clear the notification state. */
721 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdTRUE );
722 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdFALSE );
725 /* Incremented to show the task is still running. */
728 /* Leave all bits cleared. */
729 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
731 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
734 /*-----------------------------------------------------------*/
736 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
738 static uint32_t ulCallCount = 0;
739 static UBaseType_t uxIndexToNotify = 0;
741 /* Remove compiler warnings about unused parameters. */
742 ( void ) xExpiredTimer;
744 /* Callback for a timer that is used to send notifications to a task while
745 * it is suspended. The timer tests the behaviour when 1: a task waiting for a
746 * notification is suspended and then resumed without ever receiving a
747 * notification, and 2: when a task waiting for a notification receives a
748 * notification while it is suspended. Run one of two tests on every other
749 * invocation of this callback. The notification is sent to the task
750 * notification at index uxIndexToNotify. */
751 if( ( ulCallCount & 0x01 ) == 0 )
753 vTaskSuspend( xTaskToNotify );
754 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
755 vTaskResume( xTaskToNotify );
759 vTaskSuspend( xTaskToNotify );
761 /* Sending a notification while the task is suspended should pass, but
762 * not cause the task to resume. */
763 xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 1, eSetValueWithOverwrite );
765 /* Use the next task notification within the array of task notifications
766 * the next time around. */
769 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
774 /* Make sure giving the notification didn't resume the task. */
775 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
777 vTaskResume( xTaskToNotify );
782 /*-----------------------------------------------------------*/
784 static void prvNotifyingTimerCallback( TimerHandle_t xNotUsed )
786 static BaseType_t uxIndexToNotify = 0;
790 /* "Give" the task notification (which increments the target task
791 * notification value) at index uxIndexToNotify within the array of task
793 xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
795 /* Use the next task notification within the array of task notifications the
796 * next time around. */
799 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
804 /*-----------------------------------------------------------*/
806 static void prvTestNotifyTaskWhileSuspended( void )
808 UBaseType_t uxIndexToTest, uxOtherIndexes;
809 BaseType_t xReturned;
810 uint32_t ulNotifiedValue;
812 /* Raise the task's priority so it can suspend itself before the timer
814 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
816 /* Perform the test on each task notification within the array or task
818 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
820 /* Ensure no notifications within the array of task notifications are
822 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
824 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, NULL, 0 );
825 configASSERT( xReturned == pdFALSE );
826 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
829 /* Start the timer that will try notifying this task while it is
830 * suspended, then wait for a notification. The first time the callback
831 * executes the timer will suspend the task, then resume the task, without
832 * ever sending a notification to the task. */
834 xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
836 /* Check a notification is not received on the task notification at
837 * index uxIndexToTest within the array of task notifications. */
838 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
839 configASSERT( xReturned == pdFALSE );
840 configASSERT( ulNotifiedValue == 0 );
841 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
843 /* Check none of the task notifications within the array of task
844 * notifications as been notified. */
845 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
847 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
848 configASSERT( xReturned == pdFALSE );
849 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
852 /* Start the timer that will try notifying this task while it is
853 * suspended, then wait for a notification at index uxIndexToTest within
854 * the array of task notifications. The second time the callback executes
855 * the timer will suspend the task, notify the task, then resume the task
856 * (previously it was suspended and resumed without being notified). */
857 xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
859 /* Check a notification is only received in the index within the array
860 * of task notifications under test. */
861 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
862 configASSERT( xReturned == pdPASS );
863 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
864 configASSERT( ulNotifiedValue != 0 );
866 /* Check a notification is not received in any index within the array
867 * of task notifications at and below the index being tested have a notification
868 * value, and that indexes above the index being tested to not have
869 * notification values. */
870 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
872 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
873 configASSERT( xReturned == pdFALSE );
875 if( uxOtherIndexes <= uxIndexToTest )
877 configASSERT( ulNotifiedValue == 1 );
881 configASSERT( ulNotifiedValue == 0 );
884 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
885 ( void ) ulNotifiedValue;
889 /* Return the task to its proper priority */
890 vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
892 /* Incremented to show the task is still running. */
895 /* Leave all bits cleared. */
896 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
898 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
901 /* ------------------------------------------------------------------------ */
903 static void prvBlockOnTheNotifiedIndexed( void )
905 const TickType_t xTimerPeriod = pdMS_TO_TICKS( 100 ), xMargin = pdMS_TO_TICKS( 50 ), xDontBlock = 0;
906 UBaseType_t uxIndex, uxIndexToNotify;
907 uint32_t ulReceivedValue;
908 BaseType_t xReturned;
910 /* Set the value of each notification in the array of task notifications to
911 * the value of its index position plus 1 so everything starts in a known
912 * state, then clear the notification state ready for the next test. Plus 1 is
913 * used because the index under test will use 0. */
914 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
916 xTaskNotifyIndexed( xTaskToNotify, uxIndex, uxIndex + 1, eSetValueWithOverwrite );
917 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
920 /* Peform the test on each task notification within the array of task
922 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
924 /* Set the notification value of the index being tested to 0 so the
925 * notification value increment/decrement functions can be tested. */
926 xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 0, eSetValueWithOverwrite );
927 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
929 /* Start the software timer then wait for it to notify this task. Block
930 * on the notification index we expect to receive the notification on. The
931 * margin is to ensure the task blocks longer than the timer period. */
932 xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
933 ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdFALSE, xTimerPeriod + xMargin );
935 /* The notification value was initially zero, and should have been
936 * incremented by the software timer, so now one. It will also have been
937 * decremented again by the call to ulTaskNotifyTakeIndexed() so gone back
939 configASSERT( ulReceivedValue == 1UL );
940 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
942 /* No other notification indexes should have changed, and therefore should
943 * still have their value set to their index plus 1 within the array of
945 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
947 if( uxIndex != uxIndexToNotify )
949 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
950 configASSERT( xReturned == pdFALSE );
951 configASSERT( ulReceivedValue == ( uxIndex + 1 ) );
952 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
957 /* Reset the notification value for the index just tested back to the
958 * index value plus 1 ready for the next iteration around this loop. */
959 xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, uxIndexToNotify + 1, eSetValueWithOverwrite );
960 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
962 /* Incremented to show the task is still running. */
966 /* ------------------------------------------------------------------------ */
968 static void prvBlockOnANonNotifiedIndexed( void )
970 const TickType_t xTimerPeriod = pdMS_TO_TICKS( 100 ), xMargin = pdMS_TO_TICKS( 50 ), xDontBlock = 0;
971 UBaseType_t uxIndex, uxIndexToNotify;
972 uint32_t ulReceivedValue;
973 BaseType_t xReturned;
974 TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
976 /* Set all notify values within the array of tasks notifications to zero
977 * ready for the next test. */
978 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
980 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToNotify, notifyUINT32_MAX );
983 /* Perform the test for each notification within the array of task
985 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
987 /* Start the software timer then wait for it to notify this task. Block
988 * on a notification index that we do not expect to receive the notification
989 * on. The margin is to ensure the task blocks longer than the timer period. */
990 xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
991 xTimeBeforeBlocking = xTaskGetTickCount();
993 if( uxIndexToNotify == ( configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 ) )
995 /* configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 is to be notified, so
996 * block on index 0. */
1001 /* The next index to get notified will be uxIndexToNotify, so block
1002 * on uxIndexToNotify + 1 */
1003 uxIndex = uxIndexToNotify + 1;
1006 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xTimerPeriod + xMargin );
1008 /* The notification will have been sent to task notification at index
1009 * uxIndexToNotify in this task by the timer callback after xTimerPeriodTicks.
1010 * The notification should not have woken this task, so xReturned should
1011 * be false and at least xTimerPeriod + xMargin ticks should have passed. */
1012 configASSERT( xReturned == pdFALSE );
1013 xTimeNow = xTaskGetTickCount();
1014 xTimeDifference = xTimeNow - xTimeBeforeBlocking;
1015 configASSERT( xTimeDifference >= ( xTimerPeriod + xMargin ) );
1016 ( void ) xReturned; /* Remove compiler warnings if configASSERT() is not defined. */
1017 ( void ) xTimeBeforeBlocking;
1018 ( void ) xTimeDifference;
1020 /* Only the notification at index position uxIndexToNotify should be
1021 * set. Calling this function will clear it again. */
1022 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
1024 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
1026 if( uxIndex == uxIndexToNotify )
1028 /* Expect the notification state to be set and the notification
1029 * value to have been incremented. */
1030 configASSERT( xReturned == pdTRUE );
1031 configASSERT( ulReceivedValue == 1 );
1033 /* Set the notification value for this array index back to 0. */
1034 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndex, notifyUINT32_MAX );
1038 /* Expect the notification state to be clear and the notification
1039 * value to remain at zer0. */
1040 configASSERT( xReturned == pdFALSE );
1041 configASSERT( ulReceivedValue == 0 );
1045 /* Incremented to show the task is still running. */
1049 /* ------------------------------------------------------------------------ */
1051 static void prvBlockOnNotificationsComingFromInterrupts( void )
1053 UBaseType_t uxIndex, uxIndexToNotify;
1054 uint32_t ulReceivedValue;
1055 BaseType_t xReturned;
1056 const TickType_t xDontBlock = 0;
1058 /* Set the value of each notification within the array of task notifications
1059 * to zero so the task can block on xTaskNotifyTake(). */
1060 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
1062 xTaskNotifyIndexed( xTaskToNotify, uxIndex, 0, eSetValueWithOverwrite );
1063 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
1066 /* Perform the test on each task notification within the array of task
1068 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
1070 /* Tell the interrupt to send the next notification. */
1071 taskENTER_CRITICAL();
1073 /* Don't expect to find xSendNotificationFromISR set at this time as
1074 * the interrupt should have cleared it back to pdFALSE last time it
1076 configASSERT( xSendNotificationFromISR == pdFALSE );
1077 xSendNotificationFromISR = pdTRUE;
1079 taskEXIT_CRITICAL();
1081 /* Wait for a notification on the task notification at index
1082 * uxIndexToNotify within the array of task notifications. */
1083 ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdTRUE, portMAX_DELAY );
1085 /* Interrupt should have reset xSendNotificationFromISR after it sent
1086 * the notification. */
1087 configASSERT( xSendNotificationFromISR == pdFALSE );
1089 /* The notification value was initially zero, and should have been
1090 * incremented by the interrupt, so now one. */
1091 configASSERT( ulReceivedValue == 1UL );
1092 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
1094 /* No other notification indexes should have changed, and therefore should
1095 * still have their value set to 0. The value in array index uxIndexToNotify
1096 * should also have been decremented back to zero by the call to
1097 * ulTaskNotifyTakeIndexed(). */
1098 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
1100 xReturned = xTaskNotifyWaitIndexed( uxIndexToNotify, 0, 0, &ulReceivedValue, xDontBlock );
1101 configASSERT( xReturned == pdFALSE );
1102 configASSERT( ulReceivedValue == 0 );
1103 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
1107 /* Incremented to show the task is still running. */
1111 /*-----------------------------------------------------------*/
1113 void xNotifyArrayTaskFromISR( void )
1115 static BaseType_t xAPIToUse = 0;
1116 uint32_t ulPreviousValue;
1117 const uint32_t ulUnexpectedValue = 0xff;
1118 static UBaseType_t uxIndexToNotify = 0;
1120 /* Check the task notification demo task was actually created. */
1121 configASSERT( xTaskToNotify );
1123 /* The task sets xSendNotificationFromISR to pdTRUE each time it wants this
1124 * interrupt (this function runs in the RTOS tick hook) to send the next
1126 if( xSendNotificationFromISR == pdTRUE )
1128 xSendNotificationFromISR = pdFALSE;
1130 /* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
1131 * and xTaskNotifyAndQueryFromISR(). The notification is set to the task
1132 * notification at index uxIndexToNotify within the array of task
1137 vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, NULL );
1142 xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, NULL );
1147 ulPreviousValue = ulUnexpectedValue;
1148 xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, &ulPreviousValue, NULL );
1149 configASSERT( ulPreviousValue == 0 );
1153 default: /* Should never get here!. */
1157 /* Use the next index in the array of task notifications the next time
1161 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
1163 uxIndexToNotify = 0;
1167 /*-----------------------------------------------------------*/
1169 /* This is called to check the created tasks are still running and have not
1170 * detected any errors. */
1171 BaseType_t xAreTaskNotificationArrayTasksStillRunning( void )
1173 static uint32_t ulLastFineCycleCount = 0, ulLastCourseCycleCount = 0, ulCallCount = 0;
1174 const uint32_t ulCallsBetweenCourseCycleCountChecks = 3UL;
1175 static BaseType_t xErrorStatus = pdPASS;
1177 /* Check the cycle count is still incrementing to ensure the task is still
1178 * actually running. The fine counter is incremented within individual test
1179 * functions. The course counter is incremented one each time all the test
1180 * functions have been executed to ensure all the tests are running. */
1181 if( ulLastFineCycleCount == ulFineCycleCount )
1183 xErrorStatus = pdFAIL;
1187 ulLastFineCycleCount = ulFineCycleCount;
1192 if( ulCallCount >= ulCallsBetweenCourseCycleCountChecks )
1196 if( ulLastCourseCycleCount == ulCourseCycleCounter )
1198 xErrorStatus = pdFAIL;
1202 ulLastCourseCycleCount = ulCourseCycleCounter;
1206 return xErrorStatus;
1208 /*-----------------------------------------------------------*/
1210 static UBaseType_t prvRand( void )
1212 const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
1214 /* Utility function to generate a pseudo random number. */
1215 uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
1216 return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
1218 /*-----------------------------------------------------------*/