X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FDemo%2FWIN32-MSVC%2Fmain_full.c;h=5b1505c507b102929aa4be6f55f348abfd7e043d;hb=9da84ad61903f51213117867366f22c3f9e63c7e;hp=1dadba8773f78f4e35f3f0aafc11e7fd0c38443e;hpb=b18af6b07e944b8c932a9be32fbce2344510896c;p=freertos diff --git a/FreeRTOS/Demo/WIN32-MSVC/main_full.c b/FreeRTOS/Demo/WIN32-MSVC/main_full.c index 1dadba877..5b1505c50 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/main_full.c +++ b/FreeRTOS/Demo/WIN32-MSVC/main_full.c @@ -1,5 +1,6 @@ /* - FreeRTOS V7.5.0 - Copyright (C) 2013 Real Time Engineers Ltd. + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -23,10 +24,10 @@ 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. + >>! 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 @@ -69,28 +70,27 @@ * application. It is provided as a convenient development and demonstration * test bed only. This was tested using Windows XP on a dual core laptop. * - * In this example, one simulated millisecond will take approximately 40ms to - * execute, and Windows will not be running the FreeRTOS simulator threads - * continuously, so the timing information in the FreeRTOS+Trace logs have no - * meaningful units. See the documentation page for the Windows simulator for - * an explanation of the slow timing: + * Windows will not be running the FreeRTOS simulator threads continuously, so + * the timing information in the FreeRTOS+Trace logs have no meaningful units. + * See the documentation page for the Windows simulator for an explanation of + * the slow timing: * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html * - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT - * * NOTE 2: This project provides two demo applications. A simple blinky style * project, and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select - * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select + * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY * in main.c. This file implements the comprehensive test and demo version. * * NOTE 3: This file only contains the source code that is specific to the - * basic demo. Generic functions, such FreeRTOS hook functions, are defined in + * basic demo. Generic functions, such FreeRTOS hook functions, are defined in * main.c. ******************************************************************************* * - * 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 + * 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 @@ -112,10 +112,10 @@ /* Kernel includes. */ #include -#include "task.h" -#include "queue.h" -#include "timers.h" -#include "semphr.h" +#include +#include +#include +#include /* Standard demo includes. */ #include "BlockQ.h" @@ -132,15 +132,17 @@ #include "dynamic.h" #include "QueueSet.h" #include "QueueOverwrite.h" +#include "EventGroupsDemo.h" +#include "IntSemTest.h" +#include "TaskNotify.h" /* Priorities at which the tasks are created. */ -#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) #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 ) @@ -151,7 +153,7 @@ /* Task function prototypes. */ static void prvCheckTask( void *pvParameters ); -/* A task that is created from the idle task to test the functionality of +/* A task that is created from the idle task to test the functionality of eTaskStateGet(). */ static void prvTestTask( void *pvParameters ); @@ -161,6 +163,23 @@ static void prvTestTask( void *pvParameters ); */ static void prvDemonstrateTaskStateAndHandleGetFunctions( void ); +/* + * Called from the idle task hook function to demonstrate the use of + * xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by + * any of the standard demo tasks. + */ +static void prvDemonstratePendingFunctionCall( void ); + +/* + * The function that is pended by prvDemonstratePendingFunctionCall(). + */ +static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 ); + +/* + * A task to demonstrate the use of the xQueueSpacesAvailable() function. + */ +static void prvDemoQueueSpaceFunctions( void *pvParameters ); + /*-----------------------------------------------------------*/ /* The variable into which error messages are latched. */ @@ -168,16 +187,17 @@ static char *pcStatusMessage = "OK"; /* This semaphore is created purely to test using the vSemaphoreDelete() and semaphore tracing API functions. It has no other purpose. */ -static xSemaphoreHandle xMutexToDelete = NULL; +static SemaphoreHandle_t xMutexToDelete = NULL; /*-----------------------------------------------------------*/ int main_full( void ) { /* 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 ); + xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); /* Create the standard demo tasks. */ + vStartTaskNotifyTask(); vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); @@ -186,15 +206,24 @@ int main_full( void ) vStartQueuePeekTasks(); vStartMathTasks( mainFLOP_TASK_PRIORITY ); vStartRecursiveMutexTasks(); - vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); vStartCountingSemaphoreTasks(); vStartDynamicPriorityTasks(); vStartQueueSetTasks(); vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); + xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + vStartEventGroupTasks(); + vStartInterruptSemaphoreTasks(); + + #if( configUSE_PREEMPTION != 0 ) + { + /* Don't expect these tasks to pass when preemption is not used. */ + vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); + } + #endif /* 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 + 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 ); @@ -205,7 +234,7 @@ int main_full( void ) /* Start the scheduler itself. */ vTaskStartScheduler(); - /* Should never get here unless there was not enough heap space to create + /* Should never get here unless there was not enough heap space to create the idle and other system tasks. */ return 0; } @@ -213,8 +242,8 @@ int main_full( void ) static void prvCheckTask( void *pvParameters ) { -portTickType xNextWakeTime; -const portTickType xCycleFrequency = 1000 / portTICK_RATE_MS; +TickType_t xNextWakeTime; +const TickType_t xCycleFrequency = 2500 / portTICK_PERIOD_MS; /* Just to remove compiler warning. */ ( void ) pvParameters; @@ -228,16 +257,35 @@ const portTickType xCycleFrequency = 1000 / portTICK_RATE_MS; vTaskDelayUntil( &xNextWakeTime, xCycleFrequency ); /* Check the standard demo tasks are running without error. */ - if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE ) + #if( configUSE_PREEMPTION != 0 ) + { + /* These tasks are only created when preemption is used. */ + if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE ) + { + pcStatusMessage = "Error: TimerDemo"; + } + } + #endif + + if( xAreTaskNotificationTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: Notification"; + } + + if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: IntSem"; + } + else if( xAreEventGroupTasksStillRunning() != pdTRUE ) { - pcStatusMessage = "Error: TimerDemo"; + pcStatusMessage = "Error: EventGroup"; } else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) { pcStatusMessage = "Error: IntMath"; - } + } else if( xAreGenericQueueTasksStillRunning() != pdTRUE ) - { + { pcStatusMessage = "Error: GenQueue"; } else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) @@ -274,18 +322,18 @@ const portTickType xCycleFrequency = 1000 / portTICK_RATE_MS; } else if( xAreDynamicPriorityTasksStillRunning() != pdPASS ) { - pcStatusMessage = "Error: Dynamic\r\n"; + pcStatusMessage = "Error: Dynamic"; } else if( xAreQueueSetTasksStillRunning() != pdPASS ) { - pcStatusMessage = "Error: Queue set\r\n"; + pcStatusMessage = "Error: Queue set"; } else if( xIsQueueOverwriteTaskStillRunning() != pdPASS ) { - pcStatusMessage = "Error: Queue overwrite\r\n"; + pcStatusMessage = "Error: Queue overwrite"; } - /* This is the only task that uses stdout so its ok to call printf() + /* This is the only task that uses stdout so its ok to call printf() directly. */ printf( "%s - %d\r\n", pcStatusMessage, xTaskGetTickCount() ); } @@ -314,17 +362,8 @@ const unsigned long ulMSToSleep = 5; void vFullDemoIdleFunction( void ) { const unsigned long ulMSToSleep = 15; -const unsigned char ucConstQueueNumber = 0xaaU; void *pvAllocated; -/* 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 ); @@ -333,27 +372,21 @@ extern unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ); the standard demo tasks. */ prvDemonstrateTaskStateAndHandleGetFunctions(); + /* Demonstrate the use of xTimerPendFunctionCall(), which is not + demonstrated by any of the standard demo tasks. */ + prvDemonstratePendingFunctionCall(); + /* If xMutexToDelete has not already been deleted, then delete it now. - This is done purely to demonstrate the use of, and test, the + 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 ) { - /* 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; } - /* Exercise heap_4 a bit. The malloc failed hook will trap failed + /* Exercise heap_5 a bit. The malloc failed hook will trap failed allocations so there is no need to test here. */ pvAllocated = pvPortMalloc( ( rand() % 100 ) + 1 ); vPortFree( pvAllocated ); @@ -363,36 +396,85 @@ extern unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ); /* Called by vApplicationTickHook(), which is defined in main.c. */ void vFullDemoTickHookFunction( void ) { +TaskHandle_t xTimerTask; + /* Call the periodic timer test, which tests the timer API functions that can be called from an ISR. */ - vTimerPeriodicISRTests(); + #if( configUSE_PREEMPTION != 0 ) + { + /* Only created when preemption is used. */ + vTimerPeriodicISRTests(); + } + #endif /* Call the periodic queue overwrite from ISR demo. */ vQueueOverwritePeriodicISRDemo(); - /* Write to a queue that is in use as part of the queue set demo to + /* Write to a queue that is in use as part of the queue set demo to demonstrate using queue sets from an ISR. */ vQueueSetAccessQueueSetFromISR(); + + /* Exercise event groups from interrupts. */ + vPeriodicEventGroupsProcessing(); + + /* Exercise giving mutexes from an interrupt. */ + vInterruptSemaphorePeriodicTest(); + + /* Exercise using task notifications from an interrupt. */ + xNotifyTaskFromISR(); + + /* For code coverage purposes. */ + xTimerTask = xTimerGetTimerDaemonTaskHandle(); + configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY ); +} +/*-----------------------------------------------------------*/ + +static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 ) +{ +static uint32_t ulLastParameter1 = 1000UL, ulLastParameter2 = 0UL; +uint32_t ulParameter1; + + ulParameter1 = ( uint32_t ) pvParameter1; + + /* Ensure the parameters are as expected. */ + configASSERT( ulParameter1 == ( ulLastParameter1 + 1 ) ); + configASSERT( ulParameter2 == ( ulLastParameter2 + 1 ) ); + + /* Remember the parameters for the next time the function is called. */ + ulLastParameter1 = ulParameter1; + ulLastParameter2 = ulParameter2; +} +/*-----------------------------------------------------------*/ + +static void prvDemonstratePendingFunctionCall( void ) +{ +static uint32_t ulParameter1 = 1000UL, ulParameter2 = 0UL; +const TickType_t xDontBlock = 0; /* This is called from the idle task so must *not* attempt to block. */ + + /* prvPendedFunction() just expects the parameters to be incremented by one + each time it is called. */ + ulParameter1++; + ulParameter2++; + + /* Pend the function call, sending the parameters. */ + xTimerPendFunctionCall( prvPendedFunction, ( void * ) ulParameter1, ulParameter2, xDontBlock ); } /*-----------------------------------------------------------*/ static void prvDemonstrateTaskStateAndHandleGetFunctions( void ) { -xTaskHandle xIdleTaskHandle, xTimerTaskHandle; -const unsigned char ucConstTaskNumber = 0x55U; -signed char *pcTaskName; +TaskHandle_t xIdleTaskHandle, xTimerTaskHandle; +char *pcTaskName; static portBASE_TYPE xPerformedOneShotTests = pdFALSE; -xTaskHandle xTestTask; +TaskHandle_t xTestTask; - /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and + /* 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 + /* This is the idle hook, so the current task handle should equal the returned idle task handle. */ if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle ) { @@ -453,4 +535,73 @@ xTaskHandle xTestTask; } /*-----------------------------------------------------------*/ +static void prvDemoQueueSpaceFunctions( void *pvParameters ) +{ +QueueHandle_t xQueue = NULL; +const unsigned portBASE_TYPE uxQueueLength = 10; +unsigned portBASE_TYPE uxReturn, x; + + /* Remove compiler warnings. */ + ( void ) pvParameters; + + /* Create the queue that will be used. Nothing is actually going to be + sent or received so the queue item size is set to 0. */ + xQueue = xQueueCreate( uxQueueLength, 0 ); + configASSERT( xQueue ); + + for( ;; ) + { + for( x = 0; x < uxQueueLength; x++ ) + { + /* Ask how many messages are available... */ + uxReturn = uxQueueMessagesWaiting( xQueue ); + + /* Check the number of messages being reported as being available + is as expected, and force an assert if not. */ + if( uxReturn != x ) + { + /* xQueue cannot be NULL so this is deliberately causing an + assert to be triggered as there is an error. */ + configASSERT( xQueue == NULL ); + } + + /* Ask how many spaces remain in the queue... */ + uxReturn = uxQueueSpacesAvailable( xQueue ); + + /* Check the number of spaces being reported as being available + is as expected, and force an assert if not. */ + if( uxReturn != ( uxQueueLength - x ) ) + { + /* xQueue cannot be NULL so this is deliberately causing an + assert to be triggered as there is an error. */ + configASSERT( xQueue == NULL ); + } + + /* Fill one more space in the queue. */ + xQueueSendToBack( xQueue, NULL, 0 ); + } + + /* Perform the same check while the queue is full. */ + uxReturn = uxQueueMessagesWaiting( xQueue ); + if( uxReturn != uxQueueLength ) + { + configASSERT( xQueue == NULL ); + } + + uxReturn = uxQueueSpacesAvailable( xQueue ); + + if( uxReturn != 0 ) + { + configASSERT( xQueue == NULL ); + } + + /* The queue is full, start again. */ + xQueueReset( xQueue ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + } +} +