/*\r
- FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. \r
+ FreeRTOS V7.5.3 - Copyright (C) 2013 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 portEPC_STACK_LOCATION 124\r
#define portSTATUS_STACK_LOCATION 128\r
\r
-/******************************************************************/ \r
+/******************************************************************/\r
.macro portSAVE_CONTEXT\r
\r
- /* Make room for the context. First save the current status so we can \r
- manipulate it, and the cause and EPC registers so we capture their \r
- original values in case of interrupt nesting. */\r
+ /* Make room for the context. First save the current status so it can be\r
+ manipulated, and the cause and EPC registers so their original values are\r
+ captured. */\r
mfc0 k0, _CP0_CAUSE\r
addiu sp, sp, -portCONTEXT_SIZE\r
mfc0 k1, _CP0_STATUS\r
\r
- /* Also save s6 and s5 so we can use them during this interrupt. Any\r
- nesting interrupts should maintain the values of these registers\r
- across the ISR. */\r
+ /* Also save s6 and s5 so they can be used. Any nesting interrupts should\r
+ maintain the values of these registers across the ISR. */\r
sw s6, 44(sp)\r
sw s5, 40(sp)\r
sw k1, portSTATUS_STACK_LOCATION(sp)\r
\r
- /* Enable interrupts above the current priority. */\r
+ /* Prepare to enable interrupts above the current priority. */\r
srl k0, k0, 0xa\r
ins k1, k0, 10, 6\r
ins k1, zero, 1, 4\r
\r
/* If the nesting count is 0 then swap to the the system stack, otherwise\r
the system stack is already being used. */\r
- bne s6, zero, .+20\r
+ bne s6, zero, 1f\r
nop\r
\r
/* Swap to the system stack. */\r
lw sp, (sp)\r
\r
/* Increment and save the nesting count. */\r
- addiu s6, s6, 1\r
+1: addiu s6, s6, 1\r
sw s6, 0(k0)\r
\r
/* s6 holds the EPC value, this is saved after interrupts are re-enabled. */\r
/* Save the context into the space just created. s6 is saved again\r
here as it now contains the EPC value. No other s registers need be\r
saved. */\r
- sw ra, 120(s5)\r
+ sw ra, 120(s5)\r
sw s8, 116(s5)\r
sw t9, 112(s5)\r
- sw t8, 108(s5)\r
- sw t7, 104(s5)\r
+ sw t8, 108(s5)\r
+ sw t7, 104(s5)\r
sw t6, 100(s5)\r
sw t5, 96(s5)\r
sw t4, 92(s5)\r
la s6, uxInterruptNesting\r
lw s6, (s6)\r
addiu s6, s6, -1\r
- bne s6, zero, .+20\r
+ bne s6, zero, 1f\r
nop\r
\r
/* Save the stack pointer. */\r
la s6, uxSavedTaskStackPointer\r
sw s5, (s6)\r
-\r
+1:\r
.endm\r
- \r
-/******************************************************************/ \r
+\r
+/******************************************************************/\r
.macro portRESTORE_CONTEXT\r
\r
/* Restore the stack pointer from the TCB. This is only done if the\r
la s6, uxInterruptNesting\r
lw s6, (s6)\r
addiu s6, s6, -1\r
- bne s6, zero, .+20\r
+ bne s6, zero, 1f\r
nop\r
la s6, uxSavedTaskStackPointer\r
lw s5, (s6)\r
- \r
+\r
/* Restore the context. */\r
- lw s6, 8(s5)\r
+1: lw s6, 8(s5)\r
mtlo s6\r
lw s6, 12(s5)\r
mthi s6\r
\r
/* Protect access to the k registers, and others. */\r
di\r
+ ehb\r
\r
/* Decrement the nesting count. */\r
la k0, uxInterruptNesting\r
lw k0, portSTATUS_STACK_LOCATION(s5)\r
lw k1, portEPC_STACK_LOCATION(s5)\r
\r
- /* Leave the stack how we found it. First load sp from s5, then restore\r
- s5 from the stack. */\r
+ /* Leave the stack in its original state. First load sp from s5, then\r
+ restore s5 from the stack. */\r
add sp, zero, s5\r
lw s5, 40(sp)\r
- addiu sp, sp, portCONTEXT_SIZE\r
+ addiu sp, sp, portCONTEXT_SIZE\r
\r
mtc0 k0, _CP0_STATUS\r
mtc0 k1, _CP0_EPC\r
- eret \r
+ ehb\r
+ eret\r
nop\r
\r
.endm\r
/*\r
- FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. \r
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.\r
All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
the first task is being restored. */\r
#define portINITIAL_SR ( portIE_BIT | portEXL_BIT )\r
\r
+/*\r
+By default port.c generates its tick interrupt from TIMER1. The user can\r
+override this behaviour by:\r
+ 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(),\r
+ which is the function that configures the timer. The function is defined\r
+ as a weak symbol in this file so if the same function name is used in the\r
+ application code then the version in the application code will be linked\r
+ into the application in preference to the version defined in this file.\r
+ 2: Define configTICK_INTERRUPT_VECTOR to the vector number of the timer used\r
+ to generate the tick interrupt. For example, when timer 1 is used then\r
+ configTICK_INTERRUPT_VECTOR is set to _TIMER_1_VECTOR.\r
+ configTICK_INTERRUPT_VECTOR should be defined in FreeRTOSConfig.h.\r
+ 3: Define configCLEAR_TICK_TIMER_INTERRUPT() to clear the interrupt in the\r
+ timer used to generate the tick interrupt. For example, when timer 1 is\r
+ used configCLEAR_TICK_TIMER_INTERRUPT() is defined to\r
+ IFS0CLR = _IFS0_T1IF_MASK.\r
+*/\r
#ifndef configTICK_INTERRUPT_VECTOR\r
#define configTICK_INTERRUPT_VECTOR _TIMER_1_VECTOR\r
+ #define configCLEAR_TICK_TIMER_INTERRUPT() IFS0CLR = _IFS0_T1IF_MASK\r
+#else\r
+ #ifndef configCLEAR_TICK_TIMER_INTERRUPT\r
+ #error If configTICK_INTERRUPT_VECTOR is defined in application code then configCLEAR_TICK_TIMER_INTERRUPT must also be defined in application code.\r
+ #endif\r
#endif\r
\r
-/* Records the interrupt nesting depth. This starts at one as it will be\r
-decremented to 0 when the first task starts. */\r
-volatile unsigned portBASE_TYPE uxInterruptNesting = 0x01;\r
+/* Let the user override the pre-loading of the initial RA with the address of\r
+prvTaskExitError() in case is messes up unwinding of the stack in the\r
+debugger - in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */\r
+#ifdef configTASK_RETURN_ADDRESS\r
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS\r
+#else\r
+ #define portTASK_RETURN_ADDRESS prvTaskExitError\r
+#endif\r
\r
-/* Stores the task stack pointer when a switch is made to use the system stack. */\r
-unsigned portBASE_TYPE uxSavedTaskStackPointer = 0;\r
+/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task\r
+stack checking. A problem in the ISR stack will trigger an assert, not call the\r
+stack overflow hook function (because the stack overflow hook is specific to a\r
+task stack, not the ISR stack). */\r
+#if( configCHECK_FOR_STACK_OVERFLOW > 2 )\r
+\r
+ /* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for\r
+ the task stacks, and so will legitimately appear in many positions within\r
+ the ISR stack. */\r
+ #define portISR_STACK_FILL_BYTE 0xee\r
+\r
+ static const unsigned char ucExpectedStackBytes[] = {\r
+ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \\r
+ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \\r
+ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \\r
+ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \\r
+ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \\r
+\r
+ #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )\r
+#else\r
+ /* Define the function away. */\r
+ #define portCHECK_ISR_STACK()\r
+#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */\r
\r
-/* The stack used by interrupt service routines that cause a context switch. */\r
-portSTACK_TYPE xISRStack[ configISR_STACK_SIZE ] = { 0 };\r
+/*-----------------------------------------------------------*/\r
\r
-/* The top of stack value ensures there is enough space to store 6 registers on\r
-the callers stack, as some functions seem to want to do this. */\r
-const portSTACK_TYPE * const xISRStackTop = &( xISRStack[ configISR_STACK_SIZE - 7 ] );\r
\r
/*\r
* Place the prototype here to ensure the interrupt vector is correctly installed.\r
*/\r
void __attribute__( (interrupt(ipl1), vector(_CORE_SOFTWARE_0_VECTOR))) vPortYieldISR( void );\r
\r
+/*\r
+ * Used to catch tasks that attempt to return from their implementing function.\r
+ */\r
+static void prvTaskExitError( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Records the interrupt nesting depth. This is initialised to one as it is\r
+decremented to 0 when the first task starts. */\r
+volatile unsigned portBASE_TYPE uxInterruptNesting = 0x01;\r
+\r
+/* Stores the task stack pointer when a switch is made to use the system stack. */\r
+unsigned portBASE_TYPE uxSavedTaskStackPointer = 0;\r
+\r
+/* The stack used by interrupt service routines that cause a context switch. */\r
+portSTACK_TYPE xISRStack[ configISR_STACK_SIZE ] = { 0 };\r
+\r
+/* The top of stack value ensures there is enough space to store 6 registers on\r
+the callers stack, as some functions seem to want to do this. */\r
+const portSTACK_TYPE * const xISRStackTop = &( xISRStack[ configISR_STACK_SIZE - 7 ] );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/*\r
*pxTopOfStack = (portSTACK_TYPE) _CP0_GET_CAUSE();\r
pxTopOfStack--;\r
\r
- *pxTopOfStack = (portSTACK_TYPE) portINITIAL_SR; /* CP0_STATUS */\r
+ *pxTopOfStack = (portSTACK_TYPE) portINITIAL_SR;/* CP0_STATUS */\r
pxTopOfStack--;\r
\r
*pxTopOfStack = (portSTACK_TYPE) pxCode; /* CP0_EPC */\r
pxTopOfStack--;\r
\r
- *pxTopOfStack = (portSTACK_TYPE) NULL; /* ra */\r
+ *pxTopOfStack = (portSTACK_TYPE) portTASK_RETURN_ADDRESS; /* ra */\r
pxTopOfStack -= 15;\r
\r
- *pxTopOfStack = (portSTACK_TYPE) pvParameters; /* Parameters to pass in */\r
- pxTopOfStack -= 14;\r
-\r
- *pxTopOfStack = (portSTACK_TYPE) 0x00000000; /* critical nesting level - no longer used. */\r
- pxTopOfStack--;\r
+ *pxTopOfStack = (portSTACK_TYPE) pvParameters; /* Parameters to pass in. */\r
+ pxTopOfStack -= 15;\r
\r
return pxTopOfStack;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvTaskExitError( void )\r
+{\r
+ /* A function that implements a task must not exit or attempt to return to\r
+ its caller as there is nothing to return to. If a task wants to exit it\r
+ should instead call vTaskDelete( NULL ).\r
+\r
+ Artificially force an assert() to be triggered if configASSERT() is\r
+ defined, then stop here so application writers can catch the error. */\r
+ configASSERT( uxSavedTaskStackPointer == 0UL );\r
+ portDISABLE_INTERRUPTS();\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
/*\r
* Setup a timer for a regular tick. This function uses peripheral timer 1.\r
* The function is declared weak so an application writer can use a different\r
extern void vPortStartFirstTask( void );\r
extern void *pxCurrentTCB;\r
\r
+ #if ( configCHECK_FOR_STACK_OVERFLOW > 2 )\r
+ {\r
+ /* Fill the ISR stack to make it easy to asses how much is being used. */\r
+ memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );\r
+ }\r
+ #endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */\r
+\r
/* Clear the software interrupt flag. */\r
IFS0CLR = _IFS0_CS0IF_MASK;\r
\r
uxSavedTaskStackPointer = *( unsigned portBASE_TYPE * ) pxCurrentTCB;\r
vPortStartFirstTask();\r
\r
- /* Should never get here as the tasks will now be executing. */\r
+ /* Should never get here as the tasks will now be executing! Call the task\r
+ exit error function to prevent compiler warnings about a static function\r
+ not being called in the case that the application writer overrides this\r
+ functionality by defining configTASK_RETURN_ADDRESS. */\r
+ prvTaskExitError();\r
+\r
return pdFALSE;\r
}\r
/*-----------------------------------------------------------*/\r
}\r
vPortClearInterruptMaskFromISR( uxSavedStatus );\r
\r
- /* Clear timer 1 interrupt. */\r
- IFS0CLR = _IFS0_T1IF_MASK;\r
+ /* Look for the ISR stack getting near or past its limit. */\r
+ portCHECK_ISR_STACK();\r
+\r
+ /* Clear timer interrupt. */\r
+ configCLEAR_TICK_TIMER_INTERRUPT();\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
unsigned portBASE_TYPE uxSavedStatusRegister;\r
\r
- asm volatile ( "di" );\r
+ __builtin_disable_interrupts();\r
uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01;\r
/* This clears the IPL bits, then sets them to\r
configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called\r
/*\r
- FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. \r
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.\r
All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
\r
/*******************************************************************/\r
\r
- .set noreorder\r
+ .set noreorder\r
.set noat\r
- .ent vPortYieldISR\r
+ .ent vPortYieldISR\r
\r
vPortYieldISR:\r
\r
/* Make room for the context. First save the current status so it can be\r
manipulated, and the cause and EPC registers so thier original values are\r
captured. */\r
- mfc0 k0, _CP0_CAUSE\r
- addiu sp, sp, -portCONTEXT_SIZE\r
+ addiu sp, sp, -portCONTEXT_SIZE\r
mfc0 k1, _CP0_STATUS\r
\r
- /* Also save s6 and s5 so we can use them during this interrupt. Any\r
- nesting interrupts should maintain the values of these registers\r
- across the ISR. */\r
+ /* Also save s6 and s5 so they can be used. Any nesting interrupts should\r
+ maintain the values of these registers across the ISR. */\r
sw s6, 44(sp)\r
sw s5, 40(sp)\r
sw k1, portSTATUS_STACK_LOCATION(sp)\r
\r
- /* Interrupts above the kernel priority are going to be re-enabled. */\r
- srl k0, k0, 0xa\r
- ins k1, k0, 10, 6\r
+ /* Prepare to re-enabled interrupt above the kernel priority. */\r
+ ins k1, zero, 10, 6\r
+ ori k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
ins k1, zero, 1, 4\r
\r
/* s5 is used as the frame pointer. */\r
after interrupts are enabled. */\r
mfc0 s6, _CP0_EPC\r
\r
- /* Re-enable interrupts. */\r
+ /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
mtc0 k1, _CP0_STATUS\r
\r
/* Save the context into the space just created. s6 is saved again\r
here as it now contains the EPC value. */\r
- sw ra, 120(s5)\r
+ sw ra, 120(s5)\r
sw s8, 116(s5)\r
sw t9, 112(s5)\r
- sw t8, 108(s5)\r
- sw t7, 104(s5)\r
+ sw t8, 108(s5)\r
+ sw t7, 104(s5)\r
sw t6, 100(s5)\r
sw t5, 96(s5)\r
sw t4, 92(s5)\r
sw s7, 48(s5)\r
sw s6, portEPC_STACK_LOCATION(s5)\r
/* s5 and s6 has already been saved. */\r
- sw s4, 36(s5)\r
+ sw s4, 36(s5)\r
sw s3, 32(s5)\r
sw s2, 28(s5)\r
sw s1, 24(s5)\r
is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
raise the IPL value and never lower it. */\r
di\r
+ ehb\r
mfc0 s7, _CP0_STATUS\r
- ins s7, $0, 10, 6\r
+ ins s7, zero, 10, 6\r
ori s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
\r
/* This mtc0 re-enables interrupts, but only above\r
configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
mtc0 s6, _CP0_STATUS\r
+ ehb\r
\r
/* Clear the software interrupt in the core. */\r
mfc0 s6, _CP0_CAUSE\r
ins s6, zero, 8, 1\r
mtc0 s6, _CP0_CAUSE\r
+ ehb\r
\r
/* Clear the interrupt in the interrupt controller. */\r
la s6, IFS0CLR\r
\r
/* Clear the interrupt mask again. The saved status value is still in s7. */\r
mtc0 s7, _CP0_STATUS\r
+ ehb\r
\r
/* Restore the stack pointer from the TCB. */\r
la s0, pxCurrentTCB\r
\r
/* Protect access to the k registers, and others. */\r
di\r
+ ehb\r
\r
/* Set nesting back to zero. As the lowest priority interrupt this\r
interrupt cannot have nested. */\r
lw k0, portEPC_STACK_LOCATION(sp)\r
\r
/* Remove stack frame. */\r
- addiu sp, sp, portCONTEXT_SIZE\r
+ addiu sp, sp, portCONTEXT_SIZE\r
\r
mtc0 k1, _CP0_STATUS\r
mtc0 k0, _CP0_EPC\r
+ ehb\r
eret\r
nop\r
\r
#endif\r
\r
/*-----------------------------------------------------------\r
- * Port specific definitions. \r
+ * Port specific definitions.\r
*\r
* The settings in this file configure FreeRTOS correctly for the\r
* given hardware and compiler.\r
/* Hardware specifics. */\r
#define portBYTE_ALIGNMENT 8\r
#define portSTACK_GROWTH -1\r
-#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) \r
+#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
/*-----------------------------------------------------------*/\r
\r
/* Critical section management. */\r
#define portALL_IPL_BITS ( 0x3fUL << portIPL_SHIFT )\r
#define portSW0_BIT ( 0x01 << 8 )\r
\r
-/* This clears the IPL bits, then sets them to \r
-configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if \r
-configASSERT() is defined to ensure an assertion handler does not inadvertently \r
-attempt to lower the IPL when the call to assert was triggered because the IPL \r
-value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR\r
+/* This clears the IPL bits, then sets them to\r
+configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if\r
+configASSERT() is defined to ensure an assertion handler does not inadvertently\r
+attempt to lower the IPL when the call to assert was triggered because the IPL\r
+value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR\r
safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are\r
those that end in FromISR. FreeRTOS maintains a separate interrupt API to\r
ensure API function and interrupt entry is as fast and as simple as possible. */\r
ulStatus = _CP0_GET_STATUS(); \\r
\\r
/* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \\r
- if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \\r
+ if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \\r
{ \\r
ulStatus &= ~portALL_IPL_BITS; \\r
_CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \\r
_CP0_SET_CAUSE( ulCause ); \\r
}\r
\r
-#ifdef configASSERT\r
- #define portCURRENT_INTERRUPT_PRIORITY ( ( _CP0_GET_STATUS() & portALL_IPL_BITS ) >> portIPL_SHIFT )\r
- #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( portCURRENT_INTERRUPT_PRIORITY <= configMAX_SYSCALL_INTERRUPT_PRIORITY )\r
-#endif /* configASSERT */\r
-\r
+#define portCURRENT_INTERRUPT_PRIORITY ( ( _CP0_GET_STATUS() & portALL_IPL_BITS ) >> portIPL_SHIFT )\r
+#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( portCURRENT_INTERRUPT_PRIORITY <= configMAX_SYSCALL_INTERRUPT_PRIORITY )\r
\r
-#define portNOP() asm volatile ( "nop" )\r
+#define portNOP() __asm volatile ( "nop" )\r
\r
/*-----------------------------------------------------------*/\r
\r
#include "task.h"\r
#include <stdio.h>\r
\r
+#ifdef __GNUC__\r
+ #include "mmsystem.h"\r
+#else\r
+ #pragma comment(lib, "winmm.lib")\r
+#endif\r
+\r
#define portMAX_INTERRUPTS ( ( unsigned long ) sizeof( unsigned long ) * 8UL ) /* The number of bits in an unsigned long. */\r
#define portNO_CRITICAL_NESTING ( ( unsigned long ) 0 )\r
\r
static unsigned long prvProcessYieldInterrupt( void );\r
static unsigned long prvProcessTickInterrupt( void );\r
\r
+/*\r
+ * Called when the process exits to let Windows know the high timer resolution\r
+ * is no longer required.\r
+ */\r
+static BOOL WINAPI prvEndProcess( DWORD dwCtrlType );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* The WIN32 simulator runs each task in a thread. The context switching is\r
\r
static DWORD WINAPI prvSimulatedPeripheralTimer( LPVOID lpParameter )\r
{\r
-portTickType xMinimumWindowsBlockTime = ( portTickType ) 20;\r
+portTickType xMinimumWindowsBlockTime;\r
+TIMECAPS xTimeCaps;\r
+\r
+ /* Set the timer resolution to the maximum possible. */\r
+ if( timeGetDevCaps( &xTimeCaps, sizeof( xTimeCaps ) ) == MMSYSERR_NOERROR )\r
+ {\r
+ xMinimumWindowsBlockTime = ( portTickType ) xTimeCaps.wPeriodMin;\r
+ timeBeginPeriod( xTimeCaps.wPeriodMin );\r
+\r
+ /* Register an exit handler so the timeBeginPeriod() function can be\r
+ matched with a timeEndPeriod() when the application exits. */\r
+ SetConsoleCtrlHandler( prvEndProcess, TRUE );\r
+ }\r
+ else\r
+ {\r
+ xMinimumWindowsBlockTime = ( portTickType ) 20;\r
+ }\r
\r
/* Just to prevent compiler warnings. */\r
( void ) lpParameter;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static BOOL WINAPI prvEndProcess( DWORD dwCtrlType )\r
+{\r
+TIMECAPS xTimeCaps;\r
+\r
+ ( void ) dwCtrlType;\r
+\r
+ if( timeGetDevCaps( &xTimeCaps, sizeof( xTimeCaps ) ) == MMSYSERR_NOERROR )\r
+ {\r
+ /* Match the call to timeBeginPeriod( xTimeCaps.wPeriodMin ) made when\r
+ the process started with a timeEndPeriod() as the process exits. */\r
+ timeEndPeriod( xTimeCaps.wPeriodMin );\r
+ }\r
+\r
+ return pdPASS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
{\r
xThreadState *pxThreadState = NULL;\r