gpt4 book ai didi

windows - 需要产生稳定的 10mSec 中断

转载 作者:可可西里 更新时间:2023-11-01 14:19:20 25 4
gpt4 key购买 nike

我有一个应用程序需要在 Windows 7/32 位计算机上以 10 毫秒的速率 (100hz) 运行(同时还会运行其他应用程序)。此中断可以有一些最低限度的延迟 (100uSec) 响应,但不能长时间漂移。我有一个程序,我在其中加载并使用 NtSetTimerResolution 将计时器设置为 10 毫秒分辨率,然后使用 CreateTimerQueue/CreateTimereQueueTimer 函数创建了一个计时器,并带有一个切换 GPIO 引脚的回调例程(暂时) - 这会产生预期的方波,只要我不对系统做任何其他事情。当我开始其他几个过程时,我的方波的准确性超出了范围。有什么方法可以在定时器中断上获得更高的优先级(或者我可以使用另一个定时器),从而产生更稳定的输出(可能是 SMI)?我的代码如下,是使用 Windows DDK 的 x86 检查构建环境构建的,并从具有管理员权限的命令 shell 运行:

/*

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 );
}

最佳答案

您可以使用 SetThreadPriority优先考虑关键线程。在这种情况下,您可能需要显式创建一个线程并使用 CreateWaitableTimerEx , SetWaitableTimerEx , 和 WaitForSingleObjectEx而不是 CreateTimerQueueTimer .确保关键线程永远不会在等待之间花费太长时间执行,否则 Windows 可能会停止正常工作。

如果最大延迟为 100 微秒,这可能还不够。您可能需要使用 SetPriorityClass 将进程优先级设置为 REALTIME_PRIORITY_CLASS功能,但要确保您的程序永远不会长时间占用 CPU,否则 Windows 将停止正常工作。特别是,如果你的程序挂了,整个操作系统都会挂掉;在这种情况下,除非关闭电源,否则无法停止程序。

即使这样可能还不够。 Windows 不是实时操作系统,它可能无法按照您的要求执行。

关于windows - 需要产生稳定的 10mSec 中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10729418/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com