]> git.sur5r.net Git - freertos/commitdiff
Demo tasks only, with the aim of improving test coverage:
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 11 Sep 2014 12:06:27 +0000 (12:06 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 11 Sep 2014 12:06:27 +0000 (12:06 +0000)
+ Split out the code that uses a mutex from an interrupt from GenQTest.c and add to new common demo task IntSemTest.c.

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

FreeRTOS/Demo/Common/Minimal/GenQTest.c
FreeRTOS/Demo/Common/Minimal/IntSemTest.c [new file with mode: 0644]
FreeRTOS/Demo/Common/Minimal/TimerDemo.c
FreeRTOS/Demo/Common/include/IntSemTest.h [new file with mode: 0644]

index 2a303652d265455f497203a24e8396650eb90d09..250379db5ea73db746e8c361dc32da17bb54f1a1 100644 (file)
 #include "GenQTest.h"\r
 \r
 #define genqQUEUE_LENGTH               ( 5 )\r
-#define genqNO_BLOCK                   ( 0 )\r
+#define intsemNO_BLOCK                 ( 0 )\r
 \r
 #define genqMUTEX_LOW_PRIORITY         ( tskIDLE_PRIORITY )\r
 #define genqMUTEX_TEST_PRIORITY                ( tskIDLE_PRIORITY + 1 )\r
 #define genqMUTEX_MEDIUM_PRIORITY      ( tskIDLE_PRIORITY + 2 )\r
 #define genqMUTEX_HIGH_PRIORITY                ( tskIDLE_PRIORITY + 3 )\r
 \r
-#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -122,28 +121,6 @@ static void prvLowPriorityMutexTask( void *pvParameters );
 static void prvMediumPriorityMutexTask( void *pvParameters );\r
 static void prvHighPriorityMutexTask( void *pvParameters );\r
 \r
-/*\r
- * Exercises the priority inheritance when a task takes two mutexes, returning\r
- * them in a different order to which they were taken.\r
- */\r
-static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
-\r
-/*\r
- * Exercises the priority inheritance when a task takes two mutexes, returning\r
- * them in the same order in which they were taken.\r
- */\r
-static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
-\r
-/*\r
- * Task that receives an a mutex that is given from an interrupt - although\r
- * generally mutexes should not be used given in interrupts (and definitely\r
- * never taken in an interrupt) there are some circumstances when it may be\r
- * desirable.  NOTE:  This function is not declared static to prevent compiler\r
- * warnings being generated in demos where the function is declared but not\r
- * used.\r
- */\r
-void vInterruptMutexTask( void *pvParameters );\r
-\r
 /*-----------------------------------------------------------*/\r
 \r
 /* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
@@ -162,11 +139,6 @@ static volatile uint32_t ulGuardedVariable = 0;
 priority mutex test tasks. */\r
 static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;\r
 \r
-/* A mutex which is given from an interrupt - although generally mutexes should\r
-not be used given in interrupts (and definitely never taken in an interrupt)\r
-there are some circumstances when it may be desirable. */\r
-static SemaphoreHandle_t xISRMutex = NULL;\r
-\r
 /*-----------------------------------------------------------*/\r
 \r
 void vStartGenericQueueTasks( UBaseType_t uxPriority )\r
@@ -174,8 +146,6 @@ void vStartGenericQueueTasks( UBaseType_t uxPriority )
 QueueHandle_t xQueue;\r
 SemaphoreHandle_t xMutex;\r
 \r
-       xISRMutex = xSemaphoreCreateMutex();\r
-       configASSERT( xISRMutex );\r
 \r
        /* Create the queue that we are going to use for the\r
        prvSendFrontAndBackTest demo. */\r
@@ -211,14 +181,6 @@ SemaphoreHandle_t xMutex;
        xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
        xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
        xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
-\r
-       /* Only when the windows simulator is being used - create the task that\r
-       receives a mutex from an interrupt. */\r
-       #ifdef _WINDOWS_\r
-       {\r
-               xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL );\r
-       }\r
-       #endif /* __WINDOWS__ */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -244,14 +206,14 @@ QueueHandle_t xQueue;
                should have the same efect as sending it to the front of the queue.\r
 \r
                First send to the front and check everything is as expected. */\r
-               xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+               xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, intsemNO_BLOCK );\r
 \r
                if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueReceive( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -270,14 +232,14 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+               xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, intsemNO_BLOCK );\r
 \r
                if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueReceive( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -303,7 +265,7 @@ QueueHandle_t xQueue;
                /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */\r
                for( ulData = 2; ulData < 5; ulData++ )\r
                {\r
-                       xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+                       xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK );\r
                }\r
 \r
                /* Now the order in the queue should be 2, 3, 4, with 2 being the first\r
@@ -313,9 +275,9 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
                ulData = 1;\r
-               xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+               xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );\r
                ulData = 0;\r
-               xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+               xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );\r
 \r
                /* Now the queue should be full, and when we read the data out we\r
                should receive 0, 1, 2, 3, 4. */\r
@@ -324,12 +286,12 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -342,7 +304,7 @@ QueueHandle_t xQueue;
                for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )\r
                {\r
                        /* Try peeking the data first. */\r
-                       if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueuePeek( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -356,7 +318,7 @@ QueueHandle_t xQueue;
                        /* Now try receiving the data for real.  The value should be the\r
                        same.  Clobber the value first so we know we really received it. */\r
                        ulData2 = ~ulData2;\r
-                       if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -380,12 +342,12 @@ QueueHandle_t xQueue;
 \r
                /* Our queue is empty once more, add 10, 11 to the back. */\r
                ulData = 10;\r
-               if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
                ulData = 11;\r
-               if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -399,7 +361,7 @@ QueueHandle_t xQueue;
                front. */\r
                for( ulData = 9; ulData >= 7; ulData-- )\r
                {\r
-                       if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -412,12 +374,12 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -429,7 +391,7 @@ QueueHandle_t xQueue;
                /* Check the data we read out is in the expected order. */\r
                for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )\r
                {\r
-                       if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -453,7 +415,7 @@ QueueHandle_t xQueue;
 static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )\r
 {\r
        /* Take the mutex.  It should be available now. */\r
-       if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -513,7 +475,7 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
        }\r
 \r
        /* Take the local mutex too, so two mutexes are now held. */\r
-       if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xLocalMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -583,7 +545,7 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
 static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )\r
 {\r
        /* Take the mutex.  It should be available now. */\r
-       if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -634,7 +596,7 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
        }\r
 \r
        /* Take the local mutex too, so two mutexes are now held. */\r
-       if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xLocalMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -787,46 +749,6 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/* NOTE: This function is not declared static to prevent compiler warnings in\r
-demos where the function is declared but not used. */\r
-void vInterruptMutexTask( void *pvParameters )\r
-{\r
-const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
-volatile uint32_t ulLoops = 0;\r
-\r
-       /* Just to avoid compiler warnings. */\r
-       ( void ) pvParameters;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Has to wait longer than the time between gives to make sure it\r
-               should definitely have received the mutex. */\r
-               if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-               else\r
-               {\r
-                       ulLoops++;\r
-               }\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-void vMutexISRInteractionTest( void )\r
-{\r
-static TickType_t xLastGiveTime = 0;\r
-TickType_t xTimeNow;\r
-\r
-       xTimeNow = xTaskGetTickCountFromISR();\r
-       if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )\r
-       {\r
-               configASSERT( xISRMutex );\r
-               xSemaphoreGiveFromISR( xISRMutex, NULL );\r
-               xLastGiveTime = xTimeNow;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
 \r
 /* This is called to check that all the created tasks are still running. */\r
 BaseType_t xAreGenericQueueTasksStillRunning( void )\r
diff --git a/FreeRTOS/Demo/Common/Minimal/IntSemTest.c b/FreeRTOS/Demo/Common/Minimal/IntSemTest.c
new file mode 100644 (file)
index 0000000..310047a
--- /dev/null
@@ -0,0 +1,389 @@
+/*\r
+    FreeRTOS V8.1.2 - Copyright (C) 2014 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
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that has become a de facto standard.             *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly and support the FreeRTOS         *\r
+     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
+     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
+     *                                                                       *\r
+     *    Thank you!                                                         *\r
+     *                                                                       *\r
+    ***************************************************************************\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
+    >>!   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
+    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 from the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    1 tab == 4 spaces!\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    Having a problem?  Start by reading the FAQ "My application does   *\r
+     *    not run, what could be wrong?"                                     *\r
+     *                                                                       *\r
+     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
+    license and Real Time Engineers Ltd. contact details.\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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
+    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and 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
+\r
+\r
+/*\r
+ * Demonstrates and tests mutexes being used from an interrupt.\r
+ */\r
+\r
+\r
+#include <stdlib.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* Demo program include files. */\r
+#include "IntSemTest.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The priorities of the test tasks. */\r
+#define intsemMASTER_PRIORITY          ( tskIDLE_PRIORITY )\r
+#define intsemSLAVE_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
+\r
+/* The rate at which the tick hook will give the mutex. */\r
+#define intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )\r
+\r
+/* A block time of 0 means 'don't block'. */\r
+#define intsemNO_BLOCK                         0\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The master is a task that receives a mutex that is given from an interrupt -\r
+ * although generally mutexes should not be used given in interrupts (and\r
+ * definitely never taken in an interrupt) there are some circumstances when it\r
+ * may be desirable.\r
+ *\r
+ * The slave task is just used by the master task to force priority inheritance\r
+ * on a mutex that is shared between the master and the slave - which is a\r
+ * separate mutex to that given by the interrupt.\r
+ */\r
+static void vInterruptMutexSlaveTask( void *pvParameters );\r
+static void vInterruptMutexMasterTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
+detected in any of the tasks. */\r
+static volatile BaseType_t xErrorDetected = pdFALSE;\r
+\r
+/* Counters that are incremented on each cycle of a test.  This is used to\r
+detect a stalled task - a test that is no longer running. */\r
+static volatile uint32_t ulMasterLoops = 0;\r
+\r
+/* Handles of the test tasks that must be accessed from other test tasks. */\r
+static TaskHandle_t xSlaveHandle;\r
+\r
+/* A mutex which is given from an interrupt - although generally mutexes should\r
+not be used given in interrupts (and definitely never taken in an interrupt)\r
+there are some circumstances when it may be desirable. */\r
+static SemaphoreHandle_t xISRMutex = NULL;\r
+\r
+/* A mutex which is shared between the master and slave tasks - the master\r
+does both sharing of this mutex with the slave and receiving a mutex from the\r
+interrupt. */\r
+static SemaphoreHandle_t xMasterSlaveMutex = NULL;\r
+\r
+/* 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;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartInterruptSemaphoreTasks( void )\r
+{\r
+       /* Create the mutex that is given from an interrupt. */\r
+       xISRMutex = xSemaphoreCreateMutex();\r
+       configASSERT( xISRMutex );\r
+\r
+       /* Create the mutex that is shared between the master and slave tasks (the\r
+       master receives a mutex from an interrupt and shares a mutex with the\r
+       slave. */\r
+       xMasterSlaveMutex = xSemaphoreCreateMutex();\r
+       configASSERT( xMasterSlaveMutex );\r
+\r
+       /* Create the tasks that share mutexes between then and with interrupts. */\r
+       xTaskCreate( vInterruptMutexSlaveTask, "IntMuS", configMINIMAL_STACK_SIZE, NULL, intsemSLAVE_PRIORITY, &xSlaveHandle );\r
+       xTaskCreate( vInterruptMutexMasterTask, "IntMuM", configMINIMAL_STACK_SIZE, NULL, intsemMASTER_PRIORITY, NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vInterruptMutexMasterTask( void *pvParameters )\r
+{\r
+const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
+\r
+       /* Just to avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\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
+               {\r
+                       configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );\r
+               }\r
+               #endif /* INCLUDE_eTaskGetState */\r
+\r
+               if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Take the semaphore that is shared with the slave. */\r
+               if( xSemaphoreTake( xMasterSlaveMutex, intsemNO_BLOCK ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This task now has the mutex.  Unsuspend the slave so it too\r
+               attempts to take the mutex. */\r
+               vTaskResume( xSlaveHandle );\r
+\r
+               /* The slave has the higher priority so should now have executed and\r
+               blocked on the semaphore. */\r
+               #if( INCLUDE_eTaskGetState == 1 )\r
+               {\r
+                       configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );\r
+               }\r
+               #endif /* INCLUDE_eTaskGetState */\r
+\r
+               /* This task should now have inherited the priority of the slave\r
+               task. */\r
+               if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Now wait a little longer than the time between ISR gives to also\r
+               obtain the ISR mutex. */\r
+               xOkToGiveMutex = pdTRUE;\r
+               if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+               xOkToGiveMutex = pdFALSE;\r
+\r
+               /* Attempting to take again immediately should fail as the mutex is\r
+               already held. */\r
+               if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Should still be at the priority of the slave task. */\r
+               if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Give back the ISR semaphore to ensure the priority is not\r
+               disinherited as the shared mutex (which the higher priority task is\r
+               attempting to obtain) is still held. */\r
+               if( xSemaphoreGive( xISRMutex ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* 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
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               #if( INCLUDE_eTaskGetState == 1 )\r
+               {\r
+                       configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );\r
+               }\r
+               #endif /* INCLUDE_eTaskGetState */\r
+\r
+               /* Ensure not to starve out other tests. */\r
+               ulMasterLoops++;\r
+               vTaskDelay( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
+\r
+\r
+               /* Repeat exactly up to the point where the mutexes are given back.\r
+               This time the shared mutex is given back first. */\r
+               if( xSemaphoreTake( xMasterSlaveMutex, intsemNO_BLOCK ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               vTaskResume( xSlaveHandle );\r
+\r
+               #if( INCLUDE_eTaskGetState == 1 )\r
+               {\r
+                       configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );\r
+               }\r
+               #endif /* INCLUDE_eTaskGetState */\r
+\r
+               if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               xOkToGiveMutex = pdTRUE;\r
+               if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+               xOkToGiveMutex = pdFALSE;\r
+\r
+               if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This is where the differences start as this time the shared mutex is\r
+               given back first.  This time to the higher priority task should run\r
+               before this task gets to the point of releasing the interrupt mutex - so\r
+               this task should have disinherited the priority and the higher priority\r
+               task should be in the suspended state again. */\r
+               if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Give back the interrupt semaphore too, so the mutex held count goes\r
+               back to 0.  The mutex will then have to be reset so the ISR can give it\r
+               in the next cycle. */\r
+               xSemaphoreGive( xISRMutex );\r
+               xQueueReset( ( QueueHandle_t ) xISRMutex );\r
+\r
+               /* Ensure not to starve out other tests. */\r
+               ulMasterLoops++;\r
+               vTaskDelay( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vInterruptMutexSlaveTask( void *pvParameters )\r
+{\r
+       /* Just to avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               /* This task starts by suspending itself so when it executes can be\r
+               controlled by the master task. */\r
+               vTaskSuspend( NULL );\r
+\r
+               /* This task will execute when the master task already holds the mutex.\r
+               Attempting to take the mutex will place this task in the Blocked\r
+               state. */\r
+               if( xSemaphoreTake( xMasterSlaveMutex, portMAX_DELAY ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vInterruptSemaphorePeriodicTest( void )\r
+{\r
+static TickType_t xLastGiveTime = 0;\r
+TickType_t xTimeNow;\r
+\r
+       /* No mutual exclusion on xOkToGiveMutex, but this is only test code (and\r
+       only executed on a 32-bit architecture) so ignore that in this case. */\r
+       xTimeNow = xTaskGetTickCountFromISR();\r
+       if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )\r
+       {\r
+               configASSERT( xISRMutex );\r
+               if( xOkToGiveMutex != pdFALSE )\r
+               {\r
+                       xSemaphoreGiveFromISR( xISRMutex, NULL );\r
+\r
+                       /* Second give attempt should fail. */\r
+                       configASSERT( xSemaphoreGiveFromISR( xISRMutex, NULL ) == pdFAIL );\r
+               }\r
+               xLastGiveTime = xTimeNow;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+BaseType_t xAreInterruptSemaphoreTasksStillRunning( void )\r
+{\r
+static uint32_t ulLastMasterLoopCounter = 0;\r
+\r
+       /* If the demo tasks are running then it is expected that the loop counters\r
+       will have changed since this function was last called. */\r
+       if( ulLastMasterLoopCounter == ulMasterLoops )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       ulLastMasterLoopCounter = ulMasterLoops;\r
+\r
+       /* Errors detected in the task itself will have latched xErrorDetected\r
+       to true. */\r
+\r
+       return ( BaseType_t ) !xErrorDetected;\r
+}\r
+\r
+\r
index c271225683ecc4f83f3ad7e48c79265cb2b678bd..3f2cef08a17b6930dfedae08799702e200ed32e9 100644 (file)
@@ -743,7 +743,7 @@ static TickType_t uxTick = ( TickType_t ) -1;
 #else\r
        #ifdef _WINDOWS_\r
                /* Windows is not real real time. */\r
-               const TickType_t xMargin = 8;\r
+               const TickType_t xMargin = 10;\r
        #else\r
                const TickType_t xMargin = 4;\r
        #endif /* _WINDOWS_ */\r
diff --git a/FreeRTOS/Demo/Common/include/IntSemTest.h b/FreeRTOS/Demo/Common/include/IntSemTest.h
new file mode 100644 (file)
index 0000000..7a8c002
--- /dev/null
@@ -0,0 +1,76 @@
+/*\r
+    FreeRTOS V8.1.2 - Copyright (C) 2014 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
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that has become a de facto standard.             *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly and support the FreeRTOS         *\r
+     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
+     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
+     *                                                                       *\r
+     *    Thank you!                                                         *\r
+     *                                                                       *\r
+    ***************************************************************************\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
+    >>!   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
+    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 from the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    1 tab == 4 spaces!\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    Having a problem?  Start by reading the FAQ "My application does   *\r
+     *    not run, what could be wrong?"                                     *\r
+     *                                                                       *\r
+     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
+    license and Real Time Engineers Ltd. contact details.\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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
+    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and 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
+\r
+#ifndef INT_SEM_TEST_H\r
+#define INT_SEM_TEST_H\r
+\r
+void vStartInterruptSemaphoreTasks( void );\r
+BaseType_t xAreInterruptSemaphoreTasksStillRunning( void );\r
+void vInterruptSemaphorePeriodicTest( void );\r
+\r
+#endif /* INT_SEM_TEST_H */\r
+\r
+\r
+\r