Windows 7/32 ビット コンピューターで 10 ミリ秒 (100hz) の速度で実行する必要があるアプリケーションがあります (同時に他のアプリケーションも実行されます)。この割り込みには、最小限の遅延 (100uSec) の応答が含まれる可能性がありますが、長時間ドリフトしてはなりません。NtSetTimerResolution を読み込んで使用してタイマーを 10 ミリ秒の解像度に設定し、CreateTimerQueue/CreateTimereQueueTimer 関数を使用して GPIO ピンを切り替えるコールバック ルーチンを使用してタイマーを作成したプログラムがあります (当面の間)。システムで他に何もしていない限り、予想される方形波。他のいくつかのプロセスを開始すると、方形波の精度が限界に達します。より安定した出力 (おそらく SMI) を生成するタイマー割り込み (または使用できる別のタイマー) でより高い優先度レベルを取得する方法はありますか? 私のコードは以下で、Windows DDK の x86 チェック ビルド環境を使用してビルドされ、管理者権限でコマンド シェルから実行されます。
/*
Abstract:
Simple console test app for a 10mSec timer interrupt service
Enviroment:
Administrator Mode
*/
/* INCLUDES */
#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);
// MAIN
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 )
{
return;
}
// 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" );
return;
}
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" );
gfpIsInpOutDriverOpen
= ( lpIsInpOutDriverOpen )GetProcAddress( hInpOutDll, "IsInpOutDriverOpen" );
if( gfpIsInpOutDriverOpen( ) )
{
gfpOut32( 0xA01, 0x00 );
}
else
{
printf( "unable to create timer system\n\n\n\n\n\n" );
return;
}
}
CreateTimerQueueTimer( &phNewTimer, phNewQueue, TimerProc, NULL, 0, 10,
WT_EXECUTEINTIMERTHREAD );
do
{
Sleep( 1 );
} while( TRUE );
}
void CALLBACK TimerProc(void* lpParameter,
BOOLEAN TimerOrWaitFired)
{
WORD wData;
UNREFERENCED_PARAMETER ( lpParameter );
UNREFERENCED_PARAMETER ( TimerOrWaitFired );
wData = gfpInp32( 0xA00 );
wData++;
gfpOut32( 0xA00, wData );
}