]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Common/Minimal/TaskNotify.c
Added xTaskAbortDelayFromISR() and ulTaskNotifyValueClear() API functions.
[freertos] / FreeRTOS / Demo / Common / Minimal / TaskNotify.c
index 7bf9c53e5abd36aee1e674b9529a76d67b2094a0..8ee87051fe3a0a88d3500431b0d389331e3b8182 100644 (file)
@@ -1,71 +1,29 @@
 /*\r
-    FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.\r
-    All rights reserved\r
-\r
-    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
-    This file is part of the FreeRTOS distribution.\r
-\r
-    FreeRTOS is free software; you can redistribute it and/or modify it under\r
-    the terms of the GNU General Public License (version 2) as published by the\r
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
-\r
-    ***************************************************************************\r
-    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
-    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
-    >>!   obliged to provide the source code for proprietary components     !<<\r
-    >>!   outside of the FreeRTOS kernel.                                   !<<\r
-    ***************************************************************************\r
-\r
-    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
-    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
-    link: http://www.freertos.org/a00114.html\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    FreeRTOS provides completely free yet professionally developed,    *\r
-     *    robust, strictly quality controlled, supported, and cross          *\r
-     *    platform software that is more than just the market leader, it     *\r
-     *    is the industry's de facto standard.                               *\r
-     *                                                                       *\r
-     *    Help yourself get started quickly while simultaneously helping     *\r
-     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
-     *    tutorial book, reference manual, or both:                          *\r
-     *    http://www.FreeRTOS.org/Documentation                              *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
-    the FAQ page "My application does not run, what could be wrong?".  Have you\r
-    defined configASSERT()?\r
-\r
-    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
-    embedded software for free we request you assist our global community by\r
-    participating in the support forum.\r
-\r
-    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
-    be as productive as possible as early as possible.  Now you can receive\r
-    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
-    Ltd, and the world's leading authority on the world's leading RTOS.\r
-\r
-    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
-    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
-    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
-    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
-    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
-\r
-    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
-    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
-    licenses offer ticketed support, indemnification and commercial middleware.\r
-\r
-    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
-    engineered and independently SIL3 certified version for use in safety and\r
-    mission critical applications that require provable dependability.\r
-\r
-    1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
 \r
 \r
 /*\r
 /* Demo program include files. */\r
 #include "TaskNotify.h"\r
 \r
+/* Allow parameters to be overridden on a demo by demo basis. */\r
+#ifndef notifyNOTIFIED_TASK_STACK_SIZE\r
+       #define notifyNOTIFIED_TASK_STACK_SIZE configMINIMAL_STACK_SIZE\r
+#endif\r
+\r
 #define notifyTASK_PRIORITY            ( tskIDLE_PRIORITY )\r
 \r
+/* Constants used in tests when setting/clearing bits. */\r
+#define notifyUINT32_MAX               ( ( uint32_t ) 0xffffffff )\r
+#define notifyUINT32_HIGH_BYTE ( ( uint32_t ) 0xff000000 )\r
+#define notifyUINT32_LOW_BYTE  ( ( uint32_t ) 0x000000ff )\r
+\r
+#define notifySUSPENDED_TEST_TIMER_PERIOD pdMS_TO_TICKS( 50 )\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -108,6 +78,14 @@ static void prvNotifyingTimer( TimerHandle_t xTimer );
  */\r
 static UBaseType_t prvRand( void );\r
 \r
+/*\r
+ * Callback for a timer that is used during preliminary testing.  The timer\r
+ * tests the behaviour when 1: a task waiting for a notification is suspended\r
+ * and then resumed without ever receiving a notification, and 2: when a task\r
+ * waiting for a notification receives a notification while it is suspended.\r
+ */\r
+static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer );\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /* Used to latch errors during the test's execution. */\r
@@ -128,7 +106,7 @@ static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0
 static TimerHandle_t xTimer = NULL;\r
 \r
 /* Used by the pseudo random number generating function. */\r
-static uint32_t ulNextRand = 0;\r
+static size_t uxNextRand = 0;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -136,10 +114,15 @@ void vStartTaskNotifyTask( void  )
 {\r
        /* Create the task that performs some tests by itself, then loops around\r
        being notified by both a software timer and an interrupt. */\r
-       xTaskCreate( prvNotifiedTask, "Notified", configMINIMAL_STACK_SIZE, NULL, notifyTASK_PRIORITY, &xTaskToNotify );\r
+       xTaskCreate( prvNotifiedTask, /* Function that implements the task. */\r
+                                "Notified", /* Text name for the task - for debugging only - not used by the kernel. */\r
+                                notifyNOTIFIED_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */\r
+                                NULL, /* Task parameter, not used in this case. */\r
+                                notifyTASK_PRIORITY, /* Task priority, 0 is the lowest. */\r
+                                &xTaskToNotify ); /* Used to pass a handle to the task out is needed, otherwise set to NULL. */\r
 \r
        /* Pseudo seed the random number generator. */\r
-       ulNextRand = ( uint32_t ) prvRand;\r
+       uxNextRand = ( size_t ) prvRand;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -151,11 +134,14 @@ uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue, ulPreviousValue, ulExpectedV
 TickType_t xTimeOnEntering;\r
 const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;\r
 const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;\r
+TimerHandle_t xSingleTaskTimer;\r
 \r
-       /* -------------------------------------------------------------------------\r
+\r
+       /* ------------------------------------------------------------------------\r
        Check blocking when there are no notifications. */\r
        xTimeOnEntering = xTaskGetTickCount();\r
-       xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait );\r
+       xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
        /* Should have blocked for the entire block time. */\r
        if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait )\r
@@ -164,11 +150,13 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        }\r
        configASSERT( xReturned == pdFAIL );\r
        configASSERT( ulNotifiedValue == 0UL );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       ( void ) ulNotifiedValue;\r
 \r
 \r
 \r
 \r
-       /* -------------------------------------------------------------------------\r
+       /* ------------------------------------------------------------------------\r
        Check no blocking when notifications are pending.  First notify itself -\r
        this would not be a normal thing to do and is done here for test purposes\r
        only. */\r
@@ -177,13 +165,15 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        /* Even through the 'without overwrite' action was used the update should\r
        have been successful. */\r
        configASSERT( xReturned == pdPASS );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
        /* No bits should have been pending previously. */\r
        configASSERT( ulPreviousValue == 0 );\r
+       ( void ) ulPreviousValue;\r
 \r
        /* The task should now have a notification pending, and so not time out. */\r
        xTimeOnEntering = xTaskGetTickCount();\r
-       xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait );\r
+       xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );\r
 \r
        if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait )\r
        {\r
@@ -194,6 +184,8 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        be equal to ulFirstNotifiedConst. */\r
        configASSERT( xReturned == pdPASS );\r
        configASSERT( ulNotifiedValue == ulFirstNotifiedConst );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       ( void ) ulNotifiedValue;\r
 \r
        /* Incremented to show the task is still running. */\r
        ulNotifyCycleCount++;\r
@@ -202,57 +194,67 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Check the non-overwriting functionality.  The notification is done twice\r
        using two different notification values.  The action says don't overwrite so\r
        only the first notification should pass and the value read back should also\r
        be that used with the first notification. */\r
        xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );\r
        configASSERT( xReturned == pdPASS );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
        xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );\r
        configASSERT( xReturned == pdFAIL );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
        /* Waiting for the notification should now return immediately so a block\r
        time of zero is used. */\r
-       xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );\r
+       xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
 \r
        configASSERT( xReturned == pdPASS );\r
        configASSERT( ulNotifiedValue == ulFirstNotifiedConst );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       ( void ) ulNotifiedValue;\r
 \r
 \r
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Do the same again, only this time use the overwriting version.  This time\r
        both notifications should pass, and the value written the second time should\r
        overwrite the value written the first time, and so be the value that is read\r
        back. */\r
        xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );\r
        configASSERT( xReturned == pdPASS );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
        xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite );\r
        configASSERT( xReturned == pdPASS );\r
-       xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
        configASSERT( xReturned == pdPASS );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
        configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );\r
+       ( void ) ulNotifiedValue;\r
 \r
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Check notifications with no action pass without updating the value.  Even\r
        though ulFirstNotifiedConst is used as the value the value read back should\r
        remain at ulSecondNotifiedConst. */\r
        xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );\r
        configASSERT( xReturned == pdPASS );\r
-       xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
        configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );\r
+       ( void ) ulNotifiedValue; /* In case configASSERT() is not defined. */\r
 \r
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Check incrementing values.  Send ulMaxLoop increment notifications, then\r
        ensure the received value is as expected - which should be\r
        ulSecondNotificationValueConst plus how ever many times to loop iterated. */\r
@@ -260,20 +262,25 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        {\r
                xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );\r
                configASSERT( xReturned == pdPASS );\r
+               ( void ) xReturned; /* In case configASSERT() is not defined. */\r
        }\r
 \r
-       xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );\r
+       xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
        configASSERT( xReturned == pdPASS );\r
        configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       ( void ) ulNotifiedValue;\r
 \r
        /* Should not be any notifications pending now. */\r
        xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );\r
        configASSERT( xReturned == pdFAIL );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       ( void ) ulNotifiedValue;\r
 \r
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Check all bits can be set by notifying the task with one additional bit set\r
        on each notification, and exiting the loop when all the bits are found to be\r
        set.  As there are 32-bits the loop should execute 32 times before all the\r
@@ -282,7 +289,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        ulLoop = 0;\r
 \r
        /* Start with all bits clear. */\r
-       xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );\r
+       xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
 \r
        do\r
        {\r
@@ -294,13 +301,14 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
                when all the bits are set. */\r
                xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );\r
                configASSERT( xReturned == pdPASS );\r
+               ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
                ulLoop++;\r
 \r
                /* Use the next bit on the next iteration around this loop. */\r
                ulNotifyingValue <<= 1UL;\r
 \r
-       } while ( ulNotifiedValue != ULONG_MAX );\r
+       } while ( ulNotifiedValue != notifyUINT32_MAX );\r
 \r
        /* As a 32-bit value was used the loop should have executed 32 times before\r
        all the bits were set. */\r
@@ -309,7 +317,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Check bits are cleared on entry but not on exit when a notification fails\r
        to arrive before timing out - both with and without a timeout value.  Wait\r
        for the notification again - but this time it is not given by anything and\r
@@ -318,23 +326,25 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        entry should actually get cleared. */\r
        xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );\r
        configASSERT( xReturned == pdFAIL );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
        /* Notify the task with no action so as not to update the bits even though\r
-       ULONG_MAX is used as the notification value. */\r
-       xTaskNotify( xTaskToNotify, ULONG_MAX, eNoAction );\r
+       notifyUINT32_MAX is used as the notification value. */\r
+       xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eNoAction );\r
 \r
        /* Reading back the value should should find bit 0 is clear, as this was\r
        cleared on entry, but bit 1 is not clear as it will not have been cleared on\r
        exit as no notification was received. */\r
        xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );\r
        configASSERT( xReturned == pdPASS );\r
-       configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) );\r
+       configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
 \r
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
+       /*-------------------------------------------------------------------------\r
        Now try clearing the bit on exit.  For that to happen a notification must be\r
        received, so the task is notified first. */\r
        xTaskNotify( xTaskToNotify, 0, eNoAction );\r
@@ -343,25 +353,26 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
        /* However as the bit is cleared on exit, after the returned notification\r
        value is set, the returned notification value should not have the bit\r
        cleared... */\r
-       configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) );\r
+       configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );\r
 \r
        /* ...but reading the value back again should find that the bit was indeed\r
        cleared internally.  The returned value should be pdFAIL however as nothing\r
        has notified the task in the mean time. */\r
        xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );\r
        configASSERT( xReturned == pdFAIL );\r
-       configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) );\r
+       configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
 \r
 \r
 \r
 \r
-       /*--------------------------------------------------------------------------\r
-       Now try querying the previus value while notifying a task. */\r
+       /*-------------------------------------------------------------------------\r
+       Now try querying the previous value while notifying a task. */\r
        xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );\r
-       configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) );\r
+       configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );\r
 \r
        /* Clear all bits. */\r
-       xTaskNotifyWait( 0x00, ULONG_MAX, &ulNotifiedValue, 0 );\r
+       xTaskNotifyWait( 0x00, notifyUINT32_MAX, &ulNotifiedValue, 0 );\r
        xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );\r
        configASSERT( ulPreviousValue == 0 );\r
 \r
@@ -376,11 +387,148 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
                ulExpectedValue |= ulLoop;\r
        }\r
 \r
+\r
+\r
+       /* ------------------------------------------------------------------------\r
+       Clear the previous notifications. */\r
+       xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
+\r
+       /* The task should not have any notifications pending, so an attempt to clear\r
+       the notification state should fail. */\r
+       configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );\r
+\r
+       /* Get the task to notify itself.  This is not a normal thing to do, and is\r
+       only done here for test purposes. */\r
+       xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );\r
+\r
+       /* Now the notification state should be eNotified, so it should now be\r
+       possible to clear the notification state. */\r
+       configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );\r
+       configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );\r
+\r
+\r
+\r
+       /* ------------------------------------------------------------------------\r
+       Clear bits in the notification value. */\r
+\r
+       /* Get the task to set all bits its own notification value.  This is not a\r
+       normal thing to do, and is only done here for test purposes. */\r
+       xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eSetBits );\r
+\r
+       /* Now clear the top bytes - the returned value from the first call should\r
+       indicate that previously all bits were set. */\r
+       configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );\r
+\r
+       /* Next clear the bottom bytes - the returned value this time should indicate\r
+       that the top byte was clear (before the bottom byte was cleared. */\r
+       configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );\r
+\r
+       /* Next clear all bytes - the returned value should indicate that previously the\r
+       high and low bytes were clear. */\r
+       configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );\r
+\r
+       /* Now all bits should be clear. */\r
+       configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == 0 );\r
+       configASSERT( ulTaskNotifyValueClear( xTaskToNotify, 0UL ) == 0 );\r
+       configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == 0 );\r
+\r
+       /* Now the notification state should be eNotified, so it should now be\r
+       possible to clear the notification state. */\r
+       configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );\r
+       configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );\r
+\r
+\r
+\r
+       /* ------------------------------------------------------------------------\r
+       Create a timer that will try notifying this task while it is suspended. */\r
+       xSingleTaskTimer = xTimerCreate( "SingleNotify", notifySUSPENDED_TEST_TIMER_PERIOD, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );\r
+       configASSERT( xSingleTaskTimer );\r
+\r
+       /* Incremented to show the task is still running. */\r
+       ulNotifyCycleCount++;\r
+\r
+       /* Ensure no notifications are pending. */\r
+       xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );\r
+\r
+       /* Raise the task's priority so it can suspend itself before the timer\r
+       expires. */\r
+       vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );\r
+\r
+       /* Start the timer that will try notifying this task while it is\r
+       suspended, then wait for a notification.  The first time the callback\r
+       executes the timer will suspend the task, then resume the task, without\r
+       ever sending a notification to the task. */\r
+       ulNotifiedValue = 0;\r
+       xTimerStart( xSingleTaskTimer, portMAX_DELAY );\r
+\r
+       /* Check a notification is not received. */\r
+       xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );\r
+       configASSERT( xReturned == pdFALSE );\r
+       configASSERT( ulNotifiedValue == 0 );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+\r
+       /* Incremented to show the task is still running. */\r
+       ulNotifyCycleCount++;\r
+\r
+       /* Start the timer that will try notifying this task while it is\r
+       suspended, then wait for a notification.  The second time the callback\r
+       executes the timer will suspend the task, notify the task, then resume the\r
+       task (previously it was suspended and resumed without being notified). */\r
+       xTimerStart( xSingleTaskTimer, portMAX_DELAY );\r
+\r
+       /* Check a notification is received. */\r
+       xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, portMAX_DELAY );\r
+       configASSERT( xReturned == pdPASS );\r
+       ( void ) xReturned; /* In case configASSERT() is not defined. */\r
+       configASSERT( ulNotifiedValue != 0 );\r
+\r
+       /* Return the task to its proper priority and delete the timer as it is\r
+       not used again. */\r
+       vTaskPrioritySet( NULL, notifyTASK_PRIORITY );\r
+       xTimerDelete( xSingleTaskTimer, portMAX_DELAY );\r
+\r
        /* Incremented to show the task is still running. */\r
        ulNotifyCycleCount++;\r
 \r
        /* Leave all bits cleared. */\r
-       xTaskNotifyWait( ULONG_MAX, 0, NULL, 0 );\r
+       xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSuspendedTaskTimerTestCallback( TimerHandle_t xExpiredTimer )\r
+{\r
+static uint32_t ulCallCount = 0;\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) xExpiredTimer;\r
+\r
+       /* Callback for a timer that is used during preliminary testing.  The timer\r
+       tests the behaviour when 1: a task waiting for a notification is suspended\r
+       and then resumed without ever receiving a notification, and 2: when a task\r
+       waiting for a notification receives a notification while it is suspended. */\r
+\r
+       if( ulCallCount == 0 )\r
+       {\r
+               vTaskSuspend( xTaskToNotify );\r
+               configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );\r
+               vTaskResume( xTaskToNotify );\r
+       }\r
+       else\r
+       {\r
+               vTaskSuspend( xTaskToNotify );\r
+\r
+               /* Sending a notification while the task is suspended should pass, but\r
+               not cause the task to resume.  ulCallCount is just used as a convenient\r
+               non-zero value. */\r
+               xTaskNotify( xTaskToNotify, ulCallCount, eSetValueWithOverwrite );\r
+\r
+               /* Make sure giving the notification didn't resume the task. */\r
+               configASSERT( eTaskGetState( xTaskToNotify ) == eSuspended );\r
+\r
+               vTaskResume( xTaskToNotify );\r
+       }\r
+\r
+       ulCallCount++;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -403,6 +551,7 @@ static void prvNotifiedTask( void *pvParameters )
 {\r
 const TickType_t xMaxPeriod = pdMS_TO_TICKS( 90 ), xMinPeriod = pdMS_TO_TICKS( 10 ), xDontBlock = 0;\r
 TickType_t xPeriod;\r
+const uint32_t ulCyclesToRaisePriority = 50UL;\r
 \r
        /* Remove compiler warnings about unused parameters. */\r
        ( void ) pvParameters;\r
@@ -418,8 +567,8 @@ TickType_t xPeriod;
        for( ;; )\r
        {\r
                /* Start the timer again with a different period.  Sometimes the period\r
-               will be higher than the tasks block time, sometimes it will be lower\r
-               than the tasks block time. */\r
+               will be higher than the task's block time, sometimes it will be lower\r
+               than the task's block time. */\r
                xPeriod = prvRand() % xMaxPeriod;\r
                if( xPeriod < xMinPeriod )\r
                {\r
@@ -430,8 +579,8 @@ TickType_t xPeriod;
                xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );\r
 \r
                /* Block waiting for the notification again with a different period.\r
-               Sometimes the period will be higher than the tasks block time, sometimes\r
-               it will be lower than the tasks block time. */\r
+               Sometimes the period will be higher than the task's block time,\r
+               sometimes it will be lower than the task's block time. */\r
                xPeriod = prvRand() % xMaxPeriod;\r
                if( xPeriod < xMinPeriod )\r
                {\r
@@ -460,9 +609,28 @@ TickType_t xPeriod;
                the function call. */\r
                ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );\r
 \r
-               /* Wait for the next notification again, clearing all notifications if\r
-               one is received, but this time blocking indefinitely. */\r
-               ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
+               /* Occasionally raise the priority of the task being notified to test\r
+               the path where the task is notified from an ISR and becomes the highest\r
+               priority ready state task, but the pxHigherPriorityTaskWoken parameter\r
+               is NULL (which it is in the tick hook that sends notifications to this\r
+               task). */\r
+               if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )\r
+               {\r
+                       vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );\r
+\r
+                       /* Wait for the next notification again, clearing all notifications\r
+                       if one is received, but this time blocking indefinitely. */\r
+                       ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
+\r
+                       /* Reset the priority. */\r
+                       vTaskPrioritySet( xTaskToNotify, notifyTASK_PRIORITY );\r
+               }\r
+               else\r
+               {\r
+                       /* Wait for the next notification again, clearing all notifications\r
+                       if one is received, but this time blocking indefinitely. */\r
+                       ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
+               }\r
 \r
                /* Incremented to show the task is still running. */\r
                ulNotifyCycleCount++;\r
@@ -472,8 +640,13 @@ TickType_t xPeriod;
 \r
 void xNotifyTaskFromISR( void )\r
 {\r
-static BaseType_t xCallCount = 0;\r
+static BaseType_t xCallCount = 0, xAPIToUse = 0;\r
 const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );\r
+uint32_t ulPreviousValue;\r
+const uint32_t ulUnexpectedValue = 0xff;\r
+\r
+       /* Check the task notification demo tasks were actually created. */\r
+       configASSERT( xTaskToNotify );\r
 \r
        /* The task performs some tests before starting the timer that gives the\r
        notification from this interrupt.  If the timer has not been created yet\r
@@ -488,7 +661,28 @@ const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
                        /* It is time to 'give' the notification again. */\r
                        xCallCount = 0;\r
 \r
-                       vTaskNotifyGiveFromISR( xTaskToNotify, NULL );\r
+                       /* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()\r
+                       and xTaskNotifyAndQueryFromISR(). */\r
+                       switch( xAPIToUse )\r
+                       {\r
+                               case 0: vTaskNotifyGiveFromISR( xTaskToNotify, NULL );\r
+                                               xAPIToUse++;\r
+                                               break;\r
+\r
+                               case 1: xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );\r
+                                               xAPIToUse++;\r
+                                               break;\r
+\r
+                               case 2: ulPreviousValue = ulUnexpectedValue;\r
+                                               xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );\r
+                                               configASSERT( ulPreviousValue != ulUnexpectedValue );\r
+                                               xAPIToUse = 0;\r
+                                               break;\r
+\r
+                               default:/* Should never get here!. */\r
+                                               break;\r
+                       }\r
+\r
                        ulTimerNotificationsSent++;\r
                }\r
        }\r
@@ -529,10 +723,10 @@ const uint32_t ulMaxSendReceiveDeviation = 5UL;
 \r
 static UBaseType_t prvRand( void )\r
 {\r
-const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;\r
+const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;\r
 \r
        /* Utility function to generate a pseudo random number. */\r
-       ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;\r
-       return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );\r
+       uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;\r
+       return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );\r
 }\r
 /*-----------------------------------------------------------*/\r