]> begriffs open source - cmsis-freertos/blob - Demo/Common/Minimal/TaskNotifyArray.c
Updated pack to FreeRTOS 10.4.3
[cmsis-freertos] / Demo / Common / Minimal / TaskNotifyArray.c
1 /*
2  * FreeRTOS V202104.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  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28
29 /*
30  * Tests the behaviour of arrays of task notifications per task.  The tests in this
31  * file are additive to those implemented in FreeRTOS/Demo/Common/Minimal/TaskNotify.c.
32  */
33
34 /* Standard includes. */
35 #include <limits.h>
36
37 /* Scheduler include files. */
38 #include "FreeRTOS.h"
39 #include "task.h"
40 #include "timers.h"
41
42 /* Demo program include files. */
43 #include "TaskNotifyArray.h"
44
45 #if( configTASK_NOTIFICATION_ARRAY_ENTRIES < 3 )
46         #error This file tests direct to task notification arrays and needs configTASK_NOTIFICATION_ARRAY_ENTRIES to be at least 3.
47 #endif
48
49 /* Allow parameters to be overridden on a demo by demo basis. */
50 #ifndef notifyNOTIFY_ARRAY_TASK_STACK_SIZE
51         #define notifyNOTIFY_ARRAY_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
52 #endif
53
54 #define notifyTASK_PRIORITY             ( tskIDLE_PRIORITY )
55
56 /* Constants used in tests when setting/clearing bits. */
57 #define notifyUINT32_MAX                ( ( uint32_t ) 0xffffffff )
58 #define notifyUINT32_HIGH_BYTE  ( ( uint32_t ) 0xff000000 )
59 #define notifyUINT32_LOW_BYTE   ( ( uint32_t ) 0x000000ff )
60
61 /*-----------------------------------------------------------*/
62
63 /*
64  * Implementation of the task that runs the tests - the task runs some tests
65  * itself, and others where notifications are sent from a software timer or
66  * an interrupt (specifically the tick hook function).
67  */
68 static void prvNotifiedTask( void *pvParameters );
69
70 /*
71  * Performs the tests that don't require notifications to be sent from a
72  * remote source.
73  */
74 static void prvSingleTaskTests( void );
75
76 /*
77  * Uses a software timer to send notifications to the task while the task is
78  * suspended.
79  */
80 static void prvTestNotifyTaskWhileSuspended( void );
81
82 /*
83  * Uses a software timer to send notifications to the index within the array of
84  * task notifications on which the task is blocked.  The task should unblock and
85  * the state of all the other task notifications within the array should remain
86  * unchanged.
87  */
88 static void prvBlockOnTheNotifiedIndexed( void );
89
90 /*
91  * As per prvBlockOnTheNotifiedIndexed(), but this time the notification comes from
92  * the tick hook function, so from an interrupt rather than from a software timer.
93  */
94 static void prvBlockOnNotificationsComingFromInterrupts( void );
95
96 /*
97  * As per prvBlockOnTheNotifiedIndexed(), except this time the notification is
98  * sent to an index within the task notification array on which the task is not
99  * blocked, so this time the task should not unblock and the state of all the
100  * task notifications other than the one to which the notification was actually
101  * sent should remain unchanged.
102  */
103 static void prvBlockOnANonNotifiedIndexed( void );
104
105 /*
106  * Callback of the software timer used to send notifications for the
107  * prvBlockOnTheNotifiedIndexed() and prvBlockOnANonNotifiedIndexed() tests.
108  */
109 static void prvNotifyingTimerCallback( TimerHandle_t xTimer );
110
111 /*
112  * Callback for a timer that is used by the prvTestNotifyTaskWhileSuspended()
113  * test.
114  */
115 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
116
117 /*
118  * Utility function to create pseudo random numbers.
119  */
120 static UBaseType_t prvRand( void );
121
122
123 /*-----------------------------------------------------------*/
124
125 /* Counters used to check the task has not stalled.  ulFineCycleCount is
126 incremented within each test.  ulCourseCycleCounter is incremented one every
127 loop of all the tests to ensure each test is actually executing.  The check task
128 calls xAreTaskNotificationArrayTasksStillRunning() (implemented within this
129 file) to check both counters are changing. */
130 static volatile uint32_t ulFineCycleCount = 0, ulCourseCycleCounter = 0;
131
132 /* The handle of the task that runs the tests and receives the notifications
133 from the software timers and interrupts. */
134 static TaskHandle_t xTaskToNotify = NULL;
135
136 /* The software timers used to send notifications to the main test task. */
137 static TimerHandle_t xIncrementingIndexTimer = NULL;
138 static TimerHandle_t xNotifyWhileSuspendedTimer = NULL;
139
140 /* Used by the pseudo random number generating function. */
141 static size_t uxNextRand = 0;
142
143 /* Used to communicate when to send a task notification to the tick hook tests. */
144 static volatile BaseType_t xSendNotificationFromISR = pdFALSE;
145
146 /*-----------------------------------------------------------*/
147
148 void vStartTaskNotifyArrayTask( void  )
149 {
150 const TickType_t xIncrementingIndexTimerPeriod = pdMS_TO_TICKS( 100 );
151 const TickType_t xSuspendTimerPeriod = pdMS_TO_TICKS( 50 );
152
153         /* Create the software timers used for these tests.  The timer callbacks send
154         notifications to this task. */
155         xNotifyWhileSuspendedTimer = xTimerCreate( "SingleNotify", xSuspendTimerPeriod, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
156         xIncrementingIndexTimer = xTimerCreate( "Notifier", xIncrementingIndexTimerPeriod, pdFALSE, NULL, prvNotifyingTimerCallback );
157         configASSERT( xNotifyWhileSuspendedTimer );
158         configASSERT( xIncrementingIndexTimer );
159
160         /* Create the task that performs some tests by itself, then loops around
161         being notified by both a software timer and an interrupt. */
162         xTaskCreate( prvNotifiedTask, /* Function that implements the task. */
163                                  "ArrayNotifed", /* Text name for the task - for debugging only - not used by the kernel. */
164                                  notifyNOTIFY_ARRAY_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */
165                                  NULL, /* Task parameter, not used in this case. */
166                                  notifyTASK_PRIORITY, /* Task priority, 0 is the lowest. */
167                                  &xTaskToNotify ); /* Used to pass a handle to the task out if needed, otherwise set to NULL. */
168
169         /* Pseudo seed the random number generator. */
170         uxNextRand = ( size_t ) prvRand;
171 }
172 /*-----------------------------------------------------------*/
173
174 static void prvNotifiedTask( void *pvParameters )
175 {
176         /* Remove compiler warnings about unused parameters. */
177         ( void ) pvParameters;
178
179         /* Loop through each set of test functions in turn.  See the comments above
180         the respective function prototypes above for more details. */
181         for( ;; )
182         {
183                 prvSingleTaskTests();
184                 prvTestNotifyTaskWhileSuspended();
185                 prvBlockOnTheNotifiedIndexed();
186                 prvBlockOnANonNotifiedIndexed();
187                 prvBlockOnNotificationsComingFromInterrupts();
188                 ulCourseCycleCounter++;
189         }
190 }
191 /*-----------------------------------------------------------*/
192
193 static void prvSingleTaskTests( void )
194 {
195 const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
196 BaseType_t xReturned;
197 uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedValue;
198 TickType_t xTimeOnEntering, xTimeNow, xTimeDifference;
199 const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;
200 const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
201 UBaseType_t uxIndexToTest, uxOtherIndexes;
202
203
204         /* ------------------------------------------------------------------------
205         Check blocking when there are no notifications. */
206         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
207         {
208                 /* Send notifications to the task notification in each index of the
209                 task notification array other than the one on which this task will
210                 block. */
211                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
212                 {
213                         if( uxOtherIndexes != uxIndexToTest )
214                         {
215                                 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, 0, eNoAction );
216                         }
217                 }
218
219                 xTimeOnEntering = xTaskGetTickCount();
220                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
221                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
222
223                 /* Should have blocked for the entire block time. */
224                 xTimeNow = xTaskGetTickCount();
225                 xTimeDifference = xTimeNow - xTimeOnEntering;
226                 configASSERT( xTimeDifference >= xTicksToWait );
227                 configASSERT( xReturned == pdFAIL );
228                 configASSERT( ulNotifiedValue == 0UL );
229                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
230                 ( void ) ulNotifiedValue;
231
232                 /* Clear all the other notifications within the array of task
233                 notifications again ready for the next round. */
234                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
235                 {
236                         if( uxOtherIndexes != uxIndexToTest )
237                         {
238                                 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
239
240                                 /* The notification state was set above so expect it to still be
241                                 set. */
242                                 configASSERT( xReturned == pdTRUE );
243                                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
244                         }
245                 }
246         }
247
248
249
250         /* ------------------------------------------------------------------------
251         Check no blocking when notifications are pending. */
252         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
253         {
254                 /* First notify the task notification at index uxIndexToTest within this
255                 task's own array of task notifications - this would not be a normal
256                 thing to do and is done here for test purposes only. */
257                 xReturned = xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
258
259                 /* Even through the 'without overwrite' action was used the update should
260                 have been successful. */
261                 configASSERT( xReturned == pdPASS );
262                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
263
264                 /* No bits should have been pending previously. */
265                 configASSERT( ulPreviousValue == 0 );
266                 ( void ) ulPreviousValue;
267
268                 /* The task should now have a notification pending in the task
269                 notification at index uxIndexToTest within the task notification array,
270                 and so not time out. */
271                 xTimeOnEntering = xTaskGetTickCount();
272                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
273                 xTimeNow = xTaskGetTickCount();
274                 xTimeDifference = xTimeNow - xTimeOnEntering;
275                 configASSERT( xTimeDifference < xTicksToWait );
276
277                 /* The task should have been notified, and the notified value should
278                 be equal to ulFirstNotifiedConst. */
279                 configASSERT( xReturned == pdPASS );
280                 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
281                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
282                 ( void ) ulNotifiedValue;
283         }
284
285
286
287
288         /*-------------------------------------------------------------------------
289         Check the non-overwriting functionality. */
290         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
291         {
292                 /* Send notifications to all indexes with the array of task
293                 notificaitons other than the one on which this task will block. */
294                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
295                 {
296                         if( uxOtherIndexes != uxIndexToTest )
297                         {
298                                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
299                                 configASSERT(xReturned == pdPASS);
300                                 (void)xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
301                         }
302                 }
303
304                 /* The notification is performed twice using two different notification
305                 values.  The action says don't overwrite so only the first notification
306                 should pass and the value read back should also be that used with the
307                 first notification. The notification is sent to the task notification at
308                 index uxIndexToTest within the array of task notifications. */
309                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
310                 configASSERT( xReturned == pdPASS );
311                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
312
313                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
314                 configASSERT( xReturned == pdFAIL );
315                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
316
317                 /* Waiting for the notification should now return immediately so a block
318                 time of zero is used. */
319                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
320
321                 configASSERT( xReturned == pdPASS );
322                 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
323                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
324                 ( void ) ulNotifiedValue;
325
326                 /* Clear all the other task notifications within the array of task
327                 notifications again ready for the next round. */
328                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
329                 {
330                         if( uxOtherIndexes != uxIndexToTest )
331                         {
332                                 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
333                                 configASSERT( xReturned == pdTRUE );
334                                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
335
336                                 ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
337
338                                 /* The notification value was set to ulFirstNotifiedConst in all
339                                 the other indexes, so expect it to still have that value. */
340                                 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
341                                 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
342                         }
343                 }
344         }
345
346
347
348
349         /*-------------------------------------------------------------------------
350         Do the same again, only this time use the overwriting version.  This time
351         both notifications should pass, and the value written the second time should
352         overwrite the value written the first time, and so be the value that is read
353         back. */
354         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
355         {
356                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
357                 {
358                         if( uxOtherIndexes != uxIndexToTest )
359                         {
360                                 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
361                         }
362                 }
363
364                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithOverwrite );
365                 configASSERT( xReturned == pdPASS );
366                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
367                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
368                 configASSERT( xReturned == pdPASS );
369                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
370                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, notifyUINT32_MAX, &ulNotifiedValue, 0 );
371                 configASSERT( xReturned == pdPASS );
372                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
373                 configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
374                 ( void ) ulNotifiedValue;
375
376                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
377                 {
378                         if( uxOtherIndexes != uxIndexToTest )
379                         {
380                                 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
381                                 configASSERT( xReturned == pdTRUE );
382                                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
383                                 ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
384                                 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
385                                 ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
386                         }
387                 }
388         }
389
390
391
392
393         /*-------------------------------------------------------------------------
394         For each task notification within the array of task notifications, check
395         notifications with no action pass without updating the value. */
396         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
397         {
398                 /* First set the notification values of the task notification at index
399                 uxIndexToTest of the array of task notification to
400                 ulSecondNotifiedValueConst. */
401                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
402                 configASSERT( xReturned == pdPASS );
403                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
404
405                 /* Even though ulFirstNotifiedConst is used as the value next, the value
406                 read back should remain at ulSecondNotifiedConst as the action is set
407                 to eNoAction. */
408                 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eNoAction );
409                 configASSERT( xReturned == pdPASS );
410                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
411
412                 /* All task notifications in the array of task notifications up to and
413                 including index uxIndexToTest should still contain the same value. */
414                 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
415                 {
416                         /* First zero is bits to clear on entry, the second is bits to clear on
417                         exist, the last 0 is the block time. */
418                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
419                         configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
420                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
421                 }
422
423                 /* All array indexes in the array of task notifications after index
424                 uxIndexToTest should still contain 0 as they have not been set in this
425                 loop yet.  This time use ulTaskNotifyValueClearIndexed() instead of
426                 xTaskNotifyWaitIndexed(), just for test coverage. */
427                 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
428                 {
429                         /* This time 0 is the bits to clear parameter - so clearing no bits. */
430                         ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
431                         configASSERT( ulNotifiedValue == 0 );
432                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
433                 }
434         }
435
436
437
438
439         /*-------------------------------------------------------------------------
440         Check incrementing values.  For each task notification in the array of task
441         notifications in turn, send ulMaxLoop increment notifications, then ensure
442         the received value is as expected - which should be
443         ulSecondNotificationValueConst plus how ever many times to loop iterated. */
444         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
445         {
446                 for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
447                 {
448                         /* Increment the value of the task notification at index
449                         uxIndexToTest within the array of task notifications. */
450                         xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eIncrement );
451                         configASSERT( xReturned == pdPASS );
452                         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
453                 }
454
455                 /* All array indexes up to and including uxIndexToTest should still
456                 contain the updated value. */
457                 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
458                 {
459                         /* First zero is bits to clear on entry, the second is bits to clear on
460                         exist, the last 0 is the block time. */
461                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
462                         configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
463                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
464                 }
465
466                 /* Should not be any notifications pending now. */
467                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, 0 );
468                 configASSERT( xReturned == pdFAIL );
469                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
470                 ( void ) ulNotifiedValue;
471
472                 /* All notifications values in the array of task notifications after
473                 index uxIndexToTest should still contain the un-incremented
474                 ulSecondNotifiedValueConst as they have not been set in this loop yet.
475                 This time use ulTaskNotifyValueClearIndexed() instead of xTaskNotifyWaitIndexed(),
476                 just for test coverage. */
477                 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
478                 {
479                         /* This time 0 is the bits to clear parameter - so clearing no bits. */
480                         ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
481                         configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
482                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
483                 }
484         }
485
486         /* Clear all bits ready for next test. */
487         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
488         {
489                 /* Start with all bits clear. */
490                 ulTaskNotifyValueClearIndexed( NULL, uxIndexToTest, notifyUINT32_MAX );
491         }
492
493
494
495         /*-------------------------------------------------------------------------
496         For each task notification in the array of task notifications in turn, check
497         all bits in the notification's value can be set by notifying the task with
498         one additional bit set on each notification, and exiting the loop when all
499         the bits are found to be set.  As there are 32-bits the loop should execute
500         32 times before all the bits are found to be set. */
501         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
502         {
503                 ulNotifyingValue = 0x01;
504                 ulLoop = 0;
505
506                 do
507                 {
508                         /* Set the next bit in the value of the task notification at index
509                         uxIndexToTest within the array of task notifications. */
510                         xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulNotifyingValue, eSetBits );
511
512                         /* Wait for the notified value - which of course will already be
513                         available.  Don't clear the bits on entry or exit as this loop is
514                         exited when all the bits are set. */
515                         xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, 0 );
516                         configASSERT( xReturned == pdPASS );
517                         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
518
519                         ulLoop++;
520
521                         /* Use the next bit on the next iteration around this loop. */
522                         ulNotifyingValue <<= 1UL;
523
524                 } while ( ulNotifiedValue != notifyUINT32_MAX );
525
526                 /* As a 32-bit value was used the loop should have executed 32 times before
527                 all the bits were set. */
528                 configASSERT( ulLoop == 32 );
529
530                 /* The value of each task notification within the array of task
531                 notifications up to and including index uxIndexToTest should still have
532                 all bits set. */
533                 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
534                 {
535                         /* First zero is bits to clear on entry, the second is bits to clear on
536                         exist, the last 0 is the block time. */
537                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
538                         configASSERT( ulNotifiedValue == notifyUINT32_MAX );
539                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
540                 }
541
542                 /* The value of each task notification within the array of task
543                 notifications after index uxIndexToTest should still contain 0 as they
544                 have not been set in this loop yet.  This time use ulTaskNotifyValueClearIndexed()
545                 instead of xTaskNotifyWaitIndexed(), just for test coverage. */
546                 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
547                 {
548                         /* This time 0 is the bits to clear parameter - so clearing no bits. */
549                         ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
550                         configASSERT( ulNotifiedValue == 0 );
551                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
552                 }
553         }
554
555
556
557         /*-------------------------------------------------------------------------
558         For each task notification within the array of task notifications in turn,
559         check bits are cleared on entry but not on exit when a notification fails
560         to arrive before timing out - both with and without a timeout value. */
561         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
562         {
563                 /* Wait for the notification - but this time it is not given by anything
564                 and should return pdFAIL.  The parameters are set to clear bit zero on
565                 entry and bit one on exit.  As no notification was received only the bit
566                 cleared on entry should actually get cleared. */
567                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
568                 configASSERT( xReturned == pdFAIL );
569                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
570
571                 /* Send a notification with no action to the task notification at index
572                 uxIndexToTest within the array of task notifications.  This should not
573                 update the bits even though notifyUINT32_MAX is used as the notification
574                 value. */
575                 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eNoAction );
576
577                 /* All array indexes up to and including uxIndexToTest within the array
578                 of task notifications should have the modified value.  */
579                 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
580                 {
581                         /* Reading back the value should find bit 0 is clear, as this was cleared
582                         on entry, but bit 1 is not clear as it will not have been cleared on exit
583                         as no notification was received. */
584                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
585                         if( uxOtherIndexes == uxIndexToTest )
586                         {
587                                 /* This is the index being used this time round the loop and its
588                                 notification state was set immediately above. */
589                                 configASSERT( xReturned == pdPASS );
590                         }
591                         else
592                         {
593                                 /* Nothing should have set this index's notification state again. */
594                                 configASSERT( xReturned == pdFAIL );
595                         }
596
597                         configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
598                         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
599                 }
600
601                 /* All array indexes after uxIndexToTest should still contain notifyUINT32_MAX
602                 left over from the previous test.  This time use xTaskNotifyValueClear()
603                 instead of xTaskNotifyWaitIndexed(), just for test coverage. */
604                 for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
605                 {
606                         /* This time 0 is the bits to clear parameter - so clearing no bits. */
607                         ulNotifiedValue = ulTaskNotifyValueClearIndexed( NULL, uxOtherIndexes, 0 );
608                         configASSERT( ulNotifiedValue == notifyUINT32_MAX );
609                         ( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
610                 }
611         }
612
613
614
615
616         /*-------------------------------------------------------------------------
617         Now try clearing the bit on exit. */
618         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
619         {
620                 /* The task is notified first using the task notification at index
621                 uxIndexToTest within the array of task notifications. */
622                 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eNoAction );
623                 xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, ulBit1, &ulNotifiedValue, 0 );
624
625                 /* However as the bit is cleared on exit, after the returned notification
626                 value is set, the returned notification value should not have the bit
627                 cleared... */
628                 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
629
630                 /* ...but reading the value back again should find that the bit was indeed
631                 cleared internally.  The returned value should be pdFAIL however as nothing
632                 has notified the task in the mean time. */
633                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, 0x00, &ulNotifiedValue, 0 );
634                 configASSERT( xReturned == pdFAIL );
635                 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
636                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
637
638                 /* No other indexes should have a notification pending. */
639                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
640                 {
641                         if( uxOtherIndexes != uxIndexToTest )
642                         {
643                                 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
644                                 configASSERT( xReturned == pdFAIL );
645                                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
646                         }
647                 }
648         }
649
650
651
652         /*-------------------------------------------------------------------------
653         For each task notification within the array of task notifications, try
654         querying the previous value while notifying a task. */
655         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
656         {
657                 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
658                 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
659
660                 /* Clear all bits. */
661                 xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
662                 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
663                 configASSERT( ulPreviousValue == 0 );
664
665                 ulExpectedValue = 0;
666                 for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
667                 {
668                         /* Set the next bit up, and expect to receive the last bits set (so
669                         the previous value will not yet have the bit being set this time
670                         around). */
671                         xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulLoop, eSetBits, &ulPreviousValue );
672                         configASSERT( ulExpectedValue == ulPreviousValue );
673                         ulExpectedValue |= ulLoop;
674                 }
675         }
676
677
678         /* ---------------------------------------------------------------------- */
679         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
680         {
681                 /* Clear the previous notifications. */
682                 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
683         }
684
685         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
686         {
687                 /* No task notification within the array of task notifications should
688                 have any notification pending, so an attempt to clear the notification
689                 state should fail. */
690                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
691                 {
692                         configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
693                 }
694
695                 /* Get the task to notify itself using the task notification at index
696                 uxIndexToTest within the array of task notifications.  This is not a
697                 normal thing to do, and is only done here for test purposes. */
698                 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
699
700                 /* Now the notification state should be eNotified, so it should now be
701                 possible to clear the notification state.  Other indexes should still
702                 not have a notification pending - likewise uxIndexToTest should not have
703                 a notification pending once it has been cleared. */
704                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
705                 {
706                         if( uxOtherIndexes == uxIndexToTest )
707                         {
708                                 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdTRUE );
709                         }
710
711                         configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
712                 }
713         }
714
715
716         /* ------------------------------------------------------------------------
717         For each task notification within the array of task notifications, clear
718         bits in the notification value. */
719         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
720         {
721                 /* Get the task to set all bits in its task notification at index
722                 uxIndexToTest within its array of task notifications.  This is not a
723                 normal thing to do, and is only done here for test purposes. */
724                 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eSetBits );
725
726                 /* Now clear the top bytes - the returned value from the first call
727                 should indicate that previously all bits were set. */
728                 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );
729
730                 /* Next clear the bottom bytes - the returned value this time should
731                 indicate that the top byte was clear (before the bottom byte was
732                 cleared. */
733                 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
734
735                 /* Next clear all bytes - the returned value should indicate that previously the
736                 high and low bytes were clear. */
737                 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );
738
739                 /* Now all bits should be clear. */
740                 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == 0 );
741                 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, 0UL ) == 0 );
742                 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == 0 );
743
744                 /* Now the notification state should be eNotified, so it should now be
745                 possible to clear the notification state. */
746                 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdTRUE );
747                 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdFALSE );
748         }
749
750
751
752
753         /* Incremented to show the task is still running. */
754         ulFineCycleCount++;
755
756         /* Leave all bits cleared. */
757         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
758         {
759                 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
760         }
761 }
762 /*-----------------------------------------------------------*/
763
764 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
765 {
766 static uint32_t ulCallCount = 0;
767 static UBaseType_t uxIndexToNotify = 0;
768
769         /* Remove compiler warnings about unused parameters. */
770         ( void ) xExpiredTimer;
771
772         /* Callback for a timer that is used to send notifications to a task while
773         it is suspended.  The timer tests the behaviour when 1: a task waiting for a
774         notification is suspended and then resumed without ever receiving a
775         notification, and 2: when a task waiting for a notification receives a
776         notification while it is suspended.  Run one of two tests on every other
777         invocation of this callback.  The notification is sent to the task
778         notification at index uxIndexToNotify. */
779         if( ( ulCallCount & 0x01 ) == 0 )
780         {
781                 vTaskSuspend( xTaskToNotify );
782                 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
783                 vTaskResume( xTaskToNotify );
784         }
785         else
786         {
787                 vTaskSuspend( xTaskToNotify );
788
789                 /* Sending a notification while the task is suspended should pass, but
790                 not cause the task to resume. */
791                 xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 1, eSetValueWithOverwrite );
792
793                 /* Use the next task notification within the array of task notifications
794                 the next time around. */
795                 uxIndexToNotify++;
796                 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
797                 {
798                         uxIndexToNotify = 0;
799                 }
800
801                 /* Make sure giving the notification didn't resume the task. */
802                 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
803
804                 vTaskResume( xTaskToNotify );
805         }
806
807         ulCallCount++;
808 }
809 /*-----------------------------------------------------------*/
810
811 static void prvNotifyingTimerCallback( TimerHandle_t xNotUsed )
812 {
813 static BaseType_t uxIndexToNotify = 0;
814
815         ( void ) xNotUsed;
816
817         /* "Give" the task notification (which increments the target task
818         notification value) at index uxIndexToNotify within the array of task
819         notifications. */
820         xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
821
822         /* Use the next task notification within the array of task notifications the
823         next time around. */
824         uxIndexToNotify++;
825         if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
826         {
827                 uxIndexToNotify = 0;
828         }
829 }
830 /*-----------------------------------------------------------*/
831
832 static void prvTestNotifyTaskWhileSuspended( void )
833 {
834 UBaseType_t uxIndexToTest, uxOtherIndexes;
835 BaseType_t xReturned;
836 uint32_t ulNotifiedValue;
837
838         /* Raise the task's priority so it can suspend itself before the timer
839         expires. */
840         vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
841
842         /* Perform the test on each task notification within the array or task
843         notifications. */
844         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
845         {
846                 /* Ensure no notifications within the array of task notifications are
847                 pending. */
848                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
849                 {
850                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, NULL, 0 );
851                         configASSERT( xReturned == pdFALSE );
852                         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
853                 }
854
855                 /* Start the timer that will try notifying this task while it is
856                 suspended, then wait for a notification.  The first time the callback
857                 executes the timer will suspend the task, then resume the task, without
858                 ever sending a notification to the task. */
859                 ulNotifiedValue = 0;
860                 xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
861
862                 /* Check a notification is not received on the task notification at
863                 index uxIndexToTest within the array of task notifications. */
864                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
865                 configASSERT( xReturned == pdFALSE );
866                 configASSERT( ulNotifiedValue == 0 );
867                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
868
869                 /* Check none of the task notifications within the array of task
870                 notifications as been notified. */
871                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
872                 {
873                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
874                         configASSERT( xReturned == pdFALSE );
875                         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
876                 }
877
878                 /* Start the timer that will try notifying this task while it is
879                 suspended, then wait for a notification at index uxIndexToTest within
880                 the array of task notifications.  The second time the callback executes
881                 the timer will suspend the task, notify the task, then resume the task
882                 (previously it was suspended and resumed without being notified). */
883                 xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
884
885                 /* Check a notification is only received in the index within the array
886                 of task notifications under test. */
887                 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
888                 configASSERT( xReturned == pdPASS );
889                 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
890                 configASSERT( ulNotifiedValue != 0 );
891
892                 /* Check a notification is not received in any index within the array
893                 of task notifications at and below the index being tested have a notification
894                 value, and that indexes above the index being tested to not have
895                 notification values. */
896                 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
897                 {
898                         xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
899                         configASSERT( xReturned == pdFALSE );
900
901                         if( uxOtherIndexes <= uxIndexToTest )
902                         {
903                                 configASSERT( ulNotifiedValue == 1 );
904                         }
905                         else
906                         {
907                                 configASSERT( ulNotifiedValue == 0 );
908                         }
909                         ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
910                         ( void ) ulNotifiedValue;
911                 }
912         }
913
914         /* Return the task to its proper priority */
915         vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
916
917         /* Incremented to show the task is still running. */
918         ulFineCycleCount++;
919
920         /* Leave all bits cleared. */
921         for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
922         {
923                 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
924         }
925 }
926 /* ------------------------------------------------------------------------ */
927
928 static void prvBlockOnTheNotifiedIndexed( void )
929 {
930 const TickType_t xTimerPeriod = pdMS_TO_TICKS( 100 ), xMargin = pdMS_TO_TICKS( 50 ), xDontBlock = 0;
931 UBaseType_t uxIndex, uxIndexToNotify;
932 uint32_t ulReceivedValue;
933 BaseType_t xReturned;
934
935         /* Set the value of each notification in the array of task notifications to
936         the value of its index position plus 1 so everything starts in a known
937         state, then clear the notification state ready for the next test.  Plus 1 is
938         used because the index under test will use 0. */
939         for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
940         {
941                 xTaskNotifyIndexed( xTaskToNotify, uxIndex, uxIndex + 1, eSetValueWithOverwrite );
942                 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
943         }
944
945         /* Peform the test on each task notification within the array of task
946         notifications. */
947         for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
948         {
949                 /* Set the notification value of the index being tested to 0 so the
950                 notification value increment/decrement functions can be tested. */
951                 xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 0, eSetValueWithOverwrite );
952                 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
953
954                 /* Start the software timer then wait for it to notify this task.  Block
955                 on the notification index we expect to receive the notification on.  The
956                 margin is to ensure the task blocks longer than the timer period. */
957                 xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
958                 ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdFALSE, xTimerPeriod + xMargin );
959
960                 /* The notification value was initially zero, and should have been
961                 incremented by the software timer, so now one.  It will also have been
962                 decremented again by the call to ulTaskNotifyTakeIndexed() so gone back
963                 to 0. */
964                 configASSERT( ulReceivedValue == 1UL );
965                 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
966
967                 /* No other notification indexes should have changed, and therefore should
968                 still have their value set to their index plus 1 within the array of
969                 notifications. */
970                 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
971                 {
972                         if( uxIndex != uxIndexToNotify )
973                         {
974                                 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
975                                 configASSERT( xReturned == pdFALSE );
976                                 configASSERT( ulReceivedValue == ( uxIndex + 1 ) );
977                                 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
978                                 ( void ) xReturned;
979                         }
980                 }
981
982                 /* Reset the notification value for the index just tested back to the
983                 index value plus 1 ready for the next iteration around this loop. */
984                 xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, uxIndexToNotify + 1, eSetValueWithOverwrite );
985                 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
986
987                 /* Incremented to show the task is still running. */
988                 ulFineCycleCount++;
989         }
990 }
991 /* ------------------------------------------------------------------------ */
992
993 static void prvBlockOnANonNotifiedIndexed( void )
994 {
995 const TickType_t xTimerPeriod = pdMS_TO_TICKS( 100 ), xMargin = pdMS_TO_TICKS( 50 ), xDontBlock = 0;
996 UBaseType_t uxIndex, uxIndexToNotify;
997 uint32_t ulReceivedValue;
998 BaseType_t xReturned;
999 TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
1000
1001         /* Set all notify values within the array of tasks notifications to zero
1002         ready for the next test. */
1003         for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
1004         {
1005                 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToNotify, notifyUINT32_MAX );
1006         }
1007
1008         /* Perform the test for each notification within the array of task
1009         notifications. */
1010         for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
1011         {
1012                 /* Start the software timer then wait for it to notify this task.  Block
1013                 on a notification index that we do not expect to receive the notification
1014                 on.  The margin is to ensure the task blocks longer than the timer period. */
1015                 xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
1016                 xTimeBeforeBlocking = xTaskGetTickCount();
1017
1018
1019                 if( uxIndexToNotify == ( configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 ) )
1020                 {
1021                         /* configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 is to be notified, so
1022                         block on index 0. */
1023                         uxIndex = 0;
1024                 }
1025                 else
1026                 {
1027                         /* The next index to get notified will be uxIndexToNotify, so block
1028                         on uxIndexToNotify + 1 */
1029                         uxIndex = uxIndexToNotify + 1;
1030                 }
1031
1032                 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xTimerPeriod + xMargin );
1033
1034                 /* The notification will have been sent to task notification at index
1035                 uxIndexToNotify in this task by the timer callback after xTimerPeriodTicks.
1036                 The notification should not have woken this task, so xReturned should
1037                 be false and at least xTimerPeriod + xMargin ticks should have passed. */
1038                 configASSERT( xReturned == pdFALSE );
1039                 xTimeNow = xTaskGetTickCount();
1040                 xTimeDifference = xTimeNow - xTimeBeforeBlocking;
1041                 configASSERT( xTimeDifference >= ( xTimerPeriod + xMargin ) );
1042                 ( void ) xReturned; /* Remove compiler warnings if configASSERT() is not defined. */
1043                 ( void ) xTimeBeforeBlocking;
1044                 ( void ) xTimeDifference;
1045
1046                 /* Only the notification at index position uxIndexToNotify should be
1047                 set.  Calling this function will clear it again. */
1048                 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
1049                 {
1050                         xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
1051
1052                         if( uxIndex == uxIndexToNotify )
1053                         {
1054                                 /* Expect the notification state to be set and the notification
1055                                 value to have been incremented. */
1056                                 configASSERT( xReturned == pdTRUE );
1057                                 configASSERT( ulReceivedValue == 1 );
1058
1059                                 /* Set the notification value for this array index back to 0. */
1060                                 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndex, notifyUINT32_MAX );
1061                         }
1062                         else
1063                         {
1064                                 /* Expect the notification state to be clear and the notification
1065                                 value to remain at zer0. */
1066                                 configASSERT( xReturned == pdFALSE );
1067                                 configASSERT( ulReceivedValue == 0 );
1068                         }
1069                 }
1070
1071                 /* Incremented to show the task is still running. */
1072                 ulFineCycleCount++;
1073         }
1074 }
1075 /* ------------------------------------------------------------------------ */
1076
1077 static void prvBlockOnNotificationsComingFromInterrupts( void )
1078 {
1079 UBaseType_t uxIndex, uxIndexToNotify;
1080 uint32_t ulReceivedValue;
1081 BaseType_t xReturned;
1082 const TickType_t xDontBlock = 0;
1083
1084         /* Set the value of each notification within the array of task notifications
1085         to zero so the task can block on xTaskNotifyTake(). */
1086         for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
1087         {
1088                 xTaskNotifyIndexed( xTaskToNotify, uxIndex, 0, eSetValueWithOverwrite );
1089                 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
1090         }
1091
1092         /* Perform the test on each task notification within the array of task
1093         notifications. */
1094         for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
1095         {
1096                 /* Tell the interrupt to send the next notification. */
1097                 taskENTER_CRITICAL();
1098                 {
1099                         /* Don't expect to find xSendNotificationFromISR set at this time as
1100                         the interrupt should have cleared it back to pdFALSE last time it
1101                         executed. */
1102                         configASSERT( xSendNotificationFromISR == pdFALSE );
1103                         xSendNotificationFromISR = pdTRUE;
1104                 }
1105                 taskEXIT_CRITICAL();
1106
1107                 /* Wait for a notification on the task notification at index
1108                 uxIndexToNotify within the array of task notifications. */
1109                 ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdTRUE, portMAX_DELAY );
1110
1111                 /* Interrupt should have reset xSendNotificationFromISR after it sent
1112                 the notificatino. */
1113                 configASSERT( xSendNotificationFromISR == pdFALSE );
1114
1115                 /* The notification value was initially zero, and should have been
1116                 incremented by the interrupt, so now one. */
1117                 configASSERT( ulReceivedValue == 1UL );
1118                 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
1119
1120                 /* No other notification indexes should have changed, and therefore should
1121                 still have their value set to 0.  The value in array index uxIndexToNotify
1122                 should also have been decremented back to zero by the call to
1123                 ulTaskNotifyTakeIndexed(). */
1124                 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
1125                 {
1126                         xReturned = xTaskNotifyWaitIndexed( uxIndexToNotify, 0, 0, &ulReceivedValue, xDontBlock );
1127                         configASSERT( xReturned == pdFALSE );
1128                         configASSERT( ulReceivedValue == 0 );
1129                         ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
1130                         ( void ) xReturned;
1131                 }
1132
1133                 /* Incremented to show the task is still running. */
1134                 ulFineCycleCount++;
1135         }
1136 }
1137 /*-----------------------------------------------------------*/
1138
1139 void xNotifyArrayTaskFromISR( void )
1140 {
1141 static BaseType_t xAPIToUse = 0;
1142 uint32_t ulPreviousValue;
1143 const uint32_t ulUnexpectedValue = 0xff;
1144 static UBaseType_t uxIndexToNotify = 0;
1145
1146         /* Check the task notification demo task was actually created. */
1147         configASSERT( xTaskToNotify );
1148
1149         /* The task sets xSendNotificationFromISR to pdTRUE each time it wants this
1150         interrupt (this function runs in the RTOS tick hook) to send the next
1151         notification. */
1152         if( xSendNotificationFromISR == pdTRUE )
1153         {
1154                 xSendNotificationFromISR = pdFALSE;
1155
1156                 /* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
1157                 and xTaskNotifyAndQueryFromISR(). The notification is set to the task
1158                 notification at index uxIndexToNotify within the array of task
1159                 notifications. */
1160                 switch( xAPIToUse )
1161                 {
1162                         case 0: vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, NULL );
1163                                         xAPIToUse++;
1164                                         break;
1165
1166                         case 1: xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, NULL );
1167                                         xAPIToUse++;
1168                                         break;
1169
1170                         case 2: ulPreviousValue = ulUnexpectedValue;
1171                                         xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, &ulPreviousValue, NULL );
1172                                         configASSERT( ulPreviousValue == 0 );
1173                                         xAPIToUse = 0;
1174                                         break;
1175
1176                         default:/* Should never get here!. */
1177                                         break;
1178                 }
1179
1180                 /* Use the next index in the array of task notifications the next time
1181                 around. */
1182                 uxIndexToNotify++;
1183                 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
1184                 {
1185                         uxIndexToNotify = 0;
1186                 }
1187         }
1188 }
1189 /*-----------------------------------------------------------*/
1190
1191 /* This is called to check the created tasks are still running and have not
1192 detected any errors. */
1193 BaseType_t xAreTaskNotificationArrayTasksStillRunning( void )
1194 {
1195 static uint32_t ulLastFineCycleCount = 0, ulLastCourseCycleCount = 0, ulCallCount = 0;
1196 const uint32_t ulCallsBetweenCourseCycleCountChecks = 3UL;
1197 static BaseType_t xErrorStatus = pdPASS;
1198
1199         /* Check the cycle count is still incrementing to ensure the task is still
1200         actually running.  The fine counter is incremented within individual test
1201         functions.  The course counter is incremented one each time all the test
1202         functions have been executed to ensure all the tests are running. */
1203         if( ulLastFineCycleCount == ulFineCycleCount )
1204         {
1205                 xErrorStatus = pdFAIL;
1206         }
1207         else
1208         {
1209                 ulLastFineCycleCount = ulFineCycleCount;
1210         }
1211
1212         ulCallCount++;
1213         if( ulCallCount >= ulCallsBetweenCourseCycleCountChecks )
1214         {
1215                 ulCallCount = 0;
1216                 if( ulLastCourseCycleCount == ulCourseCycleCounter )
1217                 {
1218                         xErrorStatus = pdFAIL;
1219                 }
1220                 else
1221                 {
1222                         ulLastCourseCycleCount = ulCourseCycleCounter;
1223                 }
1224         }
1225
1226         return xErrorStatus;
1227 }
1228 /*-----------------------------------------------------------*/
1229
1230 static UBaseType_t prvRand( void )
1231 {
1232 const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
1233
1234         /* Utility function to generate a pseudo random number. */
1235         uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
1236         return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
1237 }
1238 /*-----------------------------------------------------------*/