]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Common/Minimal/TaskNotify.c
Update TaskNotify.c to test the condition where a direct to task notification is...
[freertos] / FreeRTOS / Demo / Common / Minimal / TaskNotify.c
index 1ce7ee5b630053cd976dd6c5666a4cea1d89cd88..a1d1f35dcbe996f8097ddd614523a52fe9855d92 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
     All rights reserved\r
 \r
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
@@ -85,6 +85,8 @@
 \r
 #define notifyTASK_PRIORITY            ( tskIDLE_PRIORITY )\r
 #define notifyUINT32_MAX       ( ( uint32_t ) 0xffffffff )\r
+#define notifySUSPENDED_TEST_TIMER_PERIOD pdMS_TO_TICKS( 50 )\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -108,6 +110,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
@@ -151,8 +161,10 @@ 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( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );\r
@@ -168,7 +180,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
@@ -202,7 +214,7 @@ 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
@@ -224,7 +236,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
@@ -240,7 +252,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
@@ -252,7 +264,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
@@ -273,7 +285,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
@@ -309,7 +321,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
@@ -334,7 +346,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
@@ -355,8 +367,8 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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 == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );\r
 \r
@@ -378,7 +390,7 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \r
 \r
 \r
-       /* -------------------------------------------------------------------------\r
+       /* ------------------------------------------------------------------------\r
        Clear the previous notifications. */\r
        xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );\r
 \r
@@ -397,6 +409,51 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 \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
+\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
+       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
@@ -406,6 +463,43 @@ const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
 }\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
 static void prvNotifyingTimer( TimerHandle_t xNotUsed )\r
 {\r
        ( void ) xNotUsed;\r
@@ -441,8 +535,8 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
        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
@@ -453,8 +547,8 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
                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
@@ -487,13 +581,13 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
                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
+               task). */\r
                if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )\r
                {\r
                        vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );\r
 \r
-                       /* Wait for the next notification again, clearing all notifications if\r
-                       one is received, but this time blocking indefinitely. */\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
@@ -501,8 +595,8 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
                }\r
                else\r
                {\r
-                       /* Wait for the next notification again, clearing all notifications if\r
-                       one is received, but this time blocking indefinitely. */\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