Click here to Skip to main content
13,050,606 members (92,358 online)
Rate this:
Please Sign up or sign in to vote.
See more:
I have an application that I need to run at a 10mSec rate (100hz) on a Windows 7/32 bit computer (that will also be running other applications at the same time). I know that windows is not an RTOS, but we are sort of stuck with a requirement to use it. This interrupt can have some minimally late (100uSec) responses, but must not drift over a prolonged time. I have a program where I have loaded and used the NtSetTimerResolution to set the timers to 10msec resolution, and then created a timer using the CreateTimerQueue/CreateTimereQueueTimer functions with a callback routine that toggles a GPIO pin (for the time being) - this produces the expected square wave, so long as I am not doing anything else with the system. When I start a couple of other processes, the accuracy of my square wave goes out the window. Is there any way to get a higher priority level on the timer interrupt (or is there another timer that I can use) that will produce a more stable output (perhaps the SMI)? My code is below, and is built using the x86 checked build environment of the Windows DDK, and run from a command shell with administrator rights:

Simple console test app for a 10mSec timer interrupt service
Administrator Mode

#include     <windows.h>
#include     <winioctl.h>
#include     <stdio.h>
#include     <string.h>
#include     <stdlib.h>
#include     <conio.h>
#include     <strsafe.h>
#include     <stdlib.h>
#include     <stdio.h>
#include     <winsock2.h>
#include     <mswsock.h>
#pragma warning(disable:4127)   // condition expression is constant
FARPROC pNtQueryTimerResolution;
FARPROC pNtSetTimerResolution;
static  HANDLE    NTDLLModuleHandle;
static  HINSTANCE hInpOutDll;
typedef         void  (   __stdcall  *lpOut32 )( short , short );
typedef  short        (   __stdcall  *lpInp32 )( short );
typedef  BOOL         (   __stdcall  *lpIsInpOutDriverOpen )( void );
//Some global function pointers (messy but fine for an example)
lpOut32              gfpOut32;
lpInp32              gfpInp32;
lpIsInpOutDriverOpen gfpIsInpOutDriverOpen;

void CALLBACK TimerProc(void* lpParameter,
    BOOLEAN TimerOrWaitFired);
VOID  __cdecl    main( void )
    ULONG ulMinRes = 0;
    ULONG ulMaxRes = 0;
    ULONG ulCurRes = 0;
    HANDLE phNewQueue;
    HANDLE phNewTimer;
    phNewQueue        = CreateTimerQueue( );
    NTDLLModuleHandle = LoadLibrary( "NTDLL.DLL" );
    if( NULL == NTDLLModuleHandle )
    // Get the function pointers,
    pNtQueryTimerResolution = GetProcAddress( NTDLLModuleHandle, "NtQueryTimerResolution" );
    pNtSetTimerResolution = GetProcAddress( NTDLLModuleHandle, "NtSetTimerResolution" );
    if( ( pNtQueryTimerResolution == NULL ) || ( pNtSetTimerResolution == NULL ) )
        printf( "unable to link to ddl\n\n\n\n\n\n" );
    pNtQueryTimerResolution( &ulMinRes, &ulMaxRes, &ulCurRes );
    printf( "MMR:  %d   %d   %d\n", ulMinRes, ulMaxRes, ulCurRes );
    ulMaxRes = 100000;
    pNtSetTimerResolution( ulMaxRes, TRUE, &ulCurRes );
    pNtQueryTimerResolution( &ulMinRes, &ulMaxRes, &ulCurRes );
    printf( "MMR:  %d   %d   %d\n", ulMinRes, ulMaxRes, ulCurRes );
    //Dynamically load the DLL at runtime (not linked at compile time)
    hInpOutDll = LoadLibrary( "InpOut32.DLL" );
    if( hInpOutDll != NULL )
        gfpOut32 = ( lpOut32 )GetProcAddress( hInpOutDll, "Out32" );
        gfpInp32 = ( lpInp32 )GetProcAddress( hInpOutDll, "Inp32" );
            = ( lpIsInpOutDriverOpen )GetProcAddress( hInpOutDll, "IsInpOutDriverOpen" );
        if( gfpIsInpOutDriverOpen( ) )
            gfpOut32( 0xA01, 0x00 );
            printf( "unable to create timer system\n\n\n\n\n\n" );
    CreateTimerQueueTimer( &phNewTimer, phNewQueue, TimerProc, NULL, 0, 10,
                       WT_EXECUTEINTIMERTHREAD );
        Sleep( 1 );
    } while( TRUE );
void CALLBACK TimerProc(void* lpParameter,
    BOOLEAN TimerOrWaitFired)
    WORD wData;
    UNREFERENCED_PARAMETER  ( lpParameter );
    wData = gfpInp32( 0xA00 );
    gfpOut32( 0xA00, wData );
Posted 23-May-12 14:01pm
Updated 24-May-12 4:29am
TRK3 23-May-12 21:01pm
Added code tags.

I don't think you have any guarantees under windows about latency once you relinquish the processor. (Unless somebody else knows some trick I'm not aware of.)

Do you have to run this on a Windows platform?
lewax00 24-May-12 11:03am
You can set a program's priority to real time in Windows.
Richard MacCutchan 24-May-12 10:39am
You and TRK3 are both correct: Windows is not a real-time OS so it makes no guarantees about timings. If you want guaranteed timer resolution then you need some other operating system. Even if you connected an external timer to your system there is still no guarantee that Windows would service it at the required intervals.

1 solution

Rate this: bad
Please Sign up or sign in to vote.

Solution 1

I don't know about the accuracy of the timer, but you can use SetThreadPriority to get the closest thing to true real time on Windows like so:
HANDLE hThread = GetCurrentThread(void);

(from here[^])

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web02 | 2.8.170713.1 | Last Updated 24 May 2012
Copyright © CodeProject, 1999-2017
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100