]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/WIN32-MSVC/main.c
Add xQueueOverwriteFromISR() and update the QueueOverwrite.c to demonstrate its use.
[freertos] / FreeRTOS / Demo / WIN32-MSVC / main.c
index e0099ea5fc335e46d71989ccfaedaa3fe95f92b8..b57938c7ba3f6781ab628790d569556fe62f23b9 100644 (file)
  * application.  It is provided as a convenient development and demonstration\r
  * test bed only.  This was tested using Windows XP on a dual core laptop.\r
  *\r
+ * In this example, one simulated millisecond will take approximately 40ms to\r
+ * execute, and Windows will not be running the FreeRTOS simulator threads\r
+ * continuously, so the timing information in the FreeRTOS+Trace logs have no\r
+ * meaningful units.  See the documentation page for the Windows simulator for\r
+ * an explanation of the slow timing:\r
+ * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html\r
  * - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -\r
  *******************************************************************************\r
  *\r
 /* Standard includes. */\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
+#include <conio.h>\r
 \r
 /* Kernel includes. */\r
 #include <FreeRTOS.h>\r
 #include "death.h"\r
 #include "dynamic.h"\r
 #include "QueueSet.h"\r
+#include "QueueOverwrite.h"\r
 \r
 /* Priorities at which the tasks are created. */\r
 #define mainCHECK_TASK_PRIORITY                        ( configMAX_PRIORITIES - 1 )\r
 #define mainINTEGER_TASK_PRIORITY              ( tskIDLE_PRIORITY )\r
 #define mainGEN_QUEUE_TASK_PRIORITY            ( tskIDLE_PRIORITY )\r
 #define mainFLOP_TASK_PRIORITY                 ( tskIDLE_PRIORITY )\r
+#define mainQUEUE_OVERWRITE_PRIORITY   ( tskIDLE_PRIORITY )\r
 \r
 #define mainTIMER_TEST_PERIOD                  ( 50 )\r
 \r
@@ -147,6 +156,20 @@ static void prvCheckTask( void *pvParameters );
 eTaskStateGet(). */\r
 static void prvTestTask( void *pvParameters );\r
 \r
+/*\r
+ * Writes trace data to a disk file when the trace recording is stopped.\r
+ * This function will simply overwrite any trace files that already exist.\r
+ */\r
+static void prvSaveTraceFile( void );\r
+\r
+/*\r
+ * Called from the idle task hook function to demonstrate a few utility\r
+ * functions that are not demonstrated by any of the standard demo tasks.\r
+ */\r
+static void prvDemonstrateTaskStateAndHandleGetFunctions( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
 /* The variable into which error messages are latched. */\r
 static char *pcStatusMessage = "OK";\r
 \r
@@ -154,10 +177,21 @@ static char *pcStatusMessage = "OK";
 semaphore tracing API functions.  It has no other purpose. */\r
 static xSemaphoreHandle xMutexToDelete = NULL;\r
 \r
+/* The user trace event posted to the trace recording on each tick interrupt.\r
+Note tick events will not appear in the trace recording with regular period\r
+because this project runs in a Windows simulator, and does not therefore\r
+exhibit deterministic behaviour. */\r
+traceLabel xTickTraceUserEvent;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 int main( void )\r
 {\r
+       /* Initialise the trace recorder and create the label used to post user\r
+       events to the trace recording on each tick interrupt. */\r
+       vTraceInitTraceData();\r
+       xTickTraceUserEvent = xTraceOpenLabel( "tick" );\r
+\r
        /* Start the check task as described at the top of this file. */\r
        xTaskCreate( prvCheckTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
 \r
@@ -174,6 +208,7 @@ int main( void )
        vStartCountingSemaphoreTasks();\r
        vStartDynamicPriorityTasks();\r
        vStartQueueSetTasks();\r
+       vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );\r
 \r
        /* The suicide tasks must be created last as they need to know how many\r
        tasks were running prior to their creation.  This then allows them to \r
@@ -187,7 +222,8 @@ int main( void )
 \r
        /* Start the trace recording - the recording is written to a file if\r
        configASSERT() is called. */\r
-       vTraceStart();\r
+       printf( "\r\nTrace started.  Hit a key to dump trace file to disk.\r\n" );\r
+       uiTraceStart();\r
 \r
        /* Start the scheduler itself. */\r
        vTaskStartScheduler();\r
@@ -267,6 +303,10 @@ const portTickType xCycleFrequency = 1000 / portTICK_RATE_MS;
                {\r
                        pcStatusMessage = "Error: Queue set\r\n";\r
                }\r
+               else if( xIsQueueOverwriteTaskStillRunning() != pdPASS )\r
+               {\r
+                       pcStatusMessage = "Error: Queue overwrite\r\n";\r
+               }\r
 \r
                /* This is the only task that uses stdout so its ok to call printf() \r
                directly. */\r
@@ -296,10 +336,9 @@ const unsigned long ulMSToSleep = 5;
 void vApplicationIdleHook( void )\r
 {\r
 const unsigned long ulMSToSleep = 15;\r
-xTaskHandle xIdleTaskHandle, xTimerTaskHandle, xTestTask;\r
-signed char *pcTaskName;\r
-const unsigned char ucConstQueueNumber = 0xaaU, ucConstTaskNumber = 0x55U;\r
+const unsigned char ucConstQueueNumber = 0xaaU;\r
 void *pvAllocated;\r
+static portBASE_TYPE xTraceRunning = pdTRUE;\r
 \r
 /* These three functions are only meant for use by trace code, and not for\r
 direct use from application code, hence their prototypes are not in queue.h. */\r
@@ -313,39 +352,9 @@ extern unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );
        tasks waiting to be terminated by the idle task. */\r
        Sleep( ulMSToSleep );\r
 \r
-       /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and \r
-       xTaskGetIdleTaskHandle() functions.  Also try using the function that sets\r
-       the task number. */\r
-       xIdleTaskHandle = xTaskGetIdleTaskHandle();\r
-       xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle();\r
-       vTaskSetTaskNumber( xIdleTaskHandle, ( unsigned long ) ucConstTaskNumber );\r
-       configASSERT( uxTaskGetTaskNumber( xIdleTaskHandle ) == ucConstTaskNumber );\r
-\r
-       /* This is the idle hook, so the current task handle should equal the \r
-       returned idle task handle. */\r
-       if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle )\r
-       {\r
-               pcStatusMessage = "Error:  Returned idle task handle was incorrect";\r
-       }\r
-\r
-       /* Check the timer task handle was returned correctly. */\r
-       pcTaskName = pcTaskGetTaskName( xTimerTaskHandle );\r
-       if( strcmp( pcTaskName, "Tmr Svc" ) != 0 )\r
-       {\r
-               pcStatusMessage = "Error:  Returned timer task handle was incorrect";\r
-       }\r
-\r
-       /* This task is running, make sure its state is returned as running. */\r
-       if( eTaskStateGet( xIdleTaskHandle ) != eRunning )\r
-       {\r
-               pcStatusMessage = "Error:  Returned idle task state was incorrect";\r
-       }\r
-\r
-       /* If this task is running, then the timer task must be blocked. */\r
-       if( eTaskStateGet( xTimerTaskHandle ) != eBlocked )\r
-       {\r
-               pcStatusMessage = "Error:  Returned timer task state was incorrect";\r
-       }\r
+       /* Demonstrate a few utility functions that are not demonstrated by any of\r
+       the standard demo tasks. */\r
+       prvDemonstrateTaskStateAndHandleGetFunctions();\r
 \r
        /* If xMutexToDelete has not already been deleted, then delete it now.\r
        This is done purely to demonstrate the use of, and test, the \r
@@ -365,40 +374,21 @@ extern unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );
                configASSERT( ucQueueGetQueueType( xMutexToDelete ) == queueQUEUE_TYPE_MUTEX );\r
                vSemaphoreDelete( xMutexToDelete );\r
                xMutexToDelete = NULL;\r
-\r
-               /* Other tests that should only be performed once follow.  The test task\r
-               is not created on each iteration because to do so would cause the death\r
-               task to report an error (too many tasks running). */\r
-\r
-               /* Create a test task to use to test other eTaskStateGet() return values. */\r
-               if( xTaskCreate( prvTestTask, "Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTestTask ) == pdPASS )\r
-               {\r
-                       /* If this task is running, the test task must be in the ready state. */\r
-                       if( eTaskStateGet( xTestTask ) != eReady )\r
-                       {\r
-                               pcStatusMessage = "Error: Returned test task state was incorrect 1";\r
-                       }\r
-\r
-                       /* Now suspend the test task and check its state is reported correctly. */\r
-                       vTaskSuspend( xTestTask );\r
-                       if( eTaskStateGet( xTestTask ) != eSuspended )\r
-                       {\r
-                               pcStatusMessage = "Error: Returned test task state was incorrect 2";\r
-                       }\r
-\r
-                       /* Now delete the task and check its state is reported correctly. */\r
-                       vTaskDelete( xTestTask );\r
-                       if( eTaskStateGet( xTestTask ) != eDeleted )\r
-                       {\r
-                               pcStatusMessage = "Error: Returned test task state was incorrect 3";\r
-                       }\r
-               }\r
        }\r
 \r
        /* Exercise heap_4 a bit.  The malloc failed hook will trap failed \r
        allocations so there is no need to test here. */\r
        pvAllocated = pvPortMalloc( ( rand() % 100 ) + 1 );\r
        vPortFree( pvAllocated );\r
+\r
+       if( _kbhit() != pdFALSE )\r
+       {\r
+               if( xTraceRunning == pdTRUE )\r
+               {\r
+                       prvSaveTraceFile();\r
+                       xTraceRunning = pdFALSE;\r
+               }\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -421,9 +411,18 @@ void vApplicationTickHook( void )
        can be called from an ISR. */\r
        vTimerPeriodicISRTests();\r
 \r
+       /* Call the periodic queue overwrite from ISR demo. */\r
+       vQueueOverwritePeriodicISRDemo();\r
+\r
        /* Write to a queue that is in use as part of the queue set demo to \r
        demonstrate using queue sets from an ISR. */\r
        vQueueSetAccessQueueSetFromISR();\r
+\r
+       /* Write a user event to the trace log.  \r
+       Note tick events will not appear in the trace recording with regular period\r
+       because this project runs in a Windows simulator, and does not therefore\r
+       exhibit deterministic behaviour. */\r
+       vTraceUserEvent( xTickTraceUserEvent );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -433,9 +432,104 @@ void vAssertCalled( void )
 \r
        /* Stop the trace recording. */\r
        vTraceStop();\r
-       vTracePortSave();\r
+       prvSaveTraceFile();\r
                \r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+static void prvSaveTraceFile( void )\r
+{\r
+FILE* pxOutputFile;\r
+\r
+       fopen_s( &pxOutputFile, "Trace.dump", "wb");\r
+\r
+       if( pxOutputFile != NULL )\r
+       {\r
+               fwrite( RecorderDataPtr, sizeof( RecorderDataType ), 1, pxOutputFile );\r
+               fclose( pxOutputFile );\r
+               printf( "\r\nTrace output saved to Trace.dump\r\n" );\r
+       }\r
+       else\r
+       {\r
+               printf( "\r\nFailed to create trace dump file\r\n" );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDemonstrateTaskStateAndHandleGetFunctions( void )\r
+{\r
+xTaskHandle xIdleTaskHandle, xTimerTaskHandle;\r
+const unsigned char ucConstTaskNumber = 0x55U;\r
+signed char *pcTaskName;\r
+static portBASE_TYPE xPerformedOneShotTests = pdFALSE;\r
+xTaskHandle xTestTask;\r
+\r
+       /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and \r
+       xTaskGetIdleTaskHandle() functions.  Also try using the function that sets\r
+       the task number. */\r
+       xIdleTaskHandle = xTaskGetIdleTaskHandle();\r
+       xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle();\r
+       vTaskSetTaskNumber( xIdleTaskHandle, ( unsigned long ) ucConstTaskNumber );\r
+       configASSERT( uxTaskGetTaskNumber( xIdleTaskHandle ) == ucConstTaskNumber );\r
+\r
+       /* This is the idle hook, so the current task handle should equal the \r
+       returned idle task handle. */\r
+       if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle )\r
+       {\r
+               pcStatusMessage = "Error:  Returned idle task handle was incorrect";\r
+       }\r
+\r
+       /* Check the timer task handle was returned correctly. */\r
+       pcTaskName = pcTaskGetTaskName( xTimerTaskHandle );\r
+       if( strcmp( pcTaskName, "Tmr Svc" ) != 0 )\r
+       {\r
+               pcStatusMessage = "Error:  Returned timer task handle was incorrect";\r
+       }\r
+\r
+       /* This task is running, make sure it's state is returned as running. */\r
+       if( eTaskStateGet( xIdleTaskHandle ) != eRunning )\r
+       {\r
+               pcStatusMessage = "Error:  Returned idle task state was incorrect";\r
+       }\r
+\r
+       /* If this task is running, then the timer task must be blocked. */\r
+       if( eTaskStateGet( xTimerTaskHandle ) != eBlocked )\r
+       {\r
+               pcStatusMessage = "Error:  Returned timer task state was incorrect";\r
+       }\r
+\r
+       /* Other tests that should only be performed once follow.  The test task\r
+       is not created on each iteration because to do so would cause the death\r
+       task to report an error (too many tasks running). */\r
+       if( xPerformedOneShotTests == pdFALSE )\r
+       {\r
+               /* Don't run this part of the test again. */\r
+               xPerformedOneShotTests = pdTRUE;\r
+\r
+               /* Create a test task to use to test other eTaskStateGet() return values. */\r
+               if( xTaskCreate( prvTestTask, "Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTestTask ) == pdPASS )\r
+               {\r
+                       /* If this task is running, the test task must be in the ready state. */\r
+                       if( eTaskStateGet( xTestTask ) != eReady )\r
+                       {\r
+                               pcStatusMessage = "Error: Returned test task state was incorrect 1";\r
+                       }\r
+\r
+                       /* Now suspend the test task and check its state is reported correctly. */\r
+                       vTaskSuspend( xTestTask );\r
+                       if( eTaskStateGet( xTestTask ) != eSuspended )\r
+                       {\r
+                               pcStatusMessage = "Error: Returned test task state was incorrect 2";\r
+                       }\r
+\r
+                       /* Now delete the task and check its state is reported correctly. */\r
+                       vTaskDelete( xTestTask );\r
+                       if( eTaskStateGet( xTestTask ) != eDeleted )\r
+                       {\r
+                               pcStatusMessage = "Error: Returned test task state was incorrect 3";\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r