]> begriffs open source - cmsis-freertos/blob - Demo/Common/Minimal/TaskNotifyArray.c
Updated pack to FreeRTOS 10.4.6
[cmsis-freertos] / Demo / Common / Minimal / TaskNotifyArray.c
1 /*
2  * FreeRTOS V202111.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
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.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26
27
28 /*
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.
31  */
32
33 /* Standard includes. */
34 #include <limits.h>
35
36 /* Scheduler include files. */
37 #include "FreeRTOS.h"
38 #include "task.h"
39 #include "timers.h"
40
41 /* Demo program include files. */
42 #include "TaskNotifyArray.h"
43
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.
46 #endif
47
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
51 #endif
52
53 #define notifyTASK_PRIORITY                       ( tskIDLE_PRIORITY )
54
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 )
59
60 /*-----------------------------------------------------------*/
61
62 /*
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).
66  */
67 static void prvNotifiedTask( void * pvParameters );
68
69 /*
70  * Performs the tests that don't require notifications to be sent from a
71  * remote source.
72  */
73 static void prvSingleTaskTests( void );
74
75 /*
76  * Uses a software timer to send notifications to the task while the task is
77  * suspended.
78  */
79 static void prvTestNotifyTaskWhileSuspended( void );
80
81 /*
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
85  * unchanged.
86  */
87 static void prvBlockOnTheNotifiedIndexed( void );
88
89 /*
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.
92  */
93 static void prvBlockOnNotificationsComingFromInterrupts( void );
94
95 /*
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.
101  */
102 static void prvBlockOnANonNotifiedIndexed( void );
103
104 /*
105  * Callback of the software timer used to send notifications for the
106  * prvBlockOnTheNotifiedIndexed() and prvBlockOnANonNotifiedIndexed() tests.
107  */
108 static void prvNotifyingTimerCallback( TimerHandle_t xTimer );
109
110 /*
111  * Callback for a timer that is used by the prvTestNotifyTaskWhileSuspended()
112  * test.
113  */
114 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
115
116 /*
117  * Utility function to create pseudo random numbers.
118  */
119 static UBaseType_t prvRand( void );
120
121
122 /*-----------------------------------------------------------*/
123
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;
130
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;
134
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;
138
139 /* Used by the pseudo random number generating function. */
140 static size_t uxNextRand = 0;
141
142 /* Used to communicate when to send a task notification to the tick hook tests. */
143 static volatile BaseType_t xSendNotificationFromISR = pdFALSE;
144
145 /*-----------------------------------------------------------*/
146
147 void vStartTaskNotifyArrayTask( void )
148 {
149     const TickType_t xIncrementingIndexTimerPeriod = pdMS_TO_TICKS( 100 );
150     const TickType_t xSuspendTimerPeriod = pdMS_TO_TICKS( 50 );
151
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 );
158
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. */
167
168     /* Pseudo seed the random number generator. */
169     uxNextRand = ( size_t ) prvRand;
170 }
171 /*-----------------------------------------------------------*/
172
173 static void prvNotifiedTask( void * pvParameters )
174 {
175     /* Remove compiler warnings about unused parameters. */
176     ( void ) pvParameters;
177
178     /* Loop through each set of test functions in turn.  See the comments above
179      * the respective function prototypes above for more details. */
180     for( ; ; )
181     {
182         prvSingleTaskTests();
183         prvTestNotifyTaskWhileSuspended();
184         prvBlockOnTheNotifiedIndexed();
185         prvBlockOnANonNotifiedIndexed();
186         prvBlockOnNotificationsComingFromInterrupts();
187         ulCourseCycleCounter++;
188     }
189 }
190 /*-----------------------------------------------------------*/
191
192 static void prvSingleTaskTests( void )
193 {
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;
201
202
203     /* ------------------------------------------------------------------------
204      * Check blocking when there are no notifications. */
205     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
206     {
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
209          * block. */
210         for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
211         {
212             if( uxOtherIndexes != uxIndexToTest )
213             {
214                 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, 0, eNoAction );
215             }
216         }
217
218         xTimeOnEntering = xTaskGetTickCount();
219         xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
220         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
221
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;
230
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++ )
234         {
235             if( uxOtherIndexes != uxIndexToTest )
236             {
237                 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
238
239                 /* The notification state was set above so expect it to still be
240                  * set. */
241                 configASSERT( xReturned == pdTRUE );
242                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
243             }
244         }
245     }
246
247     /* ------------------------------------------------------------------------
248      * Check no blocking when notifications are pending. */
249     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
250     {
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 );
255
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. */
260
261         /* No bits should have been pending previously. */
262         configASSERT( ulPreviousValue == 0 );
263         ( void ) ulPreviousValue;
264
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 );
273
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;
280     }
281
282     /*-------------------------------------------------------------------------
283      * Check the non-overwriting functionality. */
284     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
285     {
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++ )
289         {
290             if( uxOtherIndexes != uxIndexToTest )
291             {
292                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
293                 configASSERT( xReturned == pdPASS );
294                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
295             }
296         }
297
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. */
306
307         xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
308         configASSERT( xReturned == pdFAIL );
309         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
310
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 );
314
315         configASSERT( xReturned == pdPASS );
316         configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
317         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
318         ( void ) ulNotifiedValue;
319
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++ )
323         {
324             if( uxOtherIndexes != uxIndexToTest )
325             {
326                 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
327                 configASSERT( xReturned == pdTRUE );
328                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
329
330                 ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
331
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. */
336             }
337         }
338     }
339
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
344      * back. */
345     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
346     {
347         for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
348         {
349             if( uxOtherIndexes != uxIndexToTest )
350             {
351                 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
352             }
353         }
354
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;
366
367         for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
368         {
369             if( uxOtherIndexes != uxIndexToTest )
370             {
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. */
377             }
378         }
379     }
380
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++ )
385     {
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. */
392
393         /* Even though ulFirstNotifiedConst is used as the value next, the value
394          * read back should remain at ulSecondNotifiedConst as the action is set
395          * to eNoAction. */
396         xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eNoAction );
397         configASSERT( xReturned == pdPASS );
398         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
399
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++ )
403         {
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. */
409         }
410
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++ )
416         {
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. */
421         }
422     }
423
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++ )
430     {
431         for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
432         {
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. */
438         }
439
440         /* All array indexes up to and including uxIndexToTest should still
441          * contain the updated value. */
442         for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
443         {
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. */
449         }
450
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;
456
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++ )
463         {
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. */
468         }
469     }
470
471     /* Clear all bits ready for next test. */
472     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
473     {
474         /* Start with all bits clear. */
475         ulTaskNotifyValueClearIndexed( NULL, uxIndexToTest, notifyUINT32_MAX );
476     }
477
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++ )
485     {
486         ulNotifyingValue = 0x01;
487         ulLoop = 0;
488
489         do
490         {
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 );
494
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. */
501
502             ulLoop++;
503
504             /* Use the next bit on the next iteration around this loop. */
505             ulNotifyingValue <<= 1UL;
506         } while( ulNotifiedValue != notifyUINT32_MAX );
507
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 );
511
512         /* The value of each task notification within the array of task
513          * notifications up to and including index uxIndexToTest should still have
514          * all bits set. */
515         for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
516         {
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. */
522         }
523
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++ )
529         {
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. */
534         }
535     }
536
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++ )
542     {
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. */
550
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
554          * value. */
555         xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eNoAction );
556
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++ )
560         {
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 );
565
566             if( uxOtherIndexes == uxIndexToTest )
567             {
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 );
571             }
572             else
573             {
574                 /* Nothing should have set this index's notification state again. */
575                 configASSERT( xReturned == pdFAIL );
576             }
577
578             configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
579             ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
580         }
581
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++ )
586         {
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. */
591         }
592     }
593
594     /*-------------------------------------------------------------------------
595      * Now try clearing the bit on exit. */
596     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
597     {
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 );
602
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
605          * cleared... */
606         configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
607
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. */
615
616         /* No other indexes should have a notification pending. */
617         for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
618         {
619             if( uxOtherIndexes != uxIndexToTest )
620             {
621                 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
622                 configASSERT( xReturned == pdFAIL );
623                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
624             }
625         }
626     }
627
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++ )
632     {
633         xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
634         configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
635
636         /* Clear all bits. */
637         xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
638         xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
639         configASSERT( ulPreviousValue == 0 );
640
641         ulExpectedValue = 0;
642
643         for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
644         {
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
647              * around). */
648             xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulLoop, eSetBits, &ulPreviousValue );
649             configASSERT( ulExpectedValue == ulPreviousValue );
650             ulExpectedValue |= ulLoop;
651         }
652     }
653
654     /* ---------------------------------------------------------------------- */
655     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
656     {
657         /* Clear the previous notifications. */
658         xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
659     }
660
661     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
662     {
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++ )
667         {
668             configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
669         }
670
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 );
675
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++ )
681         {
682             if( uxOtherIndexes == uxIndexToTest )
683             {
684                 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdTRUE );
685             }
686
687             configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
688         }
689     }
690
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++ )
695     {
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 );
700
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 );
704
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
707          * cleared. */
708         configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
709
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 ) );
713
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 );
718
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 );
723     }
724
725     /* Incremented to show the task is still running. */
726     ulFineCycleCount++;
727
728     /* Leave all bits cleared. */
729     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
730     {
731         xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
732     }
733 }
734 /*-----------------------------------------------------------*/
735
736 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
737 {
738     static uint32_t ulCallCount = 0;
739     static UBaseType_t uxIndexToNotify = 0;
740
741     /* Remove compiler warnings about unused parameters. */
742     ( void ) xExpiredTimer;
743
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 )
752     {
753         vTaskSuspend( xTaskToNotify );
754         configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
755         vTaskResume( xTaskToNotify );
756     }
757     else
758     {
759         vTaskSuspend( xTaskToNotify );
760
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 );
764
765         /* Use the next task notification within the array of task notifications
766          * the next time around. */
767         uxIndexToNotify++;
768
769         if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
770         {
771             uxIndexToNotify = 0;
772         }
773
774         /* Make sure giving the notification didn't resume the task. */
775         configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
776
777         vTaskResume( xTaskToNotify );
778     }
779
780     ulCallCount++;
781 }
782 /*-----------------------------------------------------------*/
783
784 static void prvNotifyingTimerCallback( TimerHandle_t xNotUsed )
785 {
786     static BaseType_t uxIndexToNotify = 0;
787
788     ( void ) xNotUsed;
789
790     /* "Give" the task notification (which increments the target task
791      * notification value) at index uxIndexToNotify within the array of task
792      * notifications. */
793     xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
794
795     /* Use the next task notification within the array of task notifications the
796      * next time around. */
797     uxIndexToNotify++;
798
799     if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
800     {
801         uxIndexToNotify = 0;
802     }
803 }
804 /*-----------------------------------------------------------*/
805
806 static void prvTestNotifyTaskWhileSuspended( void )
807 {
808     UBaseType_t uxIndexToTest, uxOtherIndexes;
809     BaseType_t xReturned;
810     uint32_t ulNotifiedValue;
811
812     /* Raise the task's priority so it can suspend itself before the timer
813      * expires. */
814     vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
815
816     /* Perform the test on each task notification within the array or task
817      * notifications. */
818     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
819     {
820         /* Ensure no notifications within the array of task notifications are
821          * pending. */
822         for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
823         {
824             xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, NULL, 0 );
825             configASSERT( xReturned == pdFALSE );
826             ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
827         }
828
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. */
833         ulNotifiedValue = 0;
834         xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
835
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. */
842
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++ )
846         {
847             xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
848             configASSERT( xReturned == pdFALSE );
849             ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
850         }
851
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 );
858
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 );
865
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++ )
871         {
872             xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
873             configASSERT( xReturned == pdFALSE );
874
875             if( uxOtherIndexes <= uxIndexToTest )
876             {
877                 configASSERT( ulNotifiedValue == 1 );
878             }
879             else
880             {
881                 configASSERT( ulNotifiedValue == 0 );
882             }
883
884             ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
885             ( void ) ulNotifiedValue;
886         }
887     }
888
889     /* Return the task to its proper priority */
890     vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
891
892     /* Incremented to show the task is still running. */
893     ulFineCycleCount++;
894
895     /* Leave all bits cleared. */
896     for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
897     {
898         xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
899     }
900 }
901 /* ------------------------------------------------------------------------ */
902
903 static void prvBlockOnTheNotifiedIndexed( void )
904 {
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;
909
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++ )
915     {
916         xTaskNotifyIndexed( xTaskToNotify, uxIndex, uxIndex + 1, eSetValueWithOverwrite );
917         xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
918     }
919
920     /* Peform the test on each task notification within the array of task
921      * notifications. */
922     for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
923     {
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 );
928
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 );
934
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
938          * to 0. */
939         configASSERT( ulReceivedValue == 1UL );
940         ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
941
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
944          * notifications. */
945         for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
946         {
947             if( uxIndex != uxIndexToNotify )
948             {
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. */
953                 ( void ) xReturned;
954             }
955         }
956
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 );
961
962         /* Incremented to show the task is still running. */
963         ulFineCycleCount++;
964     }
965 }
966 /* ------------------------------------------------------------------------ */
967
968 static void prvBlockOnANonNotifiedIndexed( void )
969 {
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;
975
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++ )
979     {
980         ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToNotify, notifyUINT32_MAX );
981     }
982
983     /* Perform the test for each notification within the array of task
984      * notifications. */
985     for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
986     {
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();
992
993         if( uxIndexToNotify == ( configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 ) )
994         {
995             /* configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 is to be notified, so
996              * block on index 0. */
997             uxIndex = 0;
998         }
999         else
1000         {
1001             /* The next index to get notified will be uxIndexToNotify, so block
1002              * on uxIndexToNotify + 1 */
1003             uxIndex = uxIndexToNotify + 1;
1004         }
1005
1006         xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xTimerPeriod + xMargin );
1007
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;
1019
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++ )
1023         {
1024             xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
1025
1026             if( uxIndex == uxIndexToNotify )
1027             {
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 );
1032
1033                 /* Set the notification value for this array index back to 0. */
1034                 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndex, notifyUINT32_MAX );
1035             }
1036             else
1037             {
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 );
1042             }
1043         }
1044
1045         /* Incremented to show the task is still running. */
1046         ulFineCycleCount++;
1047     }
1048 }
1049 /* ------------------------------------------------------------------------ */
1050
1051 static void prvBlockOnNotificationsComingFromInterrupts( void )
1052 {
1053     UBaseType_t uxIndex, uxIndexToNotify;
1054     uint32_t ulReceivedValue;
1055     BaseType_t xReturned;
1056     const TickType_t xDontBlock = 0;
1057
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++ )
1061     {
1062         xTaskNotifyIndexed( xTaskToNotify, uxIndex, 0, eSetValueWithOverwrite );
1063         xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
1064     }
1065
1066     /* Perform the test on each task notification within the array of task
1067      * notifications. */
1068     for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
1069     {
1070         /* Tell the interrupt to send the next notification. */
1071         taskENTER_CRITICAL();
1072         {
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
1075              * executed. */
1076             configASSERT( xSendNotificationFromISR == pdFALSE );
1077             xSendNotificationFromISR = pdTRUE;
1078         }
1079         taskEXIT_CRITICAL();
1080
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 );
1084
1085         /* Interrupt should have reset xSendNotificationFromISR after it sent
1086          * the notification. */
1087         configASSERT( xSendNotificationFromISR == pdFALSE );
1088
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. */
1093
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++ )
1099         {
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. */
1104             ( void ) xReturned;
1105         }
1106
1107         /* Incremented to show the task is still running. */
1108         ulFineCycleCount++;
1109     }
1110 }
1111 /*-----------------------------------------------------------*/
1112
1113 void xNotifyArrayTaskFromISR( void )
1114 {
1115     static BaseType_t xAPIToUse = 0;
1116     uint32_t ulPreviousValue;
1117     const uint32_t ulUnexpectedValue = 0xff;
1118     static UBaseType_t uxIndexToNotify = 0;
1119
1120     /* Check the task notification demo task was actually created. */
1121     configASSERT( xTaskToNotify );
1122
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
1125      * notification. */
1126     if( xSendNotificationFromISR == pdTRUE )
1127     {
1128         xSendNotificationFromISR = pdFALSE;
1129
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
1133          * notifications. */
1134         switch( xAPIToUse )
1135         {
1136             case 0:
1137                 vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, NULL );
1138                 xAPIToUse++;
1139                 break;
1140
1141             case 1:
1142                 xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, NULL );
1143                 xAPIToUse++;
1144                 break;
1145
1146             case 2:
1147                 ulPreviousValue = ulUnexpectedValue;
1148                 xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, &ulPreviousValue, NULL );
1149                 configASSERT( ulPreviousValue == 0 );
1150                 xAPIToUse = 0;
1151                 break;
1152
1153             default: /* Should never get here!. */
1154                 break;
1155         }
1156
1157         /* Use the next index in the array of task notifications the next time
1158          * around. */
1159         uxIndexToNotify++;
1160
1161         if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
1162         {
1163             uxIndexToNotify = 0;
1164         }
1165     }
1166 }
1167 /*-----------------------------------------------------------*/
1168
1169 /* This is called to check the created tasks are still running and have not
1170  * detected any errors. */
1171 BaseType_t xAreTaskNotificationArrayTasksStillRunning( void )
1172 {
1173     static uint32_t ulLastFineCycleCount = 0, ulLastCourseCycleCount = 0, ulCallCount = 0;
1174     const uint32_t ulCallsBetweenCourseCycleCountChecks = 3UL;
1175     static BaseType_t xErrorStatus = pdPASS;
1176
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 )
1182     {
1183         xErrorStatus = pdFAIL;
1184     }
1185     else
1186     {
1187         ulLastFineCycleCount = ulFineCycleCount;
1188     }
1189
1190     ulCallCount++;
1191
1192     if( ulCallCount >= ulCallsBetweenCourseCycleCountChecks )
1193     {
1194         ulCallCount = 0;
1195
1196         if( ulLastCourseCycleCount == ulCourseCycleCounter )
1197         {
1198             xErrorStatus = pdFAIL;
1199         }
1200         else
1201         {
1202             ulLastCourseCycleCount = ulCourseCycleCounter;
1203         }
1204     }
1205
1206     return xErrorStatus;
1207 }
1208 /*-----------------------------------------------------------*/
1209
1210 static UBaseType_t prvRand( void )
1211 {
1212     const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
1213
1214     /* Utility function to generate a pseudo random number. */
1215     uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
1216     return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
1217 }
1218 /*-----------------------------------------------------------*/