]> git.sur5r.net Git - freertos/commitdiff
Preparing for new release...
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sat, 1 Aug 2015 07:03:32 +0000 (07:03 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sat, 1 Aug 2015 07:03:32 +0000 (07:03 +0000)
Kernel changes:
- Remove an assert that was preventing xQueueSendFromISR() being used to give a mutex from an ISR (mutexes cannot be given using xSemaphoreGiveFromISR()).
- Introduce xTaskNotifyAndQueryFromISR() as the interrupt safe version of xTaskNotifyAndQuery().

Common demo task changes:
- Update IntSemTest.c to prove the theory that it is safe to give a mutex type semaphore from an interrupt using xQueueSendFromISR() instead of xSemaphoreGiveFromISR().
- Update TaskNotify.c to test the new xTaskNotifyAndQuery() from ISR fuction.

git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2361 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Demo/Common/Minimal/IntSemTest.c
FreeRTOS/Demo/Common/Minimal/TaskNotify.c
FreeRTOS/Demo/WIN32-MSVC/main.c
FreeRTOS/Source/include/task.h
FreeRTOS/Source/queue.c
FreeRTOS/Source/tasks.c

index 69a02943cf168349d5ca437153adc5becfee35c2..13ba9bc1420da1463907572ed9fc769be0ce70dc 100644 (file)
@@ -163,7 +163,7 @@ static SemaphoreHandle_t xMasterSlaveMutex = NULL;
 /* Flag that allows the master task to control when the interrupt gives or does\r
 not give the mutex.  There is no mutual exclusion on this variable, but this is\r
 only test code and it should be fine in the 32=bit test environment. */\r
-static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE;\r
+static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE, xOkToGiveMasterSlaveMutex = pdFALSE;\r
 \r
 /* Used to coordinate timing between tasks and the interrupt. */\r
 const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
@@ -217,6 +217,8 @@ static void vInterruptMutexMasterTask( void *pvParameters )
 \r
 static void prvTakeAndGiveInTheSameOrder( void )\r
 {\r
+static BaseType_t xGiveFromTask = pdTRUE;\r
+\r
        /* Ensure the slave is suspended, and that this task is running at the\r
        lower priority as expected as the start conditions. */\r
        #if( INCLUDE_eTaskGetState == 1 )\r
@@ -293,10 +295,27 @@ static void prvTakeAndGiveInTheSameOrder( void )
        /* Finally give back the shared mutex.  This time the higher priority\r
        task should run before this task runs again - so this task should have\r
        disinherited the priority and the higher priority task should be in the\r
-       suspended state again. */\r
-       if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )\r
+       suspended state again.  Alternatve beetween giving the mutex from this task,\r
+       and giving it from the interrupt. */\r
+       if( xGiveFromTask == pdTRUE )\r
        {\r
-               xErrorDetected = pdTRUE;\r
+               if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Give the mutex from the interrupt on the next go around. */\r
+               xGiveFromTask = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               /* Wait for the mutex to be given from the interrupt. */\r
+               xOkToGiveMasterSlaveMutex = pdTRUE;\r
+               vTaskDelay( xInterruptGivePeriod + ( xInterruptGivePeriod >> 1 ) );\r
+               xOkToGiveMasterSlaveMutex = pdFALSE;\r
+\r
+               /* Give the mutex from the task on the next go around. */\r
+               xGiveFromTask = pdTRUE;\r
        }\r
 \r
        if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )\r
@@ -514,15 +533,36 @@ TickType_t xTimeNow;
        xTimeNow = xTaskGetTickCountFromISR();\r
        if( ( ( TickType_t ) ( xTimeNow - xLastGiveTime ) ) >= pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )\r
        {\r
-               configASSERT( xISRMutex );\r
                if( xOkToGiveMutex != pdFALSE )\r
                {\r
+                       configASSERT( xISRMutex );\r
+\r
                        /* Null is used as the second parameter in this give, and non-NULL\r
-                       in the other gives for code coverage reasons. */\r
-                       xSemaphoreGiveFromISR( xISRMutex, NULL );\r
+                       in the other gives, for code coverage reasons.  NOTE:  This is a\r
+                       Mutex, so xQueueGiveFromISR() should be used in place of\r
+                       xSemaphoreGiveFromISR() in case there is a mutex holder that has\r
+                       inherited a priority (although, in the case of xISRMutex, there\r
+                       isn't).  The "item to queue" parameter is set to NULL as no data is \r
+                       copied into a mutex.*/\r
+                       xQueueSendFromISR( ( QueueHandle_t ) xISRMutex, NULL, NULL );\r
+\r
+                       /* Second give attempt should fail. */\r
+                       configASSERT( xQueueSendFromISR( xISRMutex, NULL, &xHigherPriorityTaskWoken ) == pdFAIL );\r
+               }\r
+\r
+               if( xOkToGiveMasterSlaveMutex != pdFALSE )\r
+               {\r
+                       configASSERT( xOkToGiveMasterSlaveMutex );\r
+\r
+                       /* NOTE:  This is a Mutex, so xQueueGiveFromISR() should be used in \r
+                       place of xSemaphoreGiveFromISR() in case there is a mutex holder \r
+                       that has inherited a priority (as indeed there is in this case).  \r
+                       The "item to queue" parameter is set to NULL as no data is copied \r
+                       into a mutex. */\r
+                       xQueueSendFromISR( ( QueueHandle_t ) xMasterSlaveMutex, NULL, NULL );\r
 \r
                        /* Second give attempt should fail. */\r
-                       configASSERT( xSemaphoreGiveFromISR( xISRMutex, &xHigherPriorityTaskWoken ) == pdFAIL );\r
+                       configASSERT( xQueueSendFromISR( xMasterSlaveMutex, NULL, &xHigherPriorityTaskWoken ) == pdFAIL );\r
                }\r
 \r
                if( xOkToGiveCountingSemaphore != pdFALSE )\r
index 7bf9c53e5abd36aee1e674b9529a76d67b2094a0..e74d0599e08b09ea8e07049cc7a4ed2283a9daef 100644 (file)
@@ -472,8 +472,10 @@ 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
        /* 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 +490,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
index 3cd5da9be0422f2a155feed97c90f8d52a39d885..f6cc6df0dd50ed9081597f218aa111ea24ed7dc7 100644 (file)
@@ -302,6 +302,8 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
        ( void ) ulLine;\r
        ( void ) pcFileName;\r
 \r
+       printf( "ASSERT! Line %d, file %s\r\n", ulLine, pcFileName );\r
+\r
        taskENTER_CRITICAL();\r
        {\r
                /* Stop the trace recording. */\r
index 1bae572560ebd8de03f9289a25b7008853e75579..7dd9f87acb03e0701f52a0520c2f44d171e554d9 100644 (file)
@@ -1437,30 +1437,30 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
  * @param eAction Specifies how the notification updates the task's notification\r
  * value, if at all.  Valid values for eAction are as follows:\r
  *\r
- *     eSetBits -\r
- *     The task's notification value is bitwise ORed with ulValue.  xTaskNofify()\r
- *     always returns pdPASS in this case.\r
- *\r
- *     eIncrement -\r
- *     The task's notification value is incremented.  ulValue is not used and\r
- *     xTaskNotify() always returns pdPASS in this case.\r
- *\r
- *     eSetValueWithOverwrite -\r
- *     The task's notification value is set to the value of ulValue, even if the\r
- *     task being notified had not yet processed the previous notification (the\r
- *     task already had a notification pending).  xTaskNotify() always returns\r
- *     pdPASS in this case.\r
- *\r
- *     eSetValueWithoutOverwrite -\r
- *     If the task being notified did not already have a notification pending then\r
- *     the task's notification value is set to ulValue and xTaskNotify() will\r
- *     return pdPASS.  If the task being notified already had a notification\r
- *     pending then no action is performed and pdFAIL is returned.\r
- *\r
- *     eNoAction -\r
- *     The task receives a notification without its notification value being\r
- *     updated.  ulValue is not used and xTaskNotify() always returns pdPASS in\r
- *     this case.\r
+ * eSetBits -\r
+ * The task's notification value is bitwise ORed with ulValue.  xTaskNofify()\r
+ * always returns pdPASS in this case.\r
+ *\r
+ * eIncrement -\r
+ * The task's notification value is incremented.  ulValue is not used and\r
+ * xTaskNotify() always returns pdPASS in this case.\r
+ *\r
+ * eSetValueWithOverwrite -\r
+ * The task's notification value is set to the value of ulValue, even if the\r
+ * task being notified had not yet processed the previous notification (the\r
+ * task already had a notification pending).  xTaskNotify() always returns\r
+ * pdPASS in this case.\r
+ *\r
+ * eSetValueWithoutOverwrite -\r
+ * If the task being notified did not already have a notification pending then\r
+ * the task's notification value is set to ulValue and xTaskNotify() will\r
+ * return pdPASS.  If the task being notified already had a notification\r
+ * pending then no action is performed and pdFAIL is returned.\r
+ *\r
+ * eNoAction -\r
+ * The task receives a notification without its notification value being\r
+ * updated.  ulValue is not used and xTaskNotify() always returns pdPASS in\r
+ * this case.\r
  *\r
  *  pulPreviousNotificationValue -\r
  *  Can be used to pass out the subject task's notification value before any\r
@@ -1523,30 +1523,30 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
  * @param eAction Specifies how the notification updates the task's notification\r
  * value, if at all.  Valid values for eAction are as follows:\r
  *\r
- *     eSetBits -\r
- *     The task's notification value is bitwise ORed with ulValue.  xTaskNofify()\r
- *     always returns pdPASS in this case.\r
+ * eSetBits -\r
+ * The task's notification value is bitwise ORed with ulValue.  xTaskNofify()\r
+ * always returns pdPASS in this case.\r
  *\r
- *     eIncrement -\r
- *     The task's notification value is incremented.  ulValue is not used and\r
- *     xTaskNotify() always returns pdPASS in this case.\r
+ * eIncrement -\r
+ * The task's notification value is incremented.  ulValue is not used and\r
+ * xTaskNotify() always returns pdPASS in this case.\r
  *\r
- *     eSetValueWithOverwrite -\r
- *     The task's notification value is set to the value of ulValue, even if the\r
- *     task being notified had not yet processed the previous notification (the\r
- *     task already had a notification pending).  xTaskNotify() always returns\r
- *     pdPASS in this case.\r
+ * eSetValueWithOverwrite -\r
+ * The task's notification value is set to the value of ulValue, even if the\r
+ * task being notified had not yet processed the previous notification (the\r
+ * task already had a notification pending).  xTaskNotify() always returns\r
+ * pdPASS in this case.\r
  *\r
- *     eSetValueWithoutOverwrite -\r
- *     If the task being notified did not already have a notification pending then\r
- *     the task's notification value is set to ulValue and xTaskNotify() will\r
- *     return pdPASS.  If the task being notified already had a notification\r
- *     pending then no action is performed and pdFAIL is returned.\r
+ * eSetValueWithoutOverwrite -\r
+ * If the task being notified did not already have a notification pending then\r
+ * the task's notification value is set to ulValue and xTaskNotify() will\r
+ * return pdPASS.  If the task being notified already had a notification\r
+ * pending then no action is performed and pdFAIL is returned.\r
  *\r
- *     eNoAction -\r
- *     The task receives a notification without its notification value being\r
- *     updated.  ulValue is not used and xTaskNotify() always returns pdPASS in\r
- *     this case.\r
+ * eNoAction -\r
+ * The task receives a notification without its notification value being\r
+ * updated.  ulValue is not used and xTaskNotify() always returns pdPASS in\r
+ * this case.\r
  *\r
  * @param pxHigherPriorityTaskWoken  xTaskNotifyFromISR() will set\r
  * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the\r
@@ -1563,7 +1563,9 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
  * \defgroup xTaskNotify xTaskNotify\r
  * \ingroup TaskNotifications\r
  */\r
-BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;\r
+BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;\r
+#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )\r
+#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )\r
 \r
 /**\r
  * task. h\r
index c35e00626b52cbb76613b93352257f8ee3c750a4..0a196a1ef2a950e2e74c1c4a85b8e5d41bdd627d 100644 (file)
@@ -1219,9 +1219,11 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
        if the item size is not 0. */\r
        configASSERT( pxQueue->uxItemSize == 0 );\r
 \r
-       /* Normally a mutex would not be given from an interrupt, and doing so is\r
-       definitely wrong if there is a mutex holder as priority inheritance makes no\r
-       sense for an interrupts, only tasks. */\r
+       /* Normally a mutex would not be given from an interrupt, especially if \r
+       there is a mutex holder, as priority inheritance makes no sense for an \r
+       interrupts, only tasks.  However, on occasions when it is wanted to give\r
+       a mutex from an interrupt, use xQueueSendFromISR() in place of\r
+       xSemaphoreGiveFromISR(). */\r
        configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) );\r
 \r
        /* RTOS ports that support interrupt nesting have the concept of a maximum\r
index d3ec721c88ce7f6a2db32231270581e2992c58bc..49c8a4aaf848148ff63ef42630e2ad6c31d103a0 100644 (file)
@@ -3489,12 +3489,6 @@ TCB_t *pxTCB;
 \r
                if( pxMutexHolder != NULL )\r
                {\r
-                       /* A task can only have an inherited priority if it holds the mutex.\r
-                       If the mutex is held by a task then it cannot be given from an\r
-                       interrupt, and if a mutex is given by the holding task then it must\r
-                       be the running state task. */\r
-                       configASSERT( pxTCB == pxCurrentTCB );\r
-\r
                        configASSERT( pxTCB->uxMutexesHeld );\r
                        ( pxTCB->uxMutexesHeld )--;\r
 \r
@@ -4236,7 +4230,7 @@ TickType_t uxReturn;
 \r
 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
 \r
-       BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )\r
+       BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )\r
        {\r
        TCB_t * pxTCB;\r
        eNotifyValue eOriginalNotifyState;\r
@@ -4267,8 +4261,12 @@ TickType_t uxReturn;
 \r
                uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
                {\r
-                       eOriginalNotifyState = pxTCB->eNotifyState;\r
+                       if( pulPreviousNotificationValue != NULL )\r
+                       {\r
+                               *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;\r
+                       }\r
 \r
+                       eOriginalNotifyState = pxTCB->eNotifyState;\r
                        pxTCB->eNotifyState = eNotified;\r
 \r
                        switch( eAction )\r