aboutsummaryrefslogtreecommitdiffstats
path: root/src/FreeRTOS-Sim-master/Demo/Common/Minimal
diff options
context:
space:
mode:
Diffstat (limited to 'src/FreeRTOS-Sim-master/Demo/Common/Minimal')
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/GenQTest.c783
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/QPeek.c478
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/blocktim.c509
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/countsem.c326
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/crflash.c250
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/crhook.c274
-rw-r--r--src/FreeRTOS-Sim-master/Demo/Common/Minimal/recmutex.c444
7 files changed, 3064 insertions, 0 deletions
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/GenQTest.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/GenQTest.c
new file mode 100644
index 0000000..5fabb75
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/GenQTest.c
@@ -0,0 +1,783 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+/*
+ * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 -
+ * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and
+ * mutex behaviour.
+ *
+ * See the comments above the prvSendFrontAndBackTest() and
+ * prvLowPriorityMutexTask() prototypes below for more information.
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "GenQTest.h"
+
+#define genqQUEUE_LENGTH ( 5 )
+#define intsemNO_BLOCK ( 0 )
+
+#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY )
+#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
+#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack()
+ * macros by using both to fill a queue, then reading from the queue to
+ * check the resultant queue order is as expected. Queue data is also
+ * peeked.
+ */
+static void prvSendFrontAndBackTest( void *pvParameters );
+
+/*
+ * The following three tasks are used to demonstrate the mutex behaviour.
+ * Each task is given a different priority to demonstrate the priority
+ * inheritance mechanism.
+ *
+ * The low priority task obtains a mutex. After this a high priority task
+ * attempts to obtain the same mutex, causing its priority to be inherited
+ * by the low priority task. The task with the inherited high priority then
+ * resumes a medium priority task to ensure it is not blocked by the medium
+ * priority task while it holds the inherited high priority. Once the mutex
+ * is returned the task with the inherited priority returns to its original
+ * low priority, and is therefore immediately preempted by first the high
+ * priority task and then the medium prioroity task before it can continue.
+ */
+static void prvLowPriorityMutexTask( void *pvParameters );
+static void prvMediumPriorityMutexTask( void *pvParameters );
+static void prvHighPriorityMutexTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static volatile BaseType_t xErrorDetected = pdFALSE;
+
+/* Counters that are incremented on each cycle of a test. This is used to
+detect a stalled task - a test that is no longer running. */
+static volatile uint32_t ulLoopCounter = 0;
+static volatile uint32_t ulLoopCounter2 = 0;
+
+/* The variable that is guarded by the mutex in the mutex demo tasks. */
+static volatile uint32_t ulGuardedVariable = 0;
+
+/* Handles used in the mutext test to suspend and resume the high and medium
+priority mutex test tasks. */
+static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
+
+/*-----------------------------------------------------------*/
+
+void vStartGenericQueueTasks( UBaseType_t uxPriority )
+{
+QueueHandle_t xQueue;
+SemaphoreHandle_t xMutex;
+
+
+ /* Create the queue that we are going to use for the
+ prvSendFrontAndBackTest demo. */
+ xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );
+
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+ in use. The queue registry is provided as a means for kernel aware
+ debuggers to locate queues and has no purpose if a kernel aware debugger
+ is not being used. The call to vQueueAddToRegistry() will be removed
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+ defined to be less than 1. */
+ vQueueAddToRegistry( xQueue, "Gen_Queue_Test" );
+
+ /* Create the demo task and pass it the queue just created. We are
+ passing the queue handle by value so it does not matter that it is
+ declared on the stack here. */
+ xTaskCreate( prvSendFrontAndBackTest, "GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );
+
+ /* Create the mutex used by the prvMutexTest task. */
+ xMutex = xSemaphoreCreateMutex();
+
+ /* vQueueAddToRegistry() adds the mutex to the registry, if one is
+ in use. The registry is provided as a means for kernel aware
+ debuggers to locate mutexes and has no purpose if a kernel aware debugger
+ is not being used. The call to vQueueAddToRegistry() will be removed
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+ defined to be less than 1. */
+ vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" );
+
+ /* Create the mutex demo tasks and pass it the mutex just created. We are
+ passing the mutex handle by value so it does not matter that it is declared
+ on the stack here. */
+ 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 );
+}
+/*-----------------------------------------------------------*/
+
+static void prvSendFrontAndBackTest( void *pvParameters )
+{
+uint32_t ulData, ulData2;
+QueueHandle_t xQueue;
+
+ #ifdef USE_STDIO
+ void vPrintDisplayMessage( const char * const * ppcMessageToSend );
+
+ const char * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n";
+
+ /* Queue a message for printing to say the task has started. */
+ vPrintDisplayMessage( &pcTaskStartMsg );
+ #endif
+
+ xQueue = ( QueueHandle_t ) pvParameters;
+
+ for( ;; )
+ {
+ /* The queue is empty, so sending an item to the back of the queue
+ should have the same efect as sending it to the front of the queue.
+
+ First send to the front and check everything is as expected. */
+ xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, intsemNO_BLOCK );
+
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xQueueReceive( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* The data we sent to the queue should equal the data we just received
+ from the queue. */
+ if( ulLoopCounter != ulData )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Then do the same, sending the data to the back, checking everything
+ is as expected. */
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, intsemNO_BLOCK );
+
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xQueueReceive( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* The data we sent to the queue should equal the data we just received
+ from the queue. */
+ if( ulLoopCounter != ulData )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+
+
+ /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */
+ for( ulData = 2; ulData < 5; ulData++ )
+ {
+ xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
+ }
+
+ /* Now the order in the queue should be 2, 3, 4, with 2 being the first
+ thing to be read out. Now add 1 then 0 to the front of the queue. */
+ if( uxQueueMessagesWaiting( xQueue ) != 3 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ ulData = 1;
+ xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
+ ulData = 0;
+ xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
+
+ /* Now the queue should be full, and when we read the data out we
+ should receive 0, 1, 2, 3, 4. */
+ if( uxQueueMessagesWaiting( xQueue ) != 5 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* Check the data we read out is in the expected order. */
+ for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )
+ {
+ /* Try peeking the data first. */
+ if( xQueuePeek( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulData != ulData2 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+
+ /* Now try receiving the data for real. The value should be the
+ same. Clobber the value first so we know we really received it. */
+ ulData2 = ~ulData2;
+ if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulData != ulData2 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+
+ /* The queue should now be empty again. */
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+
+ /* Our queue is empty once more, add 10, 11 to the back. */
+ ulData = 10;
+ if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ ulData = 11;
+ if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 2 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the
+ front. */
+ for( ulData = 9; ulData >= 7; ulData-- )
+ {
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+
+ /* Now check that the queue is full, and that receiving data provides
+ the expected sequence of 7, 8, 9, 10, 11. */
+ if( uxQueueMessagesWaiting( xQueue ) != 5 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* Check the data we read out is in the expected order. */
+ for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )
+ {
+ if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulData != ulData2 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ ulLoopCounter++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
+{
+ /* Take the mutex. It should be available now. */
+ if( xSemaphoreTake( xMutex, intsemNO_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, intsemNO_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, intsemNO_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, intsemNO_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;
+
+ #ifdef USE_STDIO
+ void vPrintDisplayMessage( const char * const * ppcMessageToSend );
+
+ const char * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";
+
+ /* Queue a message for printing to say the task has started. */
+ vPrintDisplayMessage( &pcTaskStartMsg );
+ #endif
+
+ /* The local mutex is used to check the 'mutexs held' count. */
+ xLocalMutex = xSemaphoreCreateMutex();
+ configASSERT( xLocalMutex );
+
+ for( ;; )
+ {
+ /* 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 );
+
+ /* Just to show this task is still running. */
+ ulLoopCounter2++;
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* 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++;
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvMediumPriorityMutexTask( void *pvParameters )
+{
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* The medium priority task starts by suspending itself. The low
+ priority task will unsuspend this task when required. */
+ vTaskSuspend( NULL );
+
+ /* When this task unsuspends all it does is increment the guarded
+ variable, this is so the low priority task knows that it has
+ executed. */
+ ulGuardedVariable++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighPriorityMutexTask( void *pvParameters )
+{
+SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
+
+ for( ;; )
+ {
+ /* The high priority task starts by suspending itself. The low
+ priority task will unsuspend this task when required. */
+ vTaskSuspend( NULL );
+
+ /* When this task unsuspends all it does is attempt to obtain
+ the mutex. It should find the mutex is not available so a
+ block time is specified. */
+ if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When the mutex is eventually obtained it is just given back before
+ returning to suspend ready for the next cycle. */
+ if( xSemaphoreGive( xMutex ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+
+/* 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 loop counters to
+ have incremented since this function was last called. */
+ if( ulLastLoopCounter == ulLoopCounter )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulLastLoopCounter2 == ulLoopCounter2 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ ulLastLoopCounter = ulLoopCounter;
+ ulLastLoopCounter2 = ulLoopCounter2;
+
+ /* Errors detected in the task itself will have latched xErrorDetected
+ to true. */
+
+ return ( BaseType_t ) !xErrorDetected;
+}
+
+
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/QPeek.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/QPeek.c
new file mode 100644
index 0000000..5c47517
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/QPeek.c
@@ -0,0 +1,478 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+/*
+ * Tests the behaviour when data is peeked from a queue when there are
+ * multiple tasks blocked on the queue.
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "QPeek.h"
+
+#define qpeekQUEUE_LENGTH ( 5 )
+#define qpeekNO_BLOCK ( 0 )
+#define qpeekSHORT_DELAY ( 10 )
+
+#define qpeekLOW_PRIORITY ( tskIDLE_PRIORITY + 0 )
+#define qpeekMEDIUM_PRIORITY ( tskIDLE_PRIORITY + 1 )
+#define qpeekHIGH_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define qpeekHIGHEST_PRIORITY ( tskIDLE_PRIORITY + 3 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The following three tasks are used to demonstrate the peeking behaviour.
+ * Each task is given a different priority to demonstrate the order in which
+ * tasks are woken as data is peeked from a queue.
+ */
+static void prvLowPriorityPeekTask( void *pvParameters );
+static void prvMediumPriorityPeekTask( void *pvParameters );
+static void prvHighPriorityPeekTask( void *pvParameters );
+static void prvHighestPriorityPeekTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static volatile BaseType_t xErrorDetected = pdFALSE;
+
+/* Counter that is incremented on each cycle of a test. This is used to
+detect a stalled task - a test that is no longer running. */
+static volatile uint32_t ulLoopCounter = 0;
+
+/* Handles to the test tasks. */
+TaskHandle_t xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;
+/*-----------------------------------------------------------*/
+
+void vStartQueuePeekTasks( void )
+{
+QueueHandle_t xQueue;
+
+ /* Create the queue that we are going to use for the test/demo. */
+ xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( uint32_t ) );
+
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+ in use. The queue registry is provided as a means for kernel aware
+ debuggers to locate queues and has no purpose if a kernel aware debugger
+ is not being used. The call to vQueueAddToRegistry() will be removed
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+ defined to be less than 1. */
+ vQueueAddToRegistry( xQueue, "QPeek_Test_Queue" );
+
+ /* Create the demo tasks and pass it the queue just created. We are
+ passing the queue handle by value so it does not matter that it is declared
+ on the stack here. */
+ xTaskCreate( prvLowPriorityPeekTask, "PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
+ xTaskCreate( prvMediumPriorityPeekTask, "PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
+ xTaskCreate( prvHighPriorityPeekTask, "PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
+ xTaskCreate( prvHighestPriorityPeekTask, "PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask );
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighestPriorityPeekTask( void *pvParameters )
+{
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
+uint32_t ulValue;
+
+ #ifdef USE_STDIO
+ {
+ void vPrintDisplayMessage( const char * const * ppcMessageToSend );
+
+ const char * const pcTaskStartMsg = "Queue peek test started.\r\n";
+
+ /* Queue a message for printing to say the task has started. */
+ vPrintDisplayMessage( &pcTaskStartMsg );
+ }
+ #endif
+
+ for( ;; )
+ {
+ /* Try peeking from the queue. The queue should be empty so we will
+ block, allowing the high priority task to execute. */
+ if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+ {
+ /* We expected to have received something by the time we unblock. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When we reach here the high and medium priority tasks should still
+ be blocked on the queue. We unblocked because the low priority task
+ wrote a value to the queue, which we should have peeked. Peeking the
+ data (rather than receiving it) will leave the data on the queue, so
+ the high priority task should then have also been unblocked, but not
+ yet executed. */
+ if( ulValue != 0x11223344 )
+ {
+ /* We did not receive the expected value. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )
+ {
+ /* The message should have been left on the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now we are going to actually receive the data, so when the high
+ priority task runs it will find the queue empty and return to the
+ blocked state. */
+ ulValue = 0;
+ if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+ {
+ /* We expected to receive the value. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulValue != 0x11223344 )
+ {
+ /* We did not receive the expected value - which should have been
+ the same value as was peeked. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Now we will block again as the queue is once more empty. The low
+ priority task can then execute again. */
+ if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+ {
+ /* We expected to have received something by the time we unblock. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When we get here the low priority task should have again written to the
+ queue. */
+ if( ulValue != 0x01234567 )
+ {
+ /* We did not receive the expected value. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )
+ {
+ /* The message should have been left on the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* We only peeked the data, so suspending ourselves now should enable
+ the high priority task to also peek the data. The high priority task
+ will have been unblocked when we peeked the data as we left the data
+ in the queue. */
+ vTaskSuspend( NULL );
+
+
+
+ /* This time we are going to do the same as the above test, but the
+ high priority task is going to receive the data, rather than peek it.
+ This means that the medium priority task should never peek the value. */
+ if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulValue != 0xaabbaabb )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ vTaskSuspend( NULL );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighPriorityPeekTask( void *pvParameters )
+{
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
+uint32_t ulValue;
+
+ for( ;; )
+ {
+ /* Try peeking from the queue. The queue should be empty so we will
+ block, allowing the medium priority task to execute. Both the high
+ and highest priority tasks will then be blocked on the queue. */
+ if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+ {
+ /* We expected to have received something by the time we unblock. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When we get here the highest priority task should have peeked the data
+ (unblocking this task) then suspended (allowing this task to also peek
+ the data). */
+ if( ulValue != 0x01234567 )
+ {
+ /* We did not receive the expected value. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )
+ {
+ /* The message should have been left on the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* We only peeked the data, so suspending ourselves now should enable
+ the medium priority task to also peek the data. The medium priority task
+ will have been unblocked when we peeked the data as we left the data
+ in the queue. */
+ vTaskSuspend( NULL );
+
+
+ /* This time we are going actually receive the value, so the medium
+ priority task will never peek the data - we removed it from the queue. */
+ if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulValue != 0xaabbaabb )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ vTaskSuspend( NULL );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvMediumPriorityPeekTask( void *pvParameters )
+{
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
+uint32_t ulValue;
+
+ for( ;; )
+ {
+ /* Try peeking from the queue. The queue should be empty so we will
+ block, allowing the low priority task to execute. The highest, high
+ and medium priority tasks will then all be blocked on the queue. */
+ if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+ {
+ /* We expected to have received something by the time we unblock. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* When we get here the high priority task should have peeked the data
+ (unblocking this task) then suspended (allowing this task to also peek
+ the data). */
+ if( ulValue != 0x01234567 )
+ {
+ /* We did not receive the expected value. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )
+ {
+ /* The message should have been left on the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Just so we know the test is still running. */
+ ulLoopCounter++;
+
+ /* Now we can suspend ourselves so the low priority task can execute
+ again. */
+ vTaskSuspend( NULL );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvLowPriorityPeekTask( void *pvParameters )
+{
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
+uint32_t ulValue;
+
+ for( ;; )
+ {
+ /* Write some data to the queue. This should unblock the highest
+ priority task that is waiting to peek data from the queue. */
+ ulValue = 0x11223344;
+ if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+ {
+ /* We were expecting the queue to be empty so we should not of
+ had a problem writing to the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* By the time we get here the data should have been removed from
+ the queue. */
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Write another value to the queue, again waking the highest priority
+ task that is blocked on the queue. */
+ ulValue = 0x01234567;
+ if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+ {
+ /* We were expecting the queue to be empty so we should not of
+ had a problem writing to the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* All the other tasks should now have successfully peeked the data.
+ The data is still in the queue so we should be able to receive it. */
+ ulValue = 0;
+ if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+ {
+ /* We expected to receive the data. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( ulValue != 0x01234567 )
+ {
+ /* We did not receive the expected value. */
+ }
+
+ /* Lets just delay a while as this is an intensive test as we don't
+ want to starve other tests of processing time. */
+ vTaskDelay( qpeekSHORT_DELAY );
+
+ /* Unsuspend the other tasks so we can repeat the test - this time
+ however not all the other tasks will peek the data as the high
+ priority task is actually going to remove it from the queue. Send
+ to front is used just to be different. As the queue is empty it
+ makes no difference to the result. */
+ vTaskResume( xMediumPriorityTask );
+ vTaskResume( xHighPriorityTask );
+ vTaskResume( xHighestPriorityTask );
+
+ #if( configUSE_PREEMPTION == 0 )
+ taskYIELD();
+ #endif
+
+ ulValue = 0xaabbaabb;
+ if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+ {
+ /* We were expecting the queue to be empty so we should not of
+ had a problem writing to the queue. */
+ xErrorDetected = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* This time we should find that the queue is empty. The high priority
+ task actually removed the data rather than just peeking it. */
+ if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
+ {
+ /* We expected to receive the data. */
+ xErrorDetected = pdTRUE;
+ }
+
+ /* Unsuspend the highest and high priority tasks so we can go back
+ and repeat the whole thing. The medium priority task should not be
+ suspended as it was not able to peek the data in this last case. */
+ vTaskResume( xHighPriorityTask );
+ vTaskResume( xHighestPriorityTask );
+
+ /* Lets just delay a while as this is an intensive test as we don't
+ want to starve other tests of processing time. */
+ vTaskDelay( qpeekSHORT_DELAY );
+ }
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+BaseType_t xAreQueuePeekTasksStillRunning( void )
+{
+static uint32_t ulLastLoopCounter = 0;
+
+ /* If the demo task is still running then we expect the loopcounter to
+ have incremented since this function was last called. */
+ if( ulLastLoopCounter == ulLoopCounter )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ ulLastLoopCounter = ulLoopCounter;
+
+ /* Errors detected in the task itself will have latched xErrorDetected
+ to true. */
+
+ return ( BaseType_t ) !xErrorDetected;
+}
+
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/blocktim.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/blocktim.c
new file mode 100644
index 0000000..068ea59
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/blocktim.c
@@ -0,0 +1,509 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * This file contains some test scenarios that ensure tasks do not exit queue
+ * send or receive functions prematurely. A description of the tests is
+ * included within the code.
+ */
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Demo includes. */
+#include "blocktim.h"
+
+/* Task priorities. Allow these to be overridden. */
+#ifndef bktPRIMARY_PRIORITY
+ #define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
+#endif
+
+#ifndef bktSECONDARY_PRIORITY
+ #define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 )
+#endif
+
+/* Task behaviour. */
+#define bktQUEUE_LENGTH ( 5 )
+#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS )
+#define bktPRIMARY_BLOCK_TIME ( 10 )
+#define bktALLOWABLE_MARGIN ( 15 )
+#define bktTIME_TO_BLOCK ( 175 )
+#define bktDONT_BLOCK ( ( TickType_t ) 0 )
+#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 )
+
+/* The queue on which the tasks block. */
+static QueueHandle_t xTestQueue;
+
+/* Handle to the secondary task is required by the primary task for calls
+to vTaskSuspend/Resume(). */
+static TaskHandle_t xSecondary;
+
+/* Used to ensure that tasks are still executing without error. */
+static volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;
+static volatile BaseType_t xErrorOccurred = pdFALSE;
+
+/* Provides a simple mechanism for the primary task to know when the
+secondary task has executed. */
+static volatile UBaseType_t xRunIndicator;
+
+/* The two test tasks. Their behaviour is commented within the files. */
+static void vPrimaryBlockTimeTestTask( void *pvParameters );
+static void vSecondaryBlockTimeTestTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+void vCreateBlockTimeTasks( void )
+{
+ /* Create the queue on which the two tasks block. */
+ xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) );
+
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+ in use. The queue registry is provided as a means for kernel aware
+ debuggers to locate queues and has no purpose if a kernel aware debugger
+ is not being used. The call to vQueueAddToRegistry() will be removed
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+ defined to be less than 1. */
+ vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" );
+
+ /* Create the two test tasks. */
+ xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
+ xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
+}
+/*-----------------------------------------------------------*/
+
+static void vPrimaryBlockTimeTestTask( void *pvParameters )
+{
+BaseType_t xItem, xData;
+TickType_t xTimeWhenBlocking;
+TickType_t xTimeToBlock, xBlockedTime;
+
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /*********************************************************************
+ Test 1
+
+ Simple block time wakeup test on queue receives. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* The queue is empty. Attempt to read from the queue using a block
+ time. When we wake, ensure the delta in time is as expected. */
+ xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
+
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after xTimeToBlock having not received
+ anything on the queue. */
+ if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we blocked for? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ if( xBlockedTime < xTimeToBlock )
+ {
+ /* Should not have blocked for less than we requested. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
+ {
+ /* Should not have blocked for longer than we requested,
+ although we would not necessarily run as soon as we were
+ unblocked so a margin is allowed. */
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /*********************************************************************
+ Test 2
+
+ Simple block time wakeup test on queue sends.
+
+ First fill the queue. It should be empty so all sends should pass. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+ }
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* The queue is full. Attempt to write to the queue using a block
+ time. When we wake, ensure the delta in time is as expected. */
+ xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
+
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after xTimeToBlock having not received
+ anything on the queue. */
+ if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we blocked for? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ if( xBlockedTime < xTimeToBlock )
+ {
+ /* Should not have blocked for less than we requested. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
+ {
+ /* Should not have blocked for longer than we requested,
+ although we would not necessarily run as soon as we were
+ unblocked so a margin is allowed. */
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /*********************************************************************
+ Test 3
+
+ Wake the other task, it will block attempting to post to the queue.
+ When we read from the queue the other task will wake, but before it
+ can run we will post to the queue again. When the other task runs it
+ will find the queue still full, even though it was woken. It should
+ recognise that its block time has not expired and return to block for
+ the remains of its block time.
+
+ Wake the other task so it blocks attempting to post to the already
+ full queue. */
+ xRunIndicator = 0;
+ vTaskResume( xSecondary );
+
+ /* We need to wait a little to ensure the other task executes. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ /* The other task has not yet executed. */
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ /* Make sure the other task is blocked on the queue. */
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* Now when we make space on the queue the other task should wake
+ but not execute as this task has higher priority. */
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now fill the queue again before the other task gets a chance to
+ execute. If the other task had executed we would find the queue
+ full ourselves, and the other task have set xRunIndicator. */
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Raise the priority of the other task so it executes and blocks
+ on the queue again. */
+ vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
+
+ /* The other task should now have re-blocked without exiting the
+ queue function. */
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed outside of the
+ queue function. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Set the priority back down. */
+ vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
+ }
+
+ /* Let the other task timeout. When it unblockes it will check that it
+ unblocked at the correct time, then suspend itself. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+
+ /*********************************************************************
+ Test 4
+
+ As per test 3 - but with the send and receive the other way around.
+ The other task blocks attempting to read from the queue.
+
+ Empty the queue. We should find that it is full. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /* Wake the other task so it blocks attempting to read from the
+ already empty queue. */
+ vTaskResume( xSecondary );
+
+ /* We need to wait a little to ensure the other task executes. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* Now when we place an item on the queue the other task should
+ wake but not execute as this task has higher priority. */
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now empty the queue again before the other task gets a chance to
+ execute. If the other task had executed we would find the queue
+ empty ourselves, and the other task would be suspended. */
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Raise the priority of the other task so it executes and blocks
+ on the queue again. */
+ vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
+
+ /* The other task should now have re-blocked without exiting the
+ queue function. */
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed outside of the
+ queue function. */
+ xErrorOccurred = pdTRUE;
+ }
+ vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
+ }
+
+ /* Let the other task timeout. When it unblockes it will check that it
+ unblocked at the correct time, then suspend itself. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ vTaskDelay( bktSHORT_WAIT );
+
+ xPrimaryCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vSecondaryBlockTimeTestTask( void *pvParameters )
+{
+TickType_t xTimeWhenBlocking, xBlockedTime;
+BaseType_t xData;
+
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /*********************************************************************
+ Test 1 and 2
+
+ This task does does not participate in these tests. */
+ vTaskSuspend( NULL );
+
+ /*********************************************************************
+ Test 3
+
+ The first thing we do is attempt to read from the queue. It should be
+ full so we block. Note the time before we block so we can check the
+ wake time is as per that expected. */
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after bktTIME_TO_BLOCK having not sent
+ anything to the queue. */
+ xData = 0;
+ xRunIndicator = bktRUN_INDICATOR;
+ if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we inside the send function? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+ if( xBlockedTime < bktTIME_TO_BLOCK )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+ either. A margin is permitted as we would not necessarily run as
+ soon as we unblocked. */
+ if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Suspend ready for test 3. */
+ xRunIndicator = bktRUN_INDICATOR;
+ vTaskSuspend( NULL );
+
+ /*********************************************************************
+ Test 4
+
+ As per test three, but with the send and receive reversed. */
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after bktTIME_TO_BLOCK having not received
+ anything on the queue. */
+ xRunIndicator = bktRUN_INDICATOR;
+ if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+ if( xBlockedTime < bktTIME_TO_BLOCK )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+ either. A margin is permitted as we would not necessarily run as soon
+ as we unblocked. */
+ if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xRunIndicator = bktRUN_INDICATOR;
+
+ xSecondaryCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xAreBlockTimeTestTasksStillRunning( void )
+{
+static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
+BaseType_t xReturn = pdPASS;
+
+ /* Have both tasks performed at least one cycle since this function was
+ last called? */
+ if( xPrimaryCycles == xLastPrimaryCycleCount )
+ {
+ xReturn = pdFAIL;
+ }
+
+ if( xSecondaryCycles == xLastSecondaryCycleCount )
+ {
+ xReturn = pdFAIL;
+ }
+
+ if( xErrorOccurred == pdTRUE )
+ {
+ xReturn = pdFAIL;
+ }
+
+ xLastSecondaryCycleCount = xSecondaryCycles;
+ xLastPrimaryCycleCount = xPrimaryCycles;
+
+ return xReturn;
+}
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/countsem.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/countsem.c
new file mode 100644
index 0000000..2b45fb0
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/countsem.c
@@ -0,0 +1,326 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+/*
+ * Simple demonstration of the usage of counting semaphore.
+ */
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "countsem.h"
+
+/* The maximum count value that the semaphore used for the demo can hold. */
+#define countMAX_COUNT_VALUE ( 200 )
+
+/* Constants used to indicate whether or not the semaphore should have been
+created with its maximum count value, or its minimum count value. These
+numbers are used to ensure that the pointers passed in as the task parameters
+are valid. */
+#define countSTART_AT_MAX_COUNT ( 0xaa )
+#define countSTART_AT_ZERO ( 0x55 )
+
+/* Two tasks are created for the test. One uses a semaphore created with its
+count value set to the maximum, and one with the count value set to zero. */
+#define countNUM_TEST_TASKS ( 2 )
+#define countDONT_BLOCK ( 0 )
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static volatile BaseType_t xErrorDetected = pdFALSE;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The demo task. This simply counts the semaphore up to its maximum value,
+ * the counts it back down again. The result of each semaphore 'give' and
+ * 'take' is inspected, with an error being flagged if it is found not to be
+ * the expected result.
+ */
+static void prvCountingSemaphoreTask( void *pvParameters );
+
+/*
+ * Utility function to increment the semaphore count value up from zero to
+ * countMAX_COUNT_VALUE.
+ */
+static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter );
+
+/*
+ * Utility function to decrement the semaphore count value up from
+ * countMAX_COUNT_VALUE to zero.
+ */
+static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter );
+
+/*-----------------------------------------------------------*/
+
+/* The structure that is passed into the task as the task parameter. */
+typedef struct COUNT_SEM_STRUCT
+{
+ /* The semaphore to be used for the demo. */
+ SemaphoreHandle_t xSemaphore;
+
+ /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with
+ its count value set to its max count value, or countSTART_AT_ZERO if it
+ should have been created with its count value set to 0. */
+ UBaseType_t uxExpectedStartCount;
+
+ /* Incremented on each cycle of the demo task. Used to detect a stalled
+ task. */
+ UBaseType_t uxLoopCounter;
+} xCountSemStruct;
+
+/* Two structures are defined, one is passed to each test task. */
+static volatile xCountSemStruct xParameters[ countNUM_TEST_TASKS ];
+
+/*-----------------------------------------------------------*/
+
+void vStartCountingSemaphoreTasks( void )
+{
+ /* Create the semaphores that we are going to use for the test/demo. The
+ first should be created such that it starts at its maximum count value,
+ the second should be created such that it starts with a count value of zero. */
+ xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE );
+ xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT;
+ xParameters[ 0 ].uxLoopCounter = 0;
+
+ xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 );
+ xParameters[ 1 ].uxExpectedStartCount = 0;
+ xParameters[ 1 ].uxLoopCounter = 0;
+
+ /* vQueueAddToRegistry() adds the semaphore to the registry, if one is
+ in use. The registry is provided as a means for kernel aware
+ debuggers to locate semaphores and has no purpose if a kernel aware debugger
+ is not being used. The call to vQueueAddToRegistry() will be removed
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+ defined to be less than 1. */
+ vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 0 ].xSemaphore, "Counting_Sem_1" );
+ vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 1 ].xSemaphore, "Counting_Sem_2" );
+
+
+ /* Were the semaphores created? */
+ if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) )
+ {
+ /* Create the demo tasks, passing in the semaphore to use as the parameter. */
+ xTaskCreate( prvCountingSemaphoreTask, "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL );
+ xTaskCreate( prvCountingSemaphoreTask, "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter )
+{
+UBaseType_t ux;
+
+ /* If the semaphore count is at its maximum then we should not be able to
+ 'give' the semaphore. */
+ if( xSemaphoreGive( xSemaphore ) == pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */
+ for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )
+ {
+ if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS )
+ {
+ /* We expected to be able to take the semaphore. */
+ xErrorDetected = pdTRUE;
+ }
+
+ ( *puxLoopCounter )++;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* If the semaphore count is zero then we should not be able to 'take'
+ the semaphore. */
+ if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter )
+{
+UBaseType_t ux;
+
+ /* If the semaphore count is zero then we should not be able to 'take'
+ the semaphore. */
+ if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */
+ for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )
+ {
+ if( xSemaphoreGive( xSemaphore ) != pdPASS )
+ {
+ /* We expected to be able to take the semaphore. */
+ xErrorDetected = pdTRUE;
+ }
+
+ ( *puxLoopCounter )++;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+
+ /* If the semaphore count is at its maximum then we should not be able to
+ 'give' the semaphore. */
+ if( xSemaphoreGive( xSemaphore ) == pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvCountingSemaphoreTask( void *pvParameters )
+{
+xCountSemStruct *pxParameter;
+
+ #ifdef USE_STDIO
+ void vPrintDisplayMessage( const char * const * ppcMessageToSend );
+
+ const char * const pcTaskStartMsg = "Counting semaphore demo started.\r\n";
+
+ /* Queue a message for printing to say the task has started. */
+ vPrintDisplayMessage( &pcTaskStartMsg );
+ #endif
+
+ /* The semaphore to be used was passed as the parameter. */
+ pxParameter = ( xCountSemStruct * ) pvParameters;
+
+ /* Did we expect to find the semaphore already at its max count value, or
+ at zero? */
+ if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT )
+ {
+ prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
+ }
+
+ /* Now we expect the semaphore count to be 0, so this time there is an
+ error if we can take the semaphore. */
+ if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS )
+ {
+ xErrorDetected = pdTRUE;
+ }
+
+ for( ;; )
+ {
+ prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
+ prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
+ }
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xAreCountingSemaphoreTasksStillRunning( void )
+{
+static UBaseType_t uxLastCount0 = 0, uxLastCount1 = 0;
+BaseType_t xReturn = pdPASS;
+
+ /* Return fail if any 'give' or 'take' did not result in the expected
+ behaviour. */
+ if( xErrorDetected != pdFALSE )
+ {
+ xReturn = pdFAIL;
+ }
+
+ /* Return fail if either task is not still incrementing its loop counter. */
+ if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter )
+ {
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ uxLastCount0 = xParameters[ 0 ].uxLoopCounter;
+ }
+
+ if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter )
+ {
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ uxLastCount1 = xParameters[ 1 ].uxLoopCounter;
+ }
+
+ return xReturn;
+}
+
+
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/crflash.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/crflash.c
new file mode 100644
index 0000000..14431ad
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/crflash.c
@@ -0,0 +1,250 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * This demo application file demonstrates the use of queues to pass data
+ * between co-routines.
+ *
+ * N represents the number of 'fixed delay' co-routines that are created and
+ * is set during initialisation.
+ *
+ * N 'fixed delay' co-routines are created that just block for a fixed
+ * period then post the number of an LED onto a queue. Each such co-routine
+ * uses a different block period. A single 'flash' co-routine is also created
+ * that blocks on the same queue, waiting for the number of the next LED it
+ * should flash. Upon receiving a number it simply toggle the instructed LED
+ * then blocks on the queue once more. In this manner each LED from LED 0 to
+ * LED N-1 is caused to flash at a different rate.
+ *
+ * The 'fixed delay' co-routines are created with co-routine priority 0. The
+ * flash co-routine is created with co-routine priority 1. This means that
+ * the queue should never contain more than a single item. This is because
+ * posting to the queue will unblock the 'flash' co-routine, and as this has
+ * a priority greater than the tasks posting to the queue it is guaranteed to
+ * have emptied the queue and blocked once again before the queue can contain
+ * any more date. An error is indicated if an attempt to post data to the
+ * queue fails - indicating that the queue is already full.
+ *
+ */
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "croutine.h"
+#include "queue.h"
+
+/* Demo application includes. */
+#include "partest.h"
+#include "crflash.h"
+
+/* The queue should only need to be of length 1. See the description at the
+top of the file. */
+#define crfQUEUE_LENGTH 1
+
+#define crfFIXED_DELAY_PRIORITY 0
+#define crfFLASH_PRIORITY 1
+
+/* Only one flash co-routine is created so the index is not significant. */
+#define crfFLASH_INDEX 0
+
+/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be
+created. */
+#define crfMAX_FLASH_TASKS 8
+
+/* We don't want to block when posting to the queue. */
+#define crfPOSTING_BLOCK_TIME 0
+
+/*
+ * The 'fixed delay' co-routine as described at the top of the file.
+ */
+static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
+
+/*
+ * The 'flash' co-routine as described at the top of the file.
+ */
+static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
+
+/* The queue used to pass data between the 'fixed delay' co-routines and the
+'flash' co-routine. */
+static QueueHandle_t xFlashQueue;
+
+/* This will be set to pdFALSE if we detect an error. */
+static BaseType_t xCoRoutineFlashStatus = pdPASS;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See the header file for details.
+ */
+void vStartFlashCoRoutines( UBaseType_t uxNumberToCreate )
+{
+UBaseType_t uxIndex;
+
+ if( uxNumberToCreate > crfMAX_FLASH_TASKS )
+ {
+ uxNumberToCreate = crfMAX_FLASH_TASKS;
+ }
+
+ /* Create the queue used to pass data between the co-routines. */
+ xFlashQueue = xQueueCreate( crfQUEUE_LENGTH, sizeof( UBaseType_t ) );
+
+ if( xFlashQueue )
+ {
+ /* Create uxNumberToCreate 'fixed delay' co-routines. */
+ for( uxIndex = 0; uxIndex < uxNumberToCreate; uxIndex++ )
+ {
+ xCoRoutineCreate( prvFixedDelayCoRoutine, crfFIXED_DELAY_PRIORITY, uxIndex );
+ }
+
+ /* Create the 'flash' co-routine. */
+ xCoRoutineCreate( prvFlashCoRoutine, crfFLASH_PRIORITY, crfFLASH_INDEX );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+{
+/* Even though this is a co-routine the xResult variable does not need to be
+static as we do not need it to maintain its state between blocks. */
+BaseType_t xResult;
+/* The uxIndex parameter of the co-routine function is used as an index into
+the xFlashRates array to obtain the delay period to use. */
+static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PERIOD_MS,
+ 200 / portTICK_PERIOD_MS,
+ 250 / portTICK_PERIOD_MS,
+ 300 / portTICK_PERIOD_MS,
+ 350 / portTICK_PERIOD_MS,
+ 400 / portTICK_PERIOD_MS,
+ 450 / portTICK_PERIOD_MS,
+ 500 / portTICK_PERIOD_MS };
+
+ /* Co-routines MUST start with a call to crSTART. */
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ /* Post our uxIndex value onto the queue. This is used as the LED to
+ flash. */
+ crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult );
+
+ if( xResult != pdPASS )
+ {
+ /* For the reasons stated at the top of the file we should always
+ find that we can post to the queue. If we could not then an error
+ has occurred. */
+ xCoRoutineFlashStatus = pdFAIL;
+ }
+
+ crDELAY( xHandle, xFlashRates[ uxIndex ] );
+ }
+
+ /* Co-routines MUST end with a call to crEND. */
+ crEND();
+}
+/*-----------------------------------------------------------*/
+
+static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+{
+/* Even though this is a co-routine the variable do not need to be
+static as we do not need it to maintain their state between blocks. */
+BaseType_t xResult;
+UBaseType_t uxLEDToFlash;
+
+ /* Co-routines MUST start with a call to crSTART. */
+ crSTART( xHandle );
+ ( void ) uxIndex;
+
+ for( ;; )
+ {
+ /* Block to wait for the number of the LED to flash. */
+ crQUEUE_RECEIVE( xHandle, xFlashQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+ if( xResult != pdPASS )
+ {
+ /* We would not expect to wake unless we received something. */
+ xCoRoutineFlashStatus = pdFAIL;
+ }
+ else
+ {
+ /* We received the number of an LED to flash - flash it! */
+ vParTestToggleLED( uxLEDToFlash );
+ }
+ }
+
+ /* Co-routines MUST end with a call to crEND. */
+ crEND();
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xAreFlashCoRoutinesStillRunning( void )
+{
+ /* Return pdPASS or pdFAIL depending on whether an error has been detected
+ or not. */
+ return xCoRoutineFlashStatus;
+}
+
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/crhook.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/crhook.c
new file mode 100644
index 0000000..1f2718f
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/crhook.c
@@ -0,0 +1,274 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * This demo file demonstrates how to send data between an ISR and a
+ * co-routine. A tick hook function is used to periodically pass data between
+ * the RTOS tick and a set of 'hook' co-routines.
+ *
+ * hookNUM_HOOK_CO_ROUTINES co-routines are created. Each co-routine blocks
+ * to wait for a character to be received on a queue from the tick ISR, checks
+ * to ensure the character received was that expected, then sends the number
+ * back to the tick ISR on a different queue.
+ *
+ * The tick ISR checks the numbers received back from the 'hook' co-routines
+ * matches the number previously sent.
+ *
+ * If at any time a queue function returns unexpectedly, or an incorrect value
+ * is received either by the tick hook or a co-routine then an error is
+ * latched.
+ *
+ * This demo relies on each 'hook' co-routine to execute between each
+ * hookTICK_CALLS_BEFORE_POST tick interrupts. This and the heavy use of
+ * queues from within an interrupt may result in an error being detected on
+ * slower targets simply due to timing.
+ */
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "croutine.h"
+#include "queue.h"
+
+/* Demo application includes. */
+#include "crhook.h"
+
+/* The number of 'hook' co-routines that are to be created. */
+#define hookNUM_HOOK_CO_ROUTINES ( 4 )
+
+/* The number of times the tick hook should be called before a character is
+posted to the 'hook' co-routines. */
+#define hookTICK_CALLS_BEFORE_POST ( 500 )
+
+/* There should never be more than one item in any queue at any time. */
+#define hookHOOK_QUEUE_LENGTH ( 1 )
+
+/* Don't block when initially posting to the queue. */
+#define hookNO_BLOCK_TIME ( 0 )
+
+/* The priority relative to other co-routines (rather than tasks) that the
+'hook' co-routines should take. */
+#define mainHOOK_CR_PRIORITY ( 1 )
+/*-----------------------------------------------------------*/
+
+/*
+ * The co-routine function itself.
+ */
+static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
+
+
+/*
+ * The tick hook function. This receives a number from each 'hook' co-routine
+ * then sends a number to each co-routine. An error is flagged if a send or
+ * receive fails, or an unexpected number is received.
+ */
+void vApplicationTickHook( void );
+
+/*-----------------------------------------------------------*/
+
+/* Queues used to send data FROM a co-routine TO the tick hook function.
+The hook functions received (Rx's) on these queues. One queue per
+'hook' co-routine. */
+static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];
+
+/* Queues used to send data FROM the tick hook TO a co-routine function.
+The hood function transmits (Tx's) on these queues. One queue per
+'hook' co-routine. */
+static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];
+
+/* Set to true if an error is detected at any time. */
+static BaseType_t xCoRoutineErrorDetected = pdFALSE;
+
+/*-----------------------------------------------------------*/
+
+void vStartHookCoRoutines( void )
+{
+UBaseType_t uxIndex, uxValueToPost = 0;
+
+ for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )
+ {
+ /* Create a queue to transmit to and receive from each 'hook'
+ co-routine. */
+ xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
+ xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
+
+ /* To start things off the tick hook function expects the queue it
+ uses to receive data to contain a value. */
+ xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );
+
+ /* Create the 'hook' co-routine itself. */
+ xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static UBaseType_t uxCallCounter = 0, uxNumberToPost = 0;
+void vApplicationTickHook( void )
+{
+UBaseType_t uxReceivedNumber;
+BaseType_t xIndex, xCoRoutineWoken;
+
+ /* Is it time to talk to the 'hook' co-routines again? */
+ uxCallCounter++;
+ if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )
+ {
+ uxCallCounter = 0;
+
+ for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )
+ {
+ xCoRoutineWoken = pdFALSE;
+ if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )
+ {
+ /* There is no reason why we would not expect the queue to
+ contain a value. */
+ xCoRoutineErrorDetected = pdTRUE;
+ }
+ else
+ {
+ /* Each queue used to receive data from the 'hook' co-routines
+ should contain the number we last posted to the same co-routine. */
+ if( uxReceivedNumber != uxNumberToPost )
+ {
+ xCoRoutineErrorDetected = pdTRUE;
+ }
+
+ /* Nothing should be blocked waiting to post to the queue. */
+ if( xCoRoutineWoken != pdFALSE )
+ {
+ xCoRoutineErrorDetected = pdTRUE;
+ }
+ }
+ }
+
+ /* Start the next cycle by posting the next number onto each Tx queue. */
+ uxNumberToPost++;
+
+ for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )
+ {
+ if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )
+ {
+ /* Posting to the queue should have woken the co-routine that
+ was blocked on the queue. */
+ xCoRoutineErrorDetected = pdTRUE;
+ }
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+{
+static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];
+BaseType_t xResult;
+
+ /* Each co-routine MUST start with a call to crSTART(); */
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ /* Wait to receive a value from the tick hook. */
+ xResult = pdFAIL;
+ crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );
+
+ /* There is no reason why we should not have received something on
+ the queue. */
+ if( xResult != pdPASS )
+ {
+ xCoRoutineErrorDetected = pdTRUE;
+ }
+
+ /* Send the same number back to the idle hook so it can verify it. */
+ xResult = pdFAIL;
+ crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );
+ if( xResult != pdPASS )
+ {
+ /* There is no reason why we should not have been able to post to
+ the queue. */
+ xCoRoutineErrorDetected = pdTRUE;
+ }
+ }
+
+ /* Each co-routine MUST end with a call to crEND(). */
+ crEND();
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xAreHookCoRoutinesStillRunning( void )
+{
+ if( xCoRoutineErrorDetected )
+ {
+ return pdFALSE;
+ }
+ else
+ {
+ return pdTRUE;
+ }
+}
+
+
+
diff --git a/src/FreeRTOS-Sim-master/Demo/Common/Minimal/recmutex.c b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/recmutex.c
new file mode 100644
index 0000000..f59d360
--- /dev/null
+++ b/src/FreeRTOS-Sim-master/Demo/Common/Minimal/recmutex.c
@@ -0,0 +1,444 @@
+/*
+ FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ The tasks defined on this page demonstrate the use of recursive mutexes.
+
+ For recursive mutex functionality the created mutex should be created using
+ xSemaphoreCreateRecursiveMutex(), then be manipulated
+ using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API
+ functions.
+
+ This demo creates three tasks all of which access the same recursive mutex:
+
+ prvRecursiveMutexControllingTask() has the highest priority so executes
+ first and grabs the mutex. It then performs some recursive accesses -
+ between each of which it sleeps for a short period to let the lower
+ priority tasks execute. When it has completed its demo functionality
+ it gives the mutex back before suspending itself.
+
+ prvRecursiveMutexBlockingTask() attempts to access the mutex by performing
+ a blocking 'take'. The blocking task has a lower priority than the
+ controlling task so by the time it executes the mutex has already been
+ taken by the controlling task, causing the blocking task to block. It
+ does not unblock until the controlling task has given the mutex back,
+ and it does not actually run until the controlling task has suspended
+ itself (due to the relative priorities). When it eventually does obtain
+ the mutex all it does is give the mutex back prior to also suspending
+ itself. At this point both the controlling task and the blocking task are
+ suspended.
+
+ prvRecursiveMutexPollingTask() runs at the idle priority. It spins round
+ a tight loop attempting to obtain the mutex with a non-blocking call. As
+ the lowest priority task it will not successfully obtain the mutex until
+ both the controlling and blocking tasks are suspended. Once it eventually
+ does obtain the mutex it first unsuspends both the controlling task and
+ blocking task prior to giving the mutex back - resulting in the polling
+ task temporarily inheriting the controlling tasks priority.
+*/
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo app include files. */
+#include "recmutex.h"
+
+/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can
+be overridden by a definition in FreeRTOSConfig.h. */
+#ifndef recmuCONTROLLING_TASK_PRIORITY
+ #define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#endif
+#define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
+#define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 )
+
+/* The recursive call depth. */
+#define recmuMAX_COUNT ( 10 )
+
+/* Misc. */
+#define recmuSHORT_DELAY ( 20 / portTICK_PERIOD_MS )
+#define recmuNO_DELAY ( ( TickType_t ) 0 )
+#define recmuEIGHT_TICK_DELAY ( ( TickType_t ) 8 )
+
+/* The three tasks as described at the top of this file. */
+static void prvRecursiveMutexControllingTask( void *pvParameters );
+static void prvRecursiveMutexBlockingTask( void *pvParameters );
+static void prvRecursiveMutexPollingTask( void *pvParameters );
+
+/* The mutex used by the demo. */
+static SemaphoreHandle_t xMutex;
+
+/* Variables used to detect and latch errors. */
+static volatile BaseType_t xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE;
+static volatile UBaseType_t uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0;
+
+/* Handles of the two higher priority tasks, required so they can be resumed
+(unsuspended). */
+static TaskHandle_t xControllingTaskHandle, xBlockingTaskHandle;
+
+/*-----------------------------------------------------------*/
+
+void vStartRecursiveMutexTasks( void )
+{
+ /* Just creates the mutex and the three tasks. */
+
+ xMutex = xSemaphoreCreateRecursiveMutex();
+
+ /* vQueueAddToRegistry() adds the mutex to the registry, if one is
+ in use. The registry is provided as a means for kernel aware
+ debuggers to locate mutex and has no purpose if a kernel aware debugger
+ is not being used. The call to vQueueAddToRegistry() will be removed
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+ defined to be less than 1. */
+ vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Recursive_Mutex" );
+
+
+ if( xMutex != NULL )
+ {
+ xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );
+ xTaskCreate( prvRecursiveMutexBlockingTask, "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle );
+ xTaskCreate( prvRecursiveMutexPollingTask, "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexControllingTask( void *pvParameters )
+{
+UBaseType_t ux;
+
+ /* Just to remove compiler warning. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Should not be able to 'give' the mutex, as we have not yet 'taken'
+ it. The first time through, the mutex will not have been used yet,
+ subsequent times through, at this point the mutex will be held by the
+ polling task. */
+ if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ for( ux = 0; ux < recmuMAX_COUNT; ux++ )
+ {
+ /* We should now be able to take the mutex as many times as
+ we like.
+
+ The first time through the mutex will be immediately available, on
+ subsequent times through the mutex will be held by the polling task
+ at this point and this Take will cause the polling task to inherit
+ the priority of this task. In this case the block time must be
+ long enough to ensure the polling task will execute again before the
+ block time expires. If the block time does expire then the error
+ flag will be set here. */
+ if( xSemaphoreTakeRecursive( xMutex, recmuEIGHT_TICK_DELAY ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Ensure the other task attempting to access the mutex (and the
+ other demo tasks) are able to execute to ensure they either block
+ (where a block time is specified) or return an error (where no
+ block time is specified) as the mutex is held by this task. */
+ vTaskDelay( recmuSHORT_DELAY );
+ }
+
+ /* For each time we took the mutex, give it back. */
+ for( ux = 0; ux < recmuMAX_COUNT; ux++ )
+ {
+ /* Ensure the other task attempting to access the mutex (and the
+ other demo tasks) are able to execute. */
+ vTaskDelay( recmuSHORT_DELAY );
+
+ /* We should now be able to give the mutex as many times as we
+ took it. When the mutex is available again the Blocking task
+ should be unblocked but not run because it has a lower priority
+ than this task. The polling task should also not run at this point
+ as it too has a lower priority than this task. */
+ if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /* Having given it back the same number of times as it was taken, we
+ should no longer be the mutex owner, so the next give should fail. */
+ if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Keep count of the number of cycles this task has performed so a
+ stall can be detected. */
+ uxControllingCycles++;
+
+ /* Suspend ourselves so the blocking task can execute. */
+ xControllingIsSuspended = pdTRUE;
+ vTaskSuspend( NULL );
+ xControllingIsSuspended = pdFALSE;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexBlockingTask( void *pvParameters )
+{
+ /* Just to remove compiler warning. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* This task will run while the controlling task is blocked, and the
+ controlling task will block only once it has the mutex - therefore
+ this call should block until the controlling task has given up the
+ mutex, and not actually execute past this call until the controlling
+ task is suspended. portMAX_DELAY - 1 is used instead of portMAX_DELAY
+ to ensure the task's state is reported as Blocked and not Suspended in
+ a later call to configASSERT() (within the polling task). */
+ if( xSemaphoreTakeRecursive( xMutex, ( portMAX_DELAY - 1 ) ) == pdPASS )
+ {
+ if( xControllingIsSuspended != pdTRUE )
+ {
+ /* Did not expect to execute until the controlling task was
+ suspended. */
+ xErrorOccurred = pdTRUE;
+ }
+ else
+ {
+ /* Give the mutex back before suspending ourselves to allow
+ the polling task to obtain the mutex. */
+ if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xBlockingIsSuspended = pdTRUE;
+ vTaskSuspend( NULL );
+ xBlockingIsSuspended = pdFALSE;
+ }
+ }
+ else
+ {
+ /* We should not leave the xSemaphoreTakeRecursive() function
+ until the mutex was obtained. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* The controlling and blocking tasks should be in lock step. */
+ if( uxControllingCycles != ( uxBlockingCycles + 1 ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Keep count of the number of cycles this task has performed so a
+ stall can be detected. */
+ uxBlockingCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexPollingTask( void *pvParameters )
+{
+ /* Just to remove compiler warning. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Keep attempting to obtain the mutex. We should only obtain it when
+ the blocking task has suspended itself, which in turn should only
+ happen when the controlling task is also suspended. */
+ if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )
+ {
+ #if( INCLUDE_eTaskGetState == 1 )
+ {
+ configASSERT( eTaskGetState( xControllingTaskHandle ) == eSuspended );
+ configASSERT( eTaskGetState( xBlockingTaskHandle ) == eSuspended );
+ }
+ #endif /* INCLUDE_eTaskGetState */
+
+ /* Is the blocking task suspended? */
+ if( ( xBlockingIsSuspended != pdTRUE ) || ( xControllingIsSuspended != pdTRUE ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ else
+ {
+ /* Keep count of the number of cycles this task has performed
+ so a stall can be detected. */
+ uxPollingCycles++;
+
+ /* We can resume the other tasks here even though they have a
+ higher priority than the polling task. When they execute they
+ will attempt to obtain the mutex but fail because the polling
+ task is still the mutex holder. The polling task (this task)
+ will then inherit the higher priority. The Blocking task will
+ block indefinitely when it attempts to obtain the mutex, the
+ Controlling task will only block for a fixed period and an
+ error will be latched if the polling task has not returned the
+ mutex by the time this fixed period has expired. */
+ vTaskResume( xBlockingTaskHandle );
+ vTaskResume( xControllingTaskHandle );
+
+ /* The other two tasks should now have executed and no longer
+ be suspended. */
+ if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ #if( INCLUDE_uxTaskPriorityGet == 1 )
+ {
+ /* Check priority inherited. */
+ configASSERT( uxTaskPriorityGet( NULL ) == recmuCONTROLLING_TASK_PRIORITY );
+ }
+ #endif /* INCLUDE_uxTaskPriorityGet */
+
+ #if( INCLUDE_eTaskGetState == 1 )
+ {
+ configASSERT( eTaskGetState( xControllingTaskHandle ) == eBlocked );
+ configASSERT( eTaskGetState( xBlockingTaskHandle ) == eBlocked );
+ }
+ #endif /* INCLUDE_eTaskGetState */
+
+ /* Release the mutex, disinheriting the higher priority again. */
+ if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ #if( INCLUDE_uxTaskPriorityGet == 1 )
+ {
+ /* Check priority disinherited. */
+ configASSERT( uxTaskPriorityGet( NULL ) == recmuPOLLING_TASK_PRIORITY );
+ }
+ #endif /* INCLUDE_uxTaskPriorityGet */
+ }
+ }
+
+ #if configUSE_PREEMPTION == 0
+ {
+ taskYIELD();
+ }
+ #endif
+ }
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+BaseType_t xAreRecursiveMutexTasksStillRunning( void )
+{
+BaseType_t xReturn;
+static UBaseType_t uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0;
+
+ /* Is the controlling task still cycling? */
+ if( uxLastControllingCycles == uxControllingCycles )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ else
+ {
+ uxLastControllingCycles = uxControllingCycles;
+ }
+
+ /* Is the blocking task still cycling? */
+ if( uxLastBlockingCycles == uxBlockingCycles )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ else
+ {
+ uxLastBlockingCycles = uxBlockingCycles;
+ }
+
+ /* Is the polling task still cycling? */
+ if( uxLastPollingCycles == uxPollingCycles )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ else
+ {
+ uxLastPollingCycles = uxPollingCycles;
+ }
+
+ if( xErrorOccurred == pdTRUE )
+ {
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ xReturn = pdTRUE;
+ }
+
+ return xReturn;
+}
+
+
+
+