#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
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
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
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
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
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
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
/* 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
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
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
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
/* 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
\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
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
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
/* 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
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
}\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
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
}\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
}\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
--- /dev/null
+/*\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
#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
--- /dev/null
+/*\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