3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
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.
34 /* Standard includes. */
37 /* Scheduler include files. */
42 /* Demo program include files. */
43 #include "TaskNotifyArray.h"
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.
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
54 #define notifyTASK_PRIORITY ( tskIDLE_PRIORITY )
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 )
61 /*-----------------------------------------------------------*/
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).
68 static void prvNotifiedTask( void *pvParameters );
71 * Performs the tests that don't require notifications to be sent from a
74 static void prvSingleTaskTests( void );
77 * Uses a software timer to send notifications to the task while the task is
80 static void prvTestNotifyTaskWhileSuspended( void );
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
88 static void prvBlockOnTheNotifiedIndexed( void );
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.
94 static void prvBlockOnNotificationsComingFromInterrupts( void );
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.
103 static void prvBlockOnANonNotifiedIndexed( void );
106 * Callback of the software timer used to send notifications for the
107 * prvBlockOnTheNotifiedIndexed() and prvBlockOnANonNotifiedIndexed() tests.
109 static void prvNotifyingTimerCallback( TimerHandle_t xTimer );
112 * Callback for a timer that is used by the prvTestNotifyTaskWhileSuspended()
115 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );
118 * Utility function to create pseudo random numbers.
120 static UBaseType_t prvRand( void );
123 /*-----------------------------------------------------------*/
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;
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;
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;
140 /* Used by the pseudo random number generating function. */
141 static size_t uxNextRand = 0;
143 /* Used to communicate when to send a task notification to the tick hook tests. */
144 static volatile BaseType_t xSendNotificationFromISR = pdFALSE;
146 /*-----------------------------------------------------------*/
148 void vStartTaskNotifyArrayTask( void )
150 const TickType_t xIncrementingIndexTimerPeriod = pdMS_TO_TICKS( 100 );
151 const TickType_t xSuspendTimerPeriod = pdMS_TO_TICKS( 50 );
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 );
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. */
169 /* Pseudo seed the random number generator. */
170 uxNextRand = ( size_t ) prvRand;
172 /*-----------------------------------------------------------*/
174 static void prvNotifiedTask( void *pvParameters )
176 /* Remove compiler warnings about unused parameters. */
177 ( void ) pvParameters;
179 /* Loop through each set of test functions in turn. See the comments above
180 the respective function prototypes above for more details. */
183 prvSingleTaskTests();
184 prvTestNotifyTaskWhileSuspended();
185 prvBlockOnTheNotifiedIndexed();
186 prvBlockOnANonNotifiedIndexed();
187 prvBlockOnNotificationsComingFromInterrupts();
188 ulCourseCycleCounter++;
191 /*-----------------------------------------------------------*/
193 static void prvSingleTaskTests( void )
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;
204 /* ------------------------------------------------------------------------
205 Check blocking when there are no notifications. */
206 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
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
211 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
213 if( uxOtherIndexes != uxIndexToTest )
215 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, 0, eNoAction );
219 xTimeOnEntering = xTaskGetTickCount();
220 xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
221 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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;
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++ )
236 if( uxOtherIndexes != uxIndexToTest )
238 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
240 /* The notification state was set above so expect it to still be
242 configASSERT( xReturned == pdTRUE );
243 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
250 /* ------------------------------------------------------------------------
251 Check no blocking when notifications are pending. */
252 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
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 );
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. */
264 /* No bits should have been pending previously. */
265 configASSERT( ulPreviousValue == 0 );
266 ( void ) ulPreviousValue;
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 );
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;
288 /*-------------------------------------------------------------------------
289 Check the non-overwriting functionality. */
290 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
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++ )
296 if( uxOtherIndexes != uxIndexToTest )
298 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
299 configASSERT(xReturned == pdPASS);
300 (void)xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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. */
313 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
314 configASSERT( xReturned == pdFAIL );
315 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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 );
321 configASSERT( xReturned == pdPASS );
322 configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
323 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
324 ( void ) ulNotifiedValue;
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++ )
330 if( uxOtherIndexes != uxIndexToTest )
332 xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
333 configASSERT( xReturned == pdTRUE );
334 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
336 ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
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. */
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
354 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
356 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
358 if( uxOtherIndexes != uxIndexToTest )
360 xTaskNotifyIndexed( xTaskToNotify, uxOtherIndexes, ulFirstNotifiedConst, eSetValueWithOverwrite );
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;
376 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
378 if( uxOtherIndexes != uxIndexToTest )
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. */
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++ )
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. */
405 /* Even though ulFirstNotifiedConst is used as the value next, the value
406 read back should remain at ulSecondNotifiedConst as the action is set
408 xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eNoAction );
409 configASSERT( xReturned == pdPASS );
410 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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++ )
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. */
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++ )
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. */
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++ )
446 for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
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. */
455 /* All array indexes up to and including uxIndexToTest should still
456 contain the updated value. */
457 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
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. */
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;
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++ )
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. */
486 /* Clear all bits ready for next test. */
487 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
489 /* Start with all bits clear. */
490 ulTaskNotifyValueClearIndexed( NULL, uxIndexToTest, notifyUINT32_MAX );
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++ )
503 ulNotifyingValue = 0x01;
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 );
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. */
521 /* Use the next bit on the next iteration around this loop. */
522 ulNotifyingValue <<= 1UL;
524 } while ( ulNotifiedValue != notifyUINT32_MAX );
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 );
530 /* The value of each task notification within the array of task
531 notifications up to and including index uxIndexToTest should still have
533 for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
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. */
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++ )
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. */
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++ )
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. */
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
575 xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eNoAction );
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++ )
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 )
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 );
593 /* Nothing should have set this index's notification state again. */
594 configASSERT( xReturned == pdFAIL );
597 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
598 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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++ )
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. */
616 /*-------------------------------------------------------------------------
617 Now try clearing the bit on exit. */
618 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
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 );
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
628 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
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. */
638 /* No other indexes should have a notification pending. */
639 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
641 if( uxOtherIndexes != uxIndexToTest )
643 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
644 configASSERT( xReturned == pdFAIL );
645 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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++ )
657 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
658 configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
660 /* Clear all bits. */
661 xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );
662 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
663 configASSERT( ulPreviousValue == 0 );
666 for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
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
671 xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulLoop, eSetBits, &ulPreviousValue );
672 configASSERT( ulExpectedValue == ulPreviousValue );
673 ulExpectedValue |= ulLoop;
678 /* ---------------------------------------------------------------------- */
679 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
681 /* Clear the previous notifications. */
682 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
685 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
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++ )
692 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
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 );
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++ )
706 if( uxOtherIndexes == uxIndexToTest )
708 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdTRUE );
711 configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
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++ )
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 );
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 );
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
733 configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
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 ) );
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 );
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 );
753 /* Incremented to show the task is still running. */
756 /* Leave all bits cleared. */
757 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
759 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
762 /*-----------------------------------------------------------*/
764 static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )
766 static uint32_t ulCallCount = 0;
767 static UBaseType_t uxIndexToNotify = 0;
769 /* Remove compiler warnings about unused parameters. */
770 ( void ) xExpiredTimer;
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 )
781 vTaskSuspend( xTaskToNotify );
782 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
783 vTaskResume( xTaskToNotify );
787 vTaskSuspend( xTaskToNotify );
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 );
793 /* Use the next task notification within the array of task notifications
794 the next time around. */
796 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
801 /* Make sure giving the notification didn't resume the task. */
802 configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );
804 vTaskResume( xTaskToNotify );
809 /*-----------------------------------------------------------*/
811 static void prvNotifyingTimerCallback( TimerHandle_t xNotUsed )
813 static BaseType_t uxIndexToNotify = 0;
817 /* "Give" the task notification (which increments the target task
818 notification value) at index uxIndexToNotify within the array of task
820 xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
822 /* Use the next task notification within the array of task notifications the
825 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
830 /*-----------------------------------------------------------*/
832 static void prvTestNotifyTaskWhileSuspended( void )
834 UBaseType_t uxIndexToTest, uxOtherIndexes;
835 BaseType_t xReturned;
836 uint32_t ulNotifiedValue;
838 /* Raise the task's priority so it can suspend itself before the timer
840 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
842 /* Perform the test on each task notification within the array or task
844 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
846 /* Ensure no notifications within the array of task notifications are
848 for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
850 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, NULL, 0 );
851 configASSERT( xReturned == pdFALSE );
852 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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. */
860 xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
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. */
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++ )
873 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
874 configASSERT( xReturned == pdFALSE );
875 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
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 );
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 );
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++ )
898 xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
899 configASSERT( xReturned == pdFALSE );
901 if( uxOtherIndexes <= uxIndexToTest )
903 configASSERT( ulNotifiedValue == 1 );
907 configASSERT( ulNotifiedValue == 0 );
909 ( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
910 ( void ) ulNotifiedValue;
914 /* Return the task to its proper priority */
915 vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
917 /* Incremented to show the task is still running. */
920 /* Leave all bits cleared. */
921 for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
923 xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, NULL, 0 );
926 /* ------------------------------------------------------------------------ */
928 static void prvBlockOnTheNotifiedIndexed( void )
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;
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++ )
941 xTaskNotifyIndexed( xTaskToNotify, uxIndex, uxIndex + 1, eSetValueWithOverwrite );
942 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
945 /* Peform the test on each task notification within the array of task
947 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
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 );
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 );
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
964 configASSERT( ulReceivedValue == 1UL );
965 ( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
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
970 for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
972 if( uxIndex != uxIndexToNotify )
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. */
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 );
987 /* Incremented to show the task is still running. */
991 /* ------------------------------------------------------------------------ */
993 static void prvBlockOnANonNotifiedIndexed( void )
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;
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++ )
1005 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToNotify, notifyUINT32_MAX );
1008 /* Perform the test for each notification within the array of task
1010 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
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();
1019 if( uxIndexToNotify == ( configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 ) )
1021 /* configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 is to be notified, so
1022 block on index 0. */
1027 /* The next index to get notified will be uxIndexToNotify, so block
1028 on uxIndexToNotify + 1 */
1029 uxIndex = uxIndexToNotify + 1;
1032 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xTimerPeriod + xMargin );
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;
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++ )
1050 xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
1052 if( uxIndex == uxIndexToNotify )
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 );
1059 /* Set the notification value for this array index back to 0. */
1060 ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndex, notifyUINT32_MAX );
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 );
1071 /* Incremented to show the task is still running. */
1075 /* ------------------------------------------------------------------------ */
1077 static void prvBlockOnNotificationsComingFromInterrupts( void )
1079 UBaseType_t uxIndex, uxIndexToNotify;
1080 uint32_t ulReceivedValue;
1081 BaseType_t xReturned;
1082 const TickType_t xDontBlock = 0;
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++ )
1088 xTaskNotifyIndexed( xTaskToNotify, uxIndex, 0, eSetValueWithOverwrite );
1089 xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndex );
1092 /* Perform the test on each task notification within the array of task
1094 for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
1096 /* Tell the interrupt to send the next notification. */
1097 taskENTER_CRITICAL();
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
1102 configASSERT( xSendNotificationFromISR == pdFALSE );
1103 xSendNotificationFromISR = pdTRUE;
1105 taskEXIT_CRITICAL();
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 );
1111 /* Interrupt should have reset xSendNotificationFromISR after it sent
1112 the notificatino. */
1113 configASSERT( xSendNotificationFromISR == pdFALSE );
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. */
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++ )
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. */
1133 /* Incremented to show the task is still running. */
1137 /*-----------------------------------------------------------*/
1139 void xNotifyArrayTaskFromISR( void )
1141 static BaseType_t xAPIToUse = 0;
1142 uint32_t ulPreviousValue;
1143 const uint32_t ulUnexpectedValue = 0xff;
1144 static UBaseType_t uxIndexToNotify = 0;
1146 /* Check the task notification demo task was actually created. */
1147 configASSERT( xTaskToNotify );
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
1152 if( xSendNotificationFromISR == pdTRUE )
1154 xSendNotificationFromISR = pdFALSE;
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
1162 case 0: vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, NULL );
1166 case 1: xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, NULL );
1170 case 2: ulPreviousValue = ulUnexpectedValue;
1171 xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, &ulPreviousValue, NULL );
1172 configASSERT( ulPreviousValue == 0 );
1176 default:/* Should never get here!. */
1180 /* Use the next index in the array of task notifications the next time
1183 if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
1185 uxIndexToNotify = 0;
1189 /*-----------------------------------------------------------*/
1191 /* This is called to check the created tasks are still running and have not
1192 detected any errors. */
1193 BaseType_t xAreTaskNotificationArrayTasksStillRunning( void )
1195 static uint32_t ulLastFineCycleCount = 0, ulLastCourseCycleCount = 0, ulCallCount = 0;
1196 const uint32_t ulCallsBetweenCourseCycleCountChecks = 3UL;
1197 static BaseType_t xErrorStatus = pdPASS;
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 )
1205 xErrorStatus = pdFAIL;
1209 ulLastFineCycleCount = ulFineCycleCount;
1213 if( ulCallCount >= ulCallsBetweenCourseCycleCountChecks )
1216 if( ulLastCourseCycleCount == ulCourseCycleCounter )
1218 xErrorStatus = pdFAIL;
1222 ulLastCourseCycleCount = ulCourseCycleCounter;
1226 return xErrorStatus;
1228 /*-----------------------------------------------------------*/
1230 static UBaseType_t prvRand( void )
1232 const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;
1234 /* Utility function to generate a pseudo random number. */
1235 uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
1236 return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );
1238 /*-----------------------------------------------------------*/