/*\r
- FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.\r
All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
#define portMAX_INTERRUPTS ( ( uint32_t ) sizeof( uint32_t ) * 8UL ) /* The number of bits in an uint32_t. */\r
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )\r
\r
-/* The priorities at which the various components of the simulation execute.\r
-Priorities are higher when a soak test is performed to lessen the effect of\r
-Windows interfering with the timing. */\r
-#define portSOAK_TEST\r
-#ifndef portSOAK_TEST\r
- #define portSIMULATED_INTERRUPTS_THREAD_PRIORITY THREAD_PRIORITY_NORMAL\r
- #define portSIMULATED_TIMER_THREAD_PRIORITY THREAD_PRIORITY_BELOW_NORMAL\r
- #define portTASK_THREAD_PRIORITY THREAD_PRIORITY_IDLE\r
-#else\r
- #define portSIMULATED_INTERRUPTS_THREAD_PRIORITY THREAD_PRIORITY_TIME_CRITICAL\r
- #define portSIMULATED_TIMER_THREAD_PRIORITY THREAD_PRIORITY_HIGHEST\r
- #define portTASK_THREAD_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL\r
-#endif\r
+/* The priorities at which the various components of the simulation execute. */\r
+#define portDELETE_SELF_THREAD_PRIORITY THREAD_PRIORITY_TIME_CRITICAL /* Must be highest. */\r
+#define portSIMULATED_INTERRUPTS_THREAD_PRIORITY THREAD_PRIORITY_TIME_CRITICAL\r
+#define portSIMULATED_TIMER_THREAD_PRIORITY THREAD_PRIORITY_HIGHEST\r
+#define portTASK_THREAD_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL\r
+\r
/*\r
* Created as a high priority thread, this function uses a timer to simulate\r
* a tick interrupt being generated on an embedded target. In this Windows\r
{\r
xThreadState *pxThreadState = NULL;\r
int8_t *pcTopOfStack = ( int8_t * ) pxTopOfStack;\r
-\r
- #ifdef portSOAK_TEST\r
- {\r
- /* Ensure highest priority class is inherited. */\r
- if( !SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS ) )\r
- {\r
- printf( "SetPriorityClass() failed\r\n" );\r
- }\r
- }\r
- #endif\r
+const SIZE_T xStackSize = 1024; /* Set the size to a small number which will get rounded up to the minimum possible. */\r
\r
/* In this simulated case a stack is not initialised, but instead a thread\r
is created that will execute the task being created. The thread handles\r
pxThreadState = ( xThreadState * ) ( pcTopOfStack - sizeof( xThreadState ) );\r
\r
/* Create the thread itself. */\r
- pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, NULL );\r
- configASSERT( pxThreadState->pvThread );\r
+ pxThreadState->pvThread = CreateThread( NULL, xStackSize, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, NULL );\r
+ configASSERT( pxThreadState->pvThread ); /* See comment where TerminateThread() is called. */\r
SetThreadAffinityMask( pxThreadState->pvThread, 0x01 );\r
SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );\r
SetThreadPriority( pxThreadState->pvThread, portTASK_THREAD_PRIORITY );\r
\r
BaseType_t xPortStartScheduler( void )\r
{\r
-void *pvHandle;\r
-int32_t lSuccess = pdPASS;\r
-xThreadState *pxThreadState;\r
-\r
- /* Install the interrupt handlers used by the scheduler itself. */\r
- vPortSetInterruptHandler( portINTERRUPT_YIELD, prvProcessYieldInterrupt );\r
- vPortSetInterruptHandler( portINTERRUPT_TICK, prvProcessTickInterrupt );\r
-\r
- /* Create the events and mutexes that are used to synchronise all the\r
- threads. */\r
- pvInterruptEventMutex = CreateMutex( NULL, FALSE, NULL );\r
- pvInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
+void *pvHandle = NULL;\r
+int32_t lSuccess;\r
+xThreadState *pxThreadState = NULL;\r
+SYSTEM_INFO xSystemInfo;\r
\r
- if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) )\r
+ /* This port runs windows threads with extremely high priority. All the\r
+ threads execute on the same core - to prevent locking up the host only start\r
+ if the host has multiple cores. */\r
+ GetSystemInfo( &xSystemInfo );\r
+ if( xSystemInfo.dwNumberOfProcessors <= 1 )\r
{\r
+ printf( "This version of the FreeRTOS Windows port can only be used on multi-core hosts.\r\n" );\r
lSuccess = pdFAIL;\r
}\r
-\r
- /* Set the priority of this thread such that it is above the priority of\r
- the threads that run tasks. This higher priority is required to ensure\r
- simulated interrupts take priority over tasks. */\r
- pvHandle = GetCurrentThread();\r
- if( pvHandle == NULL )\r
+ else\r
{\r
- lSuccess = pdFAIL;\r
+ lSuccess = pdPASS;\r
+\r
+ /* The highest priority class is used to [try to] prevent other Windows\r
+ activity interfering with FreeRTOS timing too much. */\r
+ if( SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS ) == 0 )\r
+ {\r
+ printf( "SetPriorityClass() failed\r\n" );\r
+ }\r
+\r
+ /* Install the interrupt handlers used by the scheduler itself. */\r
+ vPortSetInterruptHandler( portINTERRUPT_YIELD, prvProcessYieldInterrupt );\r
+ vPortSetInterruptHandler( portINTERRUPT_TICK, prvProcessTickInterrupt );\r
+\r
+ /* Create the events and mutexes that are used to synchronise all the\r
+ threads. */\r
+ pvInterruptEventMutex = CreateMutex( NULL, FALSE, NULL );\r
+ pvInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
+\r
+ if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) )\r
+ {\r
+ lSuccess = pdFAIL;\r
+ }\r
+\r
+ /* Set the priority of this thread such that it is above the priority of\r
+ the threads that run tasks. This higher priority is required to ensure\r
+ simulated interrupts take priority over tasks. */\r
+ pvHandle = GetCurrentThread();\r
+ if( pvHandle == NULL )\r
+ {\r
+ lSuccess = pdFAIL;\r
+ }\r
}\r
\r
if( lSuccess == pdPASS )\r
{\r
WaitForSingleObject( pvInterruptEventMutex, INFINITE );\r
\r
+ /* !!! This is not a nice way to terminate a thread, and will eventually\r
+ result in resources being depleted if tasks frequently delete other\r
+ tasks (rather than deleting themselves) as the task stacks will not be\r
+ freed. */\r
ulErrorCode = TerminateThread( pxThreadState->pvThread, 0 );\r
configASSERT( ulErrorCode );\r
\r
does not run and swap it out before it is closed. If that were to happen\r
the thread would never run again and effectively be a thread handle and\r
memory leak. */\r
- SetThreadPriority( pvThread, THREAD_PRIORITY_HIGHEST );\r
+ SetThreadPriority( pvThread, portDELETE_SELF_THREAD_PRIORITY );\r
\r
/* This function will not return, therefore a yield is set as pending to\r
ensure a context switch occurs away from this thread on the next tick. */\r
ulErrorCode = CloseHandle( pvThread );\r
configASSERT( ulErrorCode );\r
\r
+ /* This is called from a critical section, which must be exited before the\r
+ thread stops. */\r
+ taskEXIT_CRITICAL();\r
+\r
ExitThread( 0 );\r
}\r
/*-----------------------------------------------------------*/\r