From 7ec5fa3c6821260f50df706993e68ece686cdbbd Mon Sep 17 00:00:00 2001 From: richardbarry Date: Sun, 21 Nov 2010 14:35:36 +0000 Subject: [PATCH] Updated the Win32 MSVC demo files. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1152 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../DemosModifiedForLowTickRate/recmutex.c | 398 ++++++++++++++++++ Demo/WIN32-MSVC/FreeRTOSConfig.h | 46 +- Demo/WIN32-MSVC/WIN32.suo | Bin 41984 -> 54784 bytes Demo/WIN32-MSVC/WIN32.vcxproj | 7 +- Demo/WIN32-MSVC/WIN32.vcxproj.filters | 9 +- Demo/WIN32-MSVC/main.c | 58 ++- 6 files changed, 491 insertions(+), 27 deletions(-) create mode 100644 Demo/WIN32-MSVC/DemosModifiedForLowTickRate/recmutex.c diff --git a/Demo/WIN32-MSVC/DemosModifiedForLowTickRate/recmutex.c b/Demo/WIN32-MSVC/DemosModifiedForLowTickRate/recmutex.c new file mode 100644 index 000000000..600906790 --- /dev/null +++ b/Demo/WIN32-MSVC/DemosModifiedForLowTickRate/recmutex.c @@ -0,0 +1,398 @@ +/* + FreeRTOS V6.1.0 - Copyright (C) 2010 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! * + * * + *************************************************************************** + + 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 + 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 + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + 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. */ +#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 ) + +/* In this version the tick period is very long, so the short delay cannot be +for too many ticks, or the check task will execute and find that the recmutex +tasks have not completed their functionality and then signal an error. The +delay does however have to be long enough to allow the lower priority tasks +a chance of executing - this is basically achieved by reducing the number +of times the loop that takes/gives the recursive mutex executes. */ +#define recmuMAX_COUNT ( 2 ) +#define recmuSHORT_DELAY ( 20 ) +#define recmuNO_DELAY ( ( portTickType ) 0 ) +#define recmuFIVE_TICK_DELAY ( ( portTickType ) 5 ) + +/* 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 xSemaphoreHandle xMutex; + +/* Variables used to detect and latch errors. */ +static volatile portBASE_TYPE xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE; +static volatile unsigned portBASE_TYPE uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0; + +/* Handles of the two higher priority tasks, required so they can be resumed +(unsuspended). */ +static xTaskHandle 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( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Recursive_Mutex" ); + + + if( xMutex != NULL ) + { + xTaskCreate( prvRecursiveMutexControllingTask, ( signed portCHAR * ) "Rec1Ctrl", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle ); + xTaskCreate( prvRecursiveMutexBlockingTask, ( signed portCHAR * ) "Rec2Blck", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle ); + xTaskCreate( prvRecursiveMutexPollingTask, ( signed portCHAR * ) "Rec3Poll", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexControllingTask( void *pvParameters ) +{ +unsigned portBASE_TYPE 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, recmuFIVE_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. */ + if( xSemaphoreTakeRecursive( xMutex, portMAX_DELAY ) == 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 ) + { + /* 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; + } + + /* Release the mutex, disinheriting the higher priority again. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + } + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreRecursiveMutexTasksStillRunning( void ) +{ +portBASE_TYPE xReturn; +static unsigned portBASE_TYPE 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; +} + + + + diff --git a/Demo/WIN32-MSVC/FreeRTOSConfig.h b/Demo/WIN32-MSVC/FreeRTOSConfig.h index 3d657bf94..a83b8abff 100644 --- a/Demo/WIN32-MSVC/FreeRTOSConfig.h +++ b/Demo/WIN32-MSVC/FreeRTOSConfig.h @@ -64,10 +64,11 @@ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. *----------------------------------------------------------*/ + #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 0 -#define configTICK_RATE_HZ ( ( portTickType ) 50 ) +#define configTICK_RATE_HZ ( 50 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ #define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 50 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ #define configTOTAL_HEAP_SIZE ( ( size_t ) 0 ) /* This parameter has no effect when heap_3.c is included in the project. */ #define configMAX_TASK_NAME_LEN ( 12 ) @@ -105,4 +106,47 @@ to exclude the API function. */ #define INCLUDE_xTaskGetSchedulerState 1 +/* When switching threads, Windows does not always seem to run the selected +thread immediately. This function can be called to check if the thread +that is currently running is the thread that is responsible for executing +the task selected by the real time scheduler. If not then a yield is performed +which will try and force the running thread to block on a semaphore, and hence +allow the thread that should be running to take over. The trace macros are a +convenient way of lacing the code with these checking calls. */ +void vPortCheckCorrectThreadIsRunning( void ); + +#define traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceBLOCKING_ON_QUEUE_SEND(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceGIVE_MUTEX_RECURSIVE(pxMutex) vPortCheckCorrectThreadIsRunning();(void)pxMutex +#define traceQUEUE_CREATE(pxNewQueue) vPortCheckCorrectThreadIsRunning();(void)pxNewQueue +#define traceQUEUE_CREATE_FAILED() vPortCheckCorrectThreadIsRunning() +#define traceCREATE_MUTEX(pxNewMutex) vPortCheckCorrectThreadIsRunning();(void)pxNewMutex +#define traceCREATE_MUTEX_FAILED() vPortCheckCorrectThreadIsRunning() +#define traceGIVE_MUTEX_RECURSIVE(pxMutex) vPortCheckCorrectThreadIsRunning();(void)pxMutex +#define traceGIVE_MUTEX_RECURSIVE_FAILED(pxMutex) vPortCheckCorrectThreadIsRunning();(void)pxMutex +#define traceTAKE_MUTEX_RECURSIVE(pxMutex) vPortCheckCorrectThreadIsRunning();(void)pxMutex +#define traceTAKE_MUTEX_RECURSIVE_FAILED(pxMutex) vPortCheckCorrectThreadIsRunning();(void)pxMutex +#define traceCREATE_COUNTING_SEMAPHORE() vPortCheckCorrectThreadIsRunning() +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() vPortCheckCorrectThreadIsRunning() +#define traceQUEUE_SEND(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_SEND_FAILED(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_RECEIVE(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_RECEIVE_FAILED(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_PEEK(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_SEND_FROM_ISR(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_RECEIVE_FROM_ISR(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_RECEIVE_FROM_ISR_FAILED(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceQUEUE_DELETE(pxQueue) vPortCheckCorrectThreadIsRunning();(void)pxQueue +#define traceTASK_CREATE(pxTask) vPortCheckCorrectThreadIsRunning();(void)pxTask +#define traceTASK_CREATE_FAILED(pxNewTCB) vPortCheckCorrectThreadIsRunning();(void)pxNewTCB +#define traceTASK_DELETE(pxTask) vPortCheckCorrectThreadIsRunning();(void)pxTask +#define traceTASK_DELAY_UNTIL() vPortCheckCorrectThreadIsRunning() +#define traceTASK_DELAY() vPortCheckCorrectThreadIsRunning() +#define traceTASK_PRIORITY_SET(pxTask,uxNewPriority) vPortCheckCorrectThreadIsRunning();(void)pxTask;(void)uxNewPriority +#define traceTASK_SUSPEND(pxTask) vPortCheckCorrectThreadIsRunning();(void)pxTask +#define traceTASK_RESUME(pxTask) vPortCheckCorrectThreadIsRunning();(void)pxTask +#define traceTASK_RESUME_FROM_ISR(pxTask) vPortCheckCorrectThreadIsRunning();(void)pxTask + + #endif /* FREERTOS_CONFIG_H */ diff --git a/Demo/WIN32-MSVC/WIN32.suo b/Demo/WIN32-MSVC/WIN32.suo index f78c1bfeb16c23ef863b3d2ace635c7ead82a487..fc93ff8c2fbeb26c31bfa1371050b2bf265ec05a 100644 GIT binary patch delta 7098 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 Ioa1u&Kg0`kBme*a delta 3359 zcmbtW3s98T75?wC3(I3ymgfqKEC@b8U>B9Qusq}uQA8J`2}V>vQC{ML3K*AEO|g!~ zJvJKg5fqcQ@yS0<(y7(;LGY0#G}d-HlXleUV_N%2Czw%Z4E@fsq|>PBOmqJE{&ViV z=br!Gdmi_Q=IugG5)KOk&$Fcl9*?M&j6yiy{9~IX(og$U>0Bo<^Zf{0nY{U z-0cGJ*+3ys1QY`$zzaYQPzuZi<^g5Ed?1PLW(V%6I^j^(YfZslwgqjwDLl|GWmCKI zhB_QlJV4pArZ_Z8+Nc^*@~5fPQ=iK=S-}8A026>nzz9SEyn%_puK}Jk34Agz1(*u- z&~eW>xr2~+%Wne~U~EVEkiTt5d94c~a0$QN~fxfdfj0i)Txzh?3a|hy(-x z%hMs5@f1iVNV%@DTu3H7xj?>@j(4H!$%nQ?mvlMDEFnS|DK|8dGD3}H*Bi(X7egkc zl1}K2@*nhX3EfT0)^pJ}hNABMDLAlFNNY$AX_0EA(WwpUIZ2^=TC~8|BS&H&2MUGXlksS zTi00Eu)MyqrDkPAtF2}uAFp_a9uH*DacjZU&d!dsyyKB1Hf_MAi!gX-JCj8 z^vY{!(Eb!l)cfw20j6XfL{Wi0=Ix) z0k;93_Zv5-s?_iAsSG1UTAoUYz7!g{Jc0f?=uaEc##5iQlI#^hlzY99cEY1h;})^p zk#S8K2vt|Q4rf@ETy#crH*>x^3XK?dhdi9==Rtcbrjf%M5Kx$}i22Jd!yo^)_j{j} zw5I>=y*Q3&Lkj{jQCf{DTm$wamolVE1aBp>jdow2p!qGjM=92MpZ+ya(QnCDs05ce z`YL&vY|EQ3)Y#Gp=RdDQ)ditjew6Q}pz;9={d3UQ6;p427^3SPwd8vL9Pe55gTd?i z*^u~-0BuB`aDs8zZzd6vLpOqrbf?GYDBh&=zgQ9a_^$WeJ3H<)g=c3Kg}c)AaPbO3 zx-0Rt?!(z3T)9U{=`4q!2MRc2GU%mHlQ2@cK9V;&N|dReOwPzU@d%azJr+t$?GaERQdh6-5#Qux{9hPuGWvt>9G`DA4itRB|3Z7JH6Y^dB=V^^yGTx zxaf;3c&Fk;+OpshS&W??bEO)(xbPA=(i#Jjs%zS6>YJKtT9O*puV}5SuXa?}y_1qn zCR9SW#JoM2{7wf&ZFKv#8aryk>bX4q7t!6~g#Ja>gff+-SB+?;Sd0#sP0vCW>=VOf5k539kp$O>}!JP$IJY2sjx?0<)c&-N@vSY zi#=84j%u4YN3GRc#0T`Cx=hWNqlN8Y4P>ja`*Nss03bSB7$poeaHqGcLm*(Cy;ZpR`xmZP|(&>2Px*YHS$kR?-g|F^@Fmlf2ZJKN~zL| z&q&ubo;s()9L-sn6EZM7Xt>8%Wn1PyI*N2+eb}O>S-G5npQ?p}mO`m0GImsTZMW z<@5hvLHP<8DmxJW^x`x{ZbQt&*pTmHEY)4AsQgGol+{%+)}m_gUqKx%_K&Vbha;0a6Nd&<~8MR`^>+Kecf~HzwEZp{JYo>f3|%ezEzoyvyT(0mRf}0vsJy% zj%rG0$=s9V($qgk^Qv3(>X;_|sCO|nJJe)6ocFYoeE2G6`shE4nEo8o_eV9Q`!L-j z#ywk0^MzZBIfu`_(O{uZYqRBlylGKTUzc5uIr01dQ5EQ3)jiaMy>xYX7TxKJL#?m+ EH%I%|i2wiq diff --git a/Demo/WIN32-MSVC/WIN32.vcxproj b/Demo/WIN32-MSVC/WIN32.vcxproj index bc4b02e9f..a92b9185f 100644 --- a/Demo/WIN32-MSVC/WIN32.vcxproj +++ b/Demo/WIN32-MSVC/WIN32.vcxproj @@ -95,7 +95,7 @@ MaxSpeed OnlyExplicitInline - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded true @@ -105,13 +105,14 @@ .\Release/ Level3 true + ..\..\Source\include;..\..\Source\portable\MSVC-MingW;..\Common\Include;.;%(AdditionalIncludeDirectories) NDEBUG;%(PreprocessorDefinitions) 0x0c09 - .\Release/WIN32.exe + .\Release/RTOSDemo.exe true .\Release/WIN32.pdb Console @@ -131,8 +132,8 @@ - + %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) diff --git a/Demo/WIN32-MSVC/WIN32.vcxproj.filters b/Demo/WIN32-MSVC/WIN32.vcxproj.filters index f57f15453..3d075c58a 100644 --- a/Demo/WIN32-MSVC/WIN32.vcxproj.filters +++ b/Demo/WIN32-MSVC/WIN32.vcxproj.filters @@ -29,6 +29,9 @@ {88f409e6-d396-4ac5-94bd-7a99c914be46} + + {143cf5a3-f134-4439-9f71-a201ae23b44b} + @@ -64,9 +67,6 @@ Demo App Source\Common Demo Tasks - - Demo App Source\Common Demo Tasks - Demo App Source\Common Demo Tasks @@ -76,6 +76,9 @@ Demo App Source\Common Demo Tasks + + Demo App Source\Common Demo Tasks\ModifiedForLowTickRate + diff --git a/Demo/WIN32-MSVC/main.c b/Demo/WIN32-MSVC/main.c index 6685e2fed..a8f09742d 100644 --- a/Demo/WIN32-MSVC/main.c +++ b/Demo/WIN32-MSVC/main.c @@ -51,6 +51,39 @@ 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. Also, at the time of writing, a method of deleting theads + * has not been implemented, although doing so would be trivial so this + * functionality might be added in at a later date. At present, calling + * vTaskDelete() will delete the real time task from FreeRTOS but not the Win32 + * thread in which the task was executing. DO NOT CALL vTaskDelete() when using + * the Win32 port! 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 @@ -64,7 +97,6 @@ #include "BlockQ.h" #include "death.h" #include "integer.h" -//#include "blocktim.h" #include "semtest.h" #include "PollQ.h" #include "GenQTest.h" @@ -94,14 +126,6 @@ static xQueueHandle xStdoutQueue = NULL; /* Task function prototypes. */ 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 ); - -/* 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 ); - /*-----------------------------------------------------------*/ int main( void ) @@ -111,14 +135,13 @@ int main( void ) /* Create the standard demo tasks. */ vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); -// vCreateBlockTimeTasks(); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); vStartQueuePeekTasks(); - vStartRecursiveMutexTasks(); vStartMathTasks( mainFLOP_TASK_PRIORITY ); + vStartRecursiveMutexTasks(); /* Start the scheduler itself. */ vTaskStartScheduler(); @@ -134,7 +157,6 @@ static void prvCheckTask( void *pvParameters ) portTickType xNextWakeTime; const portTickType xCycleFrequency = 5000 / portTICK_RATE_MS; char *pcStatusMessage = "OK"; -long lCycleCount = 0; /* Just to remove compiler warning. */ ( void ) pvParameters; @@ -164,10 +186,6 @@ long lCycleCount = 0; { pcStatusMessage = "Error: BlockQueue"; } -// else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) -// { -// pcStatusMessage = "Error: BlockTime"; -// } else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) { pcStatusMessage = "Error: SemTest"; @@ -175,15 +193,15 @@ long lCycleCount = 0; else if( xArePollingQueuesStillRunning() != pdTRUE ) { pcStatusMessage = "Error: PollQueue"; - } - else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: RecMutex"; } else if( xAreMathsTaskStillRunning() != pdPASS ) { pcStatusMessage = "Error: Flop"; } + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: RecMutex"; + } /* This is the only task that uses stdout so its ok to call printf() directly. */ -- 2.39.2