diff --git a/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dbgdt b/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dbgdt
index d3d797e57..4e6cebfa9 100644
--- a/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dbgdt
+++ b/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dbgdt
@@ -34,12 +34,12 @@
20011
- 200- Expression
- Location
- Type
- Value
- 207
- 150
- 100
- 294
200100- Frame
- _I0
- 400
- 20
300- Breakpoint
- _I0
- 500
- 35
49782746331300Debug-LogBuild200- Expression
- Location
- Type
- Value
- 100
- 150
- 100
- 100
- TC0
- TC0->TC_CHANNEL[ tmrTC0_CHANNEL_0 ].TC_RC
30010200100100100100100100100150200100100100100100100
+ 200- Expression
- Location
- Type
- Value
- 207
- 150
- 100
- 294
200100- Frame
- _I0
- 400
- 20
300- Breakpoint
- _I0
- 500
- 35
49782746331300Debug-LogBuild200- Expression
- Location
- Type
- Value
- 100
- 150
- 100
- 100
- TC0
- TC0->TC_CHANNEL[ tmrTC0_CHANNEL_0 ].TC_RC
30010300200100100100100100100100150300300100100100100100100
-
+
TabID-24673-23877
@@ -51,20 +51,20 @@
- 0TabID-22902-32031TasksTASKVIEW0TabID-22379-32041QueuesQUEUEVIEW0
+ 0TabID-31713-7906Debug LogDebug-Log0
- TextEditor$WS_DIR$\main.c0000014072497249TextEditor$WS_DIR$\Full_Demo\main_full.c000006300TextEditor$WS_DIR$\blinky_demo\main_blinky.c000006313731373TextEditor$WS_DIR$\..\..\Source\portable\IAR\ARM_CA5_No_GIC\portASM.s00000733799379930100000010000001
+ TextEditor$WS_DIR$\main.c0000012764116411TextEditor$WS_DIR$\Full_Demo\main_full.c000006300TextEditor$WS_DIR$\blinky_demo\main_blinky.c000006313731373TextEditor$WS_DIR$\..\Common\Minimal\GenQTest.c00000796272382723830100000010000001
- iaridepm.enu1debuggergui.enu1-2-2520332-2-2200200119048203252198810530488-2-21981682-2-216842001002381203252119048203252196-23961682-219616842001002381203252119048203252
+ iaridepm.enu1debuggergui.enu1-2-2718332-2-2200200119048203252198810731707-2-21981682-2-216842001002381203252119048203252
diff --git a/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dni b/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dni
index e66f27a2b..b4bbf9110 100644
--- a/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dni
+++ b/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.dni
@@ -14,7 +14,7 @@ Watch0=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
Watch1=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
CStepIntDis=_ 0
[DebugChecksum]
-Checksum=-666464609
+Checksum=-1280642381
[Exceptions]
StopOnUncaught=_ 0
StopOnThrow=_ 0
@@ -42,7 +42,7 @@ Exclusions=
[Disassemble mode]
mode=0
[Breakpoints2]
-Bp0=_ 1 "EMUL_CODE" "{$PROJ_DIR$\main.c}.218.24" 0 0 1 "" 0 "" 0
+Bp0=_ 1 "EMUL_CODE" "{$PROJ_DIR$\main.c}.221.2" 0 0 1 "" 0 "" 0
Count=1
[Aliases]
Count=0
diff --git a/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.wsdt b/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.wsdt
index a7cc6f063..76656626f 100644
--- a/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.wsdt
+++ b/FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/settings/RTOSDemo.wsdt
@@ -36,7 +36,7 @@
-
+
TabID-22351-19008
@@ -48,7 +48,7 @@
- 0
+ 0
TabID-21076-19237
@@ -58,20 +58,20 @@
TabID-23502-23081Debug LogDebug-LogTabID-24431-23894Ambiguous DefinitionsSelect-Ambiguous-DefinitionsTabID-9033-6116Find in FilesFind-in-Files
- 0
+ 0
- TextEditor$WS_DIR$\main.c0000059724972490TextEditor$WS_DIR$\Full_Demo\main_full.c000006300TextEditor$WS_DIR$\blinky_demo\main_blinky.c0000063137313730100000010000001
+ TextEditor$WS_DIR$\main.c0000063507450740TextEditor$WS_DIR$\Full_Demo\main_full.c000006300TextEditor$WS_DIR$\blinky_demo\main_blinky.c0000063137313730100000010000001
- iaridepm.enu1-2-2668352-2-2190170113095172764210714680894-2-22721682-2-216842741002381278455113095172764
+ iaridepm.enu1-2-2668352-2-2190170113095172764210714680894-2-22721682-2-216842741002381278455113095172764
diff --git a/FreeRTOS/Demo/Common/Minimal/GenQTest.c b/FreeRTOS/Demo/Common/Minimal/GenQTest.c
index 59e176b16..bd5bbba91 100644
--- a/FreeRTOS/Demo/Common/Minimal/GenQTest.c
+++ b/FreeRTOS/Demo/Common/Minimal/GenQTest.c
@@ -93,6 +93,7 @@
#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 )
+#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )
/*-----------------------------------------------------------*/
/*
@@ -121,6 +122,28 @@ static void prvLowPriorityMutexTask( void *pvParameters );
static void prvMediumPriorityMutexTask( void *pvParameters );
static void prvHighPriorityMutexTask( void *pvParameters );
+/*
+ * Exercises the priority inheritance when a task takes two mutexes, returning
+ * them in a different order to which they were taken.
+ */
+static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
+
+/*
+ * Exercises the priority inheritance when a task takes two mutexes, returning
+ * them in the same order in which they were taken.
+ */
+static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
+
+/*
+ * Task that receives an a mutex that is given from an interrupt - although
+ * generally mutexes should not be used given in interrupts (and definitely
+ * never taken in an interrupt) there are some circumstances when it may be
+ * desirable. NOTE: This function is not declared static to prevent compiler
+ * warnings being generated in demos where the function is declared but not
+ * used.
+ */
+void vInterruptMutexTask( void *pvParameters );
+
/*-----------------------------------------------------------*/
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
@@ -139,6 +162,11 @@ static volatile uint32_t ulGuardedVariable = 0;
priority mutex test tasks. */
static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
+/* A mutex which is given from an interrupt - although generally mutexes should
+not be used given in interrupts (and definitely never taken in an interrupt)
+there are some circumstances when it may be desirable. */
+static SemaphoreHandle_t xISRMutex = NULL;
+
/*-----------------------------------------------------------*/
void vStartGenericQueueTasks( UBaseType_t uxPriority )
@@ -146,6 +174,9 @@ void vStartGenericQueueTasks( UBaseType_t uxPriority )
QueueHandle_t xQueue;
SemaphoreHandle_t xMutex;
+ xISRMutex = xSemaphoreCreateMutex();
+ configASSERT( xISRMutex );
+
/* Create the queue that we are going to use for the
prvSendFrontAndBackTest demo. */
xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );
@@ -180,6 +211,14 @@ SemaphoreHandle_t xMutex;
xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
+
+ /* Only when the windows simulator is being used - create the task that
+ receives a mutex from an interrupt. */
+ #ifdef _WINDOWS_
+ {
+ xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL );
+ }
+ #endif /* __WINDOWS__ */
}
/*-----------------------------------------------------------*/
@@ -411,6 +450,252 @@ QueueHandle_t xQueue;
}
/*-----------------------------------------------------------*/
+static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
+{
+ /* Take the mutex. It should be available now. */
+ if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Set the guarded variable to a known start value. */
+ ulGuardedVariable = 0;
+
+ /* This task's priority should be as per that assigned when the task was
+ created. */
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now unsuspend the high priority task. This will attempt to take the
+ mutex, and block when it finds it cannot obtain it. */
+ vTaskResume( xHighPriorityMutexTask );
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* Ensure the task is reporting its priority as blocked and not
+ suspended (as it would have done in versions up to V7.5.3). */
+ #if( INCLUDE_eTaskGetState == 1 )
+ {
+ configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
+ }
+ #endif /* INCLUDE_eTaskGetState */
+
+ /* The priority of the high priority task should now have been inherited
+ as by now it will have attempted to get the mutex. */
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Attempt to set the priority of this task to the test priority -
+ between the idle priority and the medium/high test priorities, but the
+ actual priority should remain at the high priority. */
+ vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now unsuspend the medium priority task. This should not run as the
+ inherited priority of this task is above that of the medium priority
+ task. */
+ vTaskResume( xMediumPriorityMutexTask );
+
+ /* If the medium priority task did run then it will have incremented the
+ guarded variable. */
+ if( ulGuardedVariable != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Take the local mutex too, so two mutexes are now held. */
+ if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When the semaphore is given back the priority of this task should not
+ yet be disinherited because the local mutex is still held. This is a
+ simplification to allow FreeRTOS to be integrated with middleware that
+ attempts to hold multiple mutexes without bloating the code with complex
+ algorithms. It is possible that the high priority mutex task will
+ execute as it shares a priority with this task. */
+ if( xSemaphoreGive( xMutex ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* The guarded variable is only incremented by the medium priority task,
+ which still should not have executed as this task should remain at the
+ higher priority, ensure this is the case. */
+ if( ulGuardedVariable != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now also give back the local mutex, taking the held count back to 0.
+ This time the priority of this task should be disinherited back to the
+ priority to which it was set while the mutex was held. This means
+ the medium priority task should execute and increment the guarded
+ variable. When this task next runs both the high and medium priority
+ tasks will have been suspended again. */
+ if( xSemaphoreGive( xLocalMutex ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* Check the guarded variable did indeed increment... */
+ if( ulGuardedVariable != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* ... and that the priority of this task has been disinherited to
+ genqMUTEX_TEST_PRIORITY. */
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Set the priority of this task back to its original value, ready for
+ the next loop around this test. */
+ vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
+}
+/*-----------------------------------------------------------*/
+
+static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
+{
+ /* Take the mutex. It should be available now. */
+ if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Set the guarded variable to a known start value. */
+ ulGuardedVariable = 0;
+
+ /* This task's priority should be as per that assigned when the task was
+ created. */
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now unsuspend the high priority task. This will attempt to take the
+ mutex, and block when it finds it cannot obtain it. */
+ vTaskResume( xHighPriorityMutexTask );
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* Ensure the task is reporting its priority as blocked and not
+ suspended (as it would have done in versions up to V7.5.3). */
+ #if( INCLUDE_eTaskGetState == 1 )
+ {
+ configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
+ }
+ #endif /* INCLUDE_eTaskGetState */
+
+ /* The priority of the high priority task should now have been inherited
+ as by now it will have attempted to get the mutex. */
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now unsuspend the medium priority task. This should not run as the
+ inherited priority of this task is above that of the medium priority
+ task. */
+ vTaskResume( xMediumPriorityMutexTask );
+
+ /* If the medium priority task did run then it will have incremented the
+ guarded variable. */
+ if( ulGuardedVariable != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Take the local mutex too, so two mutexes are now held. */
+ if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When the local semaphore is given back the priority of this task should
+ not yet be disinherited because the shared mutex is still held. This is a
+ simplification to allow FreeRTOS to be integrated with middleware that
+ attempts to hold multiple mutexes without bloating the code with complex
+ algorithms. It is possible that the high priority mutex task will
+ execute as it shares a priority with this task. */
+ if( xSemaphoreGive( xLocalMutex ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* The guarded variable is only incremented by the medium priority task,
+ which still should not have executed as this task should remain at the
+ higher priority, ensure this is the case. */
+ if( ulGuardedVariable != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now also give back the shared mutex, taking the held count back to 0.
+ This time the priority of this task should be disinherited back to the
+ priority at which it was created. This means the medium priority task
+ should execute and increment the guarded variable. When this task next runs
+ both the high and medium priority tasks will have been suspended again. */
+ if( xSemaphoreGive( xMutex ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* Check the guarded variable did indeed increment... */
+ if( ulGuardedVariable != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* ... and that the priority of this task has been disinherited to
+ genqMUTEX_LOW_PRIORITY. */
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
+ {
+ xErrorDetected = pdTRUE;
+ }
+}
+/*-----------------------------------------------------------*/
+
static void prvLowPriorityMutexTask( void *pvParameters )
{
SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
@@ -430,131 +715,21 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
for( ;; )
{
- /* Take the mutex. It should be available now. */
- if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
- {
- xErrorDetected = pdTRUE;
- }
+ /* The first tests exercise the priority inheritance when two mutexes
+ are taken then returned in a different order to which they were
+ taken. */
+ prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex );
- /* Set the guarded variable to a known start value. */
- ulGuardedVariable = 0;
-
- /* This task's priority should be as per that assigned when the task was
- created. */
- if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* Now unsuspend the high priority task. This will attempt to take the
- mutex, and block when it finds it cannot obtain it. */
- vTaskResume( xHighPriorityMutexTask );
+ /* Just to show this task is still running. */
+ ulLoopCounter2++;
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
- /* Ensure the task is reporting its priority as blocked and not
- suspended (as it would have done in versions up to V7.5.3). */
- #if( INCLUDE_eTaskGetState == 1 )
- {
- configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
- }
- #endif /* INCLUDE_eTaskGetState */
-
- /* The priority of the high priority task should now have been inherited
- as by now it will have attempted to get the mutex. */
- if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* Attempt to set the priority of this task to the test priority -
- between the idle priority and the medium/high test priorities, but the
- actual priority should remain at the high priority. */
- vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
- if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* Now unsuspend the medium priority task. This should not run as the
- inherited priority of this task is above that of the medium priority
- task. */
- vTaskResume( xMediumPriorityMutexTask );
-
- /* If the medium priority task did run then it will have incremented the
- guarded variable. */
- if( ulGuardedVariable != 0 )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* Take the local mutex too, so two mutexes are now held. */
- if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* When the semaphore is given back the priority of this task should not
- yet be disinherited because the local mutex is still held. This is a
- simplification to allow FreeRTOS to be integrated with middleware that
- attempts to hold multiple mutexes without bloating the code with complex
- algorithms. It is possible that the high priority mutex task will
- execute as it shares a priority with this task. */
- if( xSemaphoreGive( xMutex ) != pdPASS )
- {
- xErrorDetected = pdTRUE;
- }
-
- #if configUSE_PREEMPTION == 0
- taskYIELD();
- #endif
-
- /* The guarded variable is only incremented by the medium priority task,
- which still should not have executed as this task should remain at the
- higher priority, ensure this is the case. */
- if( ulGuardedVariable != 0 )
- {
- xErrorDetected = pdTRUE;
- }
-
- if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* Now also give back the local mutex, taking the held count back to 0.
- This time the priority of this task should be disinherited back to the
- priority to which it was set while the mutex was held. This means
- the medium priority task should execute and increment the guarded
- variable. When this task next runs both the high and medium priority
- tasks will have been suspended again. */
- if( xSemaphoreGive( xLocalMutex ) != pdPASS )
- {
- xErrorDetected = pdTRUE;
- }
-
- #if configUSE_PREEMPTION == 0
- taskYIELD();
- #endif
-
- /* Check the guarded variable did indeed increment... */
- if( ulGuardedVariable != 1 )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* ... and that the priority of this task has been disinherited to
- genqMUTEX_TEST_PRIORITY. */
- if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
- {
- xErrorDetected = pdTRUE;
- }
-
- /* Set the priority of this task back to its original value, ready for
- the next loop around this test. */
- vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
+ /* The second tests exercise the priority inheritance when two mutexes
+ are taken then returned in the same order in which they were taken. */
+ prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex );
/* Just to show this task is still running. */
ulLoopCounter2++;
@@ -612,12 +787,53 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
}
/*-----------------------------------------------------------*/
+/* NOTE: This function is not declared static to prevent compiler warnings in
+demos where the function is declared but not used. */
+void vInterruptMutexTask( void *pvParameters )
+{
+const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS );
+volatile uint32_t ulLoops = 0;
+
+ /* Just to avoid compiler warnings. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Has to wait longer than the time between gives to make sure it
+ should definitely have received the mutex. */
+ if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ else
+ {
+ ulLoops++;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vMutexISRInteractionTest( void )
+{
+static TickType_t xLastGiveTime = 0;
+TickType_t xTimeNow;
+
+ xTimeNow = xTaskGetTickCountFromISR();
+ if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )
+ {
+ configASSERT( xISRMutex );
+ xSemaphoreGiveFromISR( xISRMutex, NULL );
+ xLastGiveTime = xTimeNow;
+ }
+}
+/*-----------------------------------------------------------*/
+
/* This is called to check that all the created tasks are still running. */
BaseType_t xAreGenericQueueTasksStillRunning( void )
{
static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
- /* If the demo task is still running then we expect the loopcounters to
+ /* If the demo task is still running then we expect the loop counters to
have incremented since this function was last called. */
if( ulLastLoopCounter == ulLoopCounter )
{
diff --git a/FreeRTOS/Demo/Common/Minimal/TimerDemo.c b/FreeRTOS/Demo/Common/Minimal/TimerDemo.c
index f600ac97f..35afdc1af 100644
--- a/FreeRTOS/Demo/Common/Minimal/TimerDemo.c
+++ b/FreeRTOS/Demo/Common/Minimal/TimerDemo.c
@@ -741,7 +741,12 @@ static TickType_t uxTick = ( TickType_t ) -1;
as well as late timer expiries. */
const TickType_t xMargin = 6;
#else
- const TickType_t xMargin = 3;
+ #ifdef _WINDOWS_
+ /* Windows is not real real time. */
+ const TickType_t xMargin = 8;
+ #else
+ const TickType_t xMargin = 4;
+ #endif /* _WINDOWS_ */
#endif
diff --git a/FreeRTOS/Demo/Common/include/GenQTest.h b/FreeRTOS/Demo/Common/include/GenQTest.h
index 804eaab9f..ef63920d1 100644
--- a/FreeRTOS/Demo/Common/include/GenQTest.h
+++ b/FreeRTOS/Demo/Common/include/GenQTest.h
@@ -1,5 +1,5 @@
/*
- FreeRTOS V8.1.0 - Copyright (C) 2014 Real Time Engineers Ltd.
+ FreeRTOS V8.1.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -68,6 +68,7 @@
void vStartGenericQueueTasks( UBaseType_t uxPriority );
BaseType_t xAreGenericQueueTasksStillRunning( void );
+void vMutexISRInteractionTest( void );
#endif /* GEN_Q_TEST_H */
diff --git a/FreeRTOS/Demo/WIN32-MSVC/main.c b/FreeRTOS/Demo/WIN32-MSVC/main.c
index 917f642dc..948a3f6a5 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/main.c
+++ b/FreeRTOS/Demo/WIN32-MSVC/main.c
@@ -297,7 +297,7 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
( void ) ulLine;
( void ) pcFileName;
- taskENTER_CRITICAL();
+ taskENTER_CRITICAL();
{
/* Stop the trace recording. */
if( xPrinted == pdFALSE )
diff --git a/FreeRTOS/Demo/WIN32-MSVC/main_full.c b/FreeRTOS/Demo/WIN32-MSVC/main_full.c
index 30e93f303..85b6f14e3 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/main_full.c
+++ b/FreeRTOS/Demo/WIN32-MSVC/main_full.c
@@ -162,7 +162,7 @@ static void prvTestTask( void *pvParameters );
static void prvDemonstrateTaskStateAndHandleGetFunctions( void );
/*
- * Called from the idle task hook function to demonstrate the use of
+ * Called from the idle task hook function to demonstrate the use of
* xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by
* any of the standard demo tasks.
*/
@@ -401,6 +401,9 @@ void vFullDemoTickHookFunction( void )
/* Exercise event groups from interrupts. */
vPeriodicEventGroupsProcessing();
+
+ /* Exercise giving mutexes from an interrupt. */
+ vMutexISRInteractionTest();
}
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Source/include/projdefs.h b/FreeRTOS/Source/include/projdefs.h
index f7b9a0e3e..22c810b40 100644
--- a/FreeRTOS/Source/include/projdefs.h
+++ b/FreeRTOS/Source/include/projdefs.h
@@ -73,7 +73,7 @@
typedef void (*TaskFunction_t)( void * );
/* Converts a time in milliseconds to a time in ticks. */
-#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) xTimeInMs * configTICK_RATE_HZ ) / ( TickType_t ) 1000 )
+#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) ( xTimeInMs ) * configTICK_RATE_HZ ) / ( TickType_t ) 1000 )
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h
index bdc60598f..8186a93fa 100644
--- a/FreeRTOS/Source/include/task.h
+++ b/FreeRTOS/Source/include/task.h
@@ -1554,12 +1554,9 @@ eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
/*
* For internal use only. Increment the mutex held count when a mutex is
- * taken and decrement the mutex held count when the mutex is given back
- * respectively. The mutex held count is used to know when it is safe to
- * disinherit a priority.
+ * taken and return the handle of the task that has taken the mutex.
*/
-void vTaskIncrementMutexHeldCount( void );
-void vTaskDecrementMutexHeldCount( void );
+void *pvTaskIncrementMutexHeldCount( void );
#ifdef __cplusplus
}
diff --git a/FreeRTOS/Source/list.c b/FreeRTOS/Source/list.c
index 941dafef2..388143aaf 100644
--- a/FreeRTOS/Source/list.c
+++ b/FreeRTOS/Source/list.c
@@ -144,7 +144,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M3
parts where numerically high priority values denote low actual
- interrupt priories, which can seem counter intuitive. See
+ interrupt priorities, which can seem counter intuitive. See
configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does
diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c
index f9e003759..0e5bc9e3a 100644
--- a/FreeRTOS/Source/queue.c
+++ b/FreeRTOS/Source/queue.c
@@ -421,10 +421,7 @@ QueueHandle_t xReturn = NULL;
traceCREATE_MUTEX( pxNewQueue );
- /* Start with the semaphore in the expected state. Preload the
- mutex held count as calling xQueueGenericSend() will decrement the
- count back to 0. */
- vTaskIncrementMutexHeldCount();
+ /* Start with the semaphore in the expected state. */
( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
}
else
@@ -702,7 +699,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
the mutexes were given back in an order that is
different to that in which they were taken. */
queueYIELD_IF_USING_PREEMPTION();
- }
+ }
else
{
mtCOVERAGE_TEST_MARKER();
@@ -1125,8 +1122,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
- /* The task waiting has a higher priority so record that a
- context switch is required. */
+ /* The task waiting has a higher priority so
+ record that a context switch is required. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
@@ -1243,7 +1240,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
/* Record the information required to implement
priority inheritance should it become necessary. */
- pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
+ pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
}
else
{
@@ -1633,7 +1630,6 @@ BaseType_t xReturn = pdFALSE;
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
/* The mutex is no longer being held. */
- vTaskDecrementMutexHeldCount();
xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
pxQueue->pxMutexHolder = NULL;
}
@@ -1699,7 +1695,7 @@ BaseType_t xReturn = pdFALSE;
static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer )
{
- if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
+ if( pxQueue->uxItemSize != 0 )
{
pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
@@ -1712,11 +1708,6 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
}
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */
}
- else
- {
- /* A mutex was taken. */
- vTaskIncrementMutexHeldCount();
- }
}
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c
index 5300d09a9..28d1c9632 100644
--- a/FreeRTOS/Source/tasks.c
+++ b/FreeRTOS/Source/tasks.c
@@ -553,14 +553,14 @@ TCB_t * pxNewTCB;
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
/* Check the alignment of the calculated top of stack is correct. */
- configASSERT( ( ( ( uint32_t ) pxTopOfStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
}
#else /* portSTACK_GROWTH */
{
pxTopOfStack = pxNewTCB->pxStack;
/* Check the alignment of the stack buffer is correct. */
- configASSERT( ( ( ( uint32_t ) pxNewTCB->pxStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
/* If we want to use stack checking on architectures that use
a positive stack growth direction then we also need to store the
@@ -3246,6 +3246,9 @@ TCB_t *pxTCB;
if( pxMutexHolder != NULL )
{
+ configASSERT( pxTCB->uxMutexesHeld );
+ ( pxTCB->uxMutexesHeld )--;
+
if( pxTCB->uxPriority != pxTCB->uxBasePriority )
{
/* Only disinherit if no other mutexes are held. */
@@ -3584,7 +3587,7 @@ TickType_t uxReturn;
}
/*-----------------------------------------------------------*/
-void vTaskIncrementMutexHeldCount( void )
+void *pvTaskIncrementMutexHeldCount( void )
{
#if ( configUSE_MUTEXES == 1 )
{
@@ -3594,26 +3597,13 @@ void vTaskIncrementMutexHeldCount( void )
{
( pxCurrentTCB->uxMutexesHeld )++;
}
+
+ return pxCurrentTCB;
}
#endif
}
/*-----------------------------------------------------------*/
-void vTaskDecrementMutexHeldCount( void )
-{
- #if ( configUSE_MUTEXES == 1 )
- {
- /* If xSemaphoreCreateMutex() is called before any tasks have been created
- then pxCurrentTCB will be NULL. */
- if( pxCurrentTCB != NULL )
- {
- configASSERT( pxCurrentTCB->uxMutexesHeld );
- ( pxCurrentTCB->uxMutexesHeld )--;
- }
- }
- #endif
-}
-
#ifdef FREERTOS_MODULE_TEST
#include "tasks_test_access_functions.h"
#endif