X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=Demo%2FWIN32-MSVC%2Fmain.c;h=f067143e18b250a23f0987c96c0077060d2db6fb;hb=1e29c3a095310fe360325ef6fbb5c9cd9af709da;hp=b5b7d497bfb5ebacb07cca44b97eb6032dd917a0;hpb=702eb2128ca5a045bed89e68d7ff90bbccc74056;p=freertos diff --git a/Demo/WIN32-MSVC/main.c b/Demo/WIN32-MSVC/main.c index b5b7d497b..f067143e1 100644 --- a/Demo/WIN32-MSVC/main.c +++ b/Demo/WIN32-MSVC/main.c @@ -1,38 +1,38 @@ /* - FreeRTOS V6.1.0 - Copyright (C) 2010 Real Time Engineers Ltd. + FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. + *************************************************************************** - * * - * If you are: * - * * - * + New to FreeRTOS, * - * + Wanting to learn FreeRTOS or multitasking in general quickly * - * + Looking for basic training, * - * + Wanting to improve your FreeRTOS skills and productivity * - * * - * then take a look at the FreeRTOS books - available as PDF or paperback * - * * - * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * - * http://www.FreeRTOS.org/Documentation * - * * - * A pdf reference manual is also available. Both are usually delivered * - * to your inbox within 20 minutes to two hours when purchased between 8am * - * and 8pm GMT (although please allow up to 24 hours in case of * - * exceptional circumstances). Thank you for your support! * - * * + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * *************************************************************************** + 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 exception 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. See the GNU General Public License for + >>>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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License and the FreeRTOS license exception along with FreeRTOS; if not it can be viewed here: http://www.freertos.org/a00114.html and also obtained @@ -51,42 +51,113 @@ licensing and training services. */ +/* + ******************************************************************************* + * -NOTE- The Win32 port is a simulation (or is that emulation?) only! Do not + * expect to get real time behaviour from the Win32 port or this demo + * application. It is provided as a convenient development and demonstration + * test bed only. This was tested using Windows XP on a dual core laptop. + * + * - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT - + ******************************************************************************* + * + * main() creates all the demo application tasks, then starts the scheduler. + * The web documentation provides more details of the standard demo application + * tasks, which provide no particular functionality but do provide a good + * example of how to use the FreeRTOS API. + * + * In addition to the standard demo tasks, the following tasks and tests are + * defined and/or created within this file: + * + * "Check" task - This only executes every five seconds but has a high priority + * to ensure it gets processor time. Its main function is to check that all the + * standard demo tasks are still operational. While no errors have been + * discovered the check task will print out "OK" and the current simulated tick + * time. If an error is discovered in the execution of a task then the check + * task will print out an appropriate error message. + * + */ + + +/* Standard includes. */ #include + +/* Kernel includes. */ #include #include "task.h" #include "queue.h" - -/* Task priorities. */ -#define mainSTDOUT_TASK_PRIORITY tskIDLE_PRIORITY - -/* Stack sizes. */ -#define mainSTDOUT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 ) - -/* File scope variables. */ -static volatile unsigned long ul1 = 0, ul2 = 0; -static xQueueHandle xStdoutQueue = NULL; +#include "timers.h" +#include "semphr.h" + +/* Standard demo includes. */ +#include "BlockQ.h" +#include "integer.h" +#include "semtest.h" +#include "PollQ.h" +#include "GenQTest.h" +#include "QPeek.h" +#include "recmutex.h" +#include "flop.h" +#include "TimerDemo.h" +#include "countsem.h" +#include "death.h" +#include "dynamic.h" + +/* Priorities at which the tasks are created. */ +#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY ) + +#define mainTIMER_TEST_PERIOD ( 50 ) /* Task function prototypes. */ -static void prvTask1( void *pvParameters ); -static void prvTask2( void *pvParameters ); -static void prvStdoutTask( void *pvParameters ); +static void prvCheckTask( void *pvParameters ); -/* Create a queue on which console output strings can be posted, then start the -task that processes the queue - printf()'ing each string that is received. */ -static void prvStartStdoutTask( void ); +/* The variable into which error messages are latched. */ +static char *pcStatusMessage = "OK"; -/* Post a message for output by the stdout task. Basically queues the message -pointed to by pcTextToPrint for output to stdout in a thread safe manner. */ -void vMainConsolePrint( const char *pcTextToPrint, portTickType xTicksToWait ); +/* This semaphore is created purely to test using the vSemaphoreDelete() and +semaphore tracing API functions. It has no other purpose. */ +static xSemaphoreHandle xMutexToDelete = NULL; -volatile unsigned long ulIdleCount = 0UL, ulT1Count = 0UL, ulT2Count = 0UL, ulTicks = 0UL; /*-----------------------------------------------------------*/ int main( void ) { - prvStartStdoutTask(); - xTaskCreate( prvTask1, "t1", 100, NULL, 0, NULL ); - xTaskCreate( prvTask2, "t2", 100, NULL, 0, NULL ); + /* Start the check task as described at the top of this file. */ + xTaskCreate( prvCheckTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); + + /* Create the standard demo tasks. */ + vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); + vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); + vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); + vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); + vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); + vStartQueuePeekTasks(); + vStartMathTasks( mainFLOP_TASK_PRIORITY ); + vStartRecursiveMutexTasks(); + vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); + vStartCountingSemaphoreTasks(); + vStartDynamicPriorityTasks(); + + /* The suicide tasks must be created last as they need to know how many + tasks were running prior to their creation. This then allows them to + ascertain whether or not the correct/expected number of tasks are running at + any given time. */ + vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + + /* Create the semaphore that will be deleted in the idle task hook. This + is done purely to test the use of vSemaphoreDelete(). */ + xMutexToDelete = xSemaphoreCreateMutex(); + + /* Start the scheduler itself. */ vTaskStartScheduler(); /* Should never get here unless there was not enough heap space to create @@ -95,102 +166,167 @@ int main( void ) } /*-----------------------------------------------------------*/ -void vMainConsolePrint( const char *pcTextToPrint, portTickType xTicksToWait ) +static void prvCheckTask( void *pvParameters ) { - if( xStdoutQueue != NULL ) - { - xQueueSend( xStdoutQueue, &pcTextToPrint, xTicksToWait ); - } -} -/*-----------------------------------------------------------*/ +portTickType xNextWakeTime; +const portTickType xCycleFrequency = 1000 / portTICK_RATE_MS; -static void prvStartStdoutTask( void ) -{ -const unsigned long ulQueueLength = 20; + /* Just to remove compiler warning. */ + ( void ) pvParameters; - /* Create the queue on which starings for output will be stored. */ - xStdoutQueue = xQueueCreate( ulQueueLength, ( unsigned portBASE_TYPE ) sizeof( char * ) ); + /* Initialise xNextWakeTime - this only needs to be done once. */ + xNextWakeTime = xTaskGetTickCount(); - if( xStdoutQueue != NULL ) + for( ;; ) { - /* Create the task that processes the stdout messages. */ - xTaskCreate( prvStdoutTask, "stdout task", mainSTDOUT_TASK_STACK_SIZE, NULL, mainSTDOUT_TASK_PRIORITY, NULL ); + /* Place this task in the blocked state until it is time to run again. */ + vTaskDelayUntil( &xNextWakeTime, xCycleFrequency ); + + /* Check the standard demo tasks are running without error. */ + if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE ) + { + pcStatusMessage = "Error: TimerDemo"; + } + else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: IntMath"; + } + else if( xAreGenericQueueTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: GenQueue"; + } + else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: QueuePeek"; + } + else if( xAreBlockingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: BlockQueue"; + } + else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: SemTest"; + } + else if( xArePollingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: PollQueue"; + } + else if( xAreMathsTaskStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Flop"; + } + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: RecMutex"; + } + else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: CountSem"; + } + else if( xIsCreateTaskStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: Death"; + } + else if( xAreDynamicPriorityTasksStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Dynamic\r\n"; + } + + /* This is the only task that uses stdout so its ok to call printf() + directly. */ + printf( "%s - %d\r\n", pcStatusMessage, xTaskGetTickCount() ); } } /*-----------------------------------------------------------*/ -static void prvStdoutTask( void *pvParameters ) +void vApplicationIdleHook( void ) { -char *pcString; +const unsigned long ulMSToSleep = 5; +xTaskHandle xIdleTaskHandle, xTimerTaskHandle; +signed char *pcTaskName; +const unsigned char ucConstQueueNumber = 0xaaU, ucConstTaskNumber = 0x55U; + +/* These three functions are only meant for use by trace code, and not for +direct use from application code, hence their prototypes are not in queue.h. */ +extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber ); +extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue ); +extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ); +extern void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ); +extern unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ); + + /* Sleep to reduce CPU load, but don't sleep indefinitely in case there are + tasks waiting to be terminated by the idle task. */ + Sleep( ulMSToSleep ); + + /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and + xTaskGetIdleTaskHandle() functions. Also try using the function that sets + the task number. */ + xIdleTaskHandle = xTaskGetIdleTaskHandle(); + xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle(); + vTaskSetTaskNumber( xIdleTaskHandle, ( unsigned long ) ucConstTaskNumber ); + configASSERT( uxTaskGetTaskNumber( xIdleTaskHandle ) == ucConstTaskNumber ); + + /* This is the idle hook, so the current task handle should equal the + returned idle task handle. */ + if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle ) + { + pcStatusMessage = "Error: Returned idle task handle was incorrect"; + } - /* Just to remove compiler warnings. */ - ( void ) pvParameters; + /* Check the timer task handle was returned correctly. */ + pcTaskName = pcTaskGetTaskName( xTimerTaskHandle ); + if( strcmp( pcTaskName, "Tmr Svc" ) != 0 ) + { + pcStatusMessage = "Error: Returned timer task handle was incorrect"; + } - for( ;; ) + /* If xMutexToDelete has not already been deleted, then delete it now. + This is done purely to demonstrate the use of, and test, the + vSemaphoreDelete() macro. Care must be taken not to delete a semaphore + that has tasks blocked on it. */ + if( xMutexToDelete != NULL ) { - /* This task would not have been created if the queue had not been created - successfully too. Also, because of the FreeRTOSConfig.h settings using - portMAX_DELAY in this case means wait forever, so when this function returns - we know there is a string to print. */ - xQueueReceive( xStdoutQueue, &pcString, portMAX_DELAY ); - printf( "%s", pcString ); - //fflush( stdout ); + /* Before deleting the semaphore, test the function used to set its + number. This would normally only be done from trace software, rather + than application code. */ + vQueueSetQueueNumber( xMutexToDelete, ucConstQueueNumber ); + + /* Before deleting the semaphore, test the functions used to get its + type and number. Again, these would normally only be done from trace + software, rather than application code. */ + configASSERT( ucQueueGetQueueNumber( xMutexToDelete ) == ucConstQueueNumber ); + configASSERT( ucQueueGetQueueType( xMutexToDelete ) == queueQUEUE_TYPE_MUTEX ); + vSemaphoreDelete( xMutexToDelete ); + xMutexToDelete = NULL; } } /*-----------------------------------------------------------*/ -static void prvTask1( void *pvParameters ) +void vApplicationMallocFailedHook( void ) { -const char *pcTask1Message = "Task 1 running\r\n"; -const portTickType xTicksToDelay = 1000 / portTICK_RATE_MS; - - /* Just to remove compiler warnings. */ - ( void ) pvParameters; - - for( ;; ) - { -// ul1++; - vMainConsolePrint( pcTask1Message, 0 ); - vTaskDelay( xTicksToDelay ); - ulT1Count++; - } + /* Can be implemented if required, but probably not required in this + environment and running this demo. */ } /*-----------------------------------------------------------*/ -static void prvTask2( void *pvParameters ) +void vApplicationStackOverflowHook( void ) { -const char *pcTask2Message = "Task 2 running\r\n"; -const portTickType xTicksToDelay = 500 / portTICK_RATE_MS; - - /* Just to remove compiler warnings. */ - ( void ) pvParameters; - - for( ;; ) - { -// ul2++; - vMainConsolePrint( pcTask2Message, 0 ); - vTaskDelay( xTicksToDelay ); - ulT2Count++; -// taskYIELD(); - } + /* Can be implemented if required, but not required in this + environment and running this demo. */ } /*-----------------------------------------------------------*/ -void vApplicationIdleHook() +void vApplicationTickHook( void ) { -const unsigned long ulMSToSleep = 5; - - /* Sleep to reduce CPU load, but don't sleep indefinitely if not using - preemption as as nothing will cause a task switch. */ - #if configUSE_PREEMPTION != 0 - { - SleepEx( INFINITE, TRUE ); - } - #else - { - SleepEx( ulMSToSleep, TRUE ); - } - #endif + /* Call the periodic timer test, which tests the timer API functions that + can be called from an ISR. */ + vTimerPeriodicISRTests(); +} +/*-----------------------------------------------------------*/ - ulIdleCount++; +void vAssertCalled( void ) +{ + taskDISABLE_INTERRUPTS(); + for( ;; ); } +