沁恒技术支持,请教关于CH365伪中断频率太高的问题

这个问题电话联系过你们,但没有回音,我这里详细描述一下,望帮助分析原因:

现在PCI卡驱动程序里中断为1.5ms,原来应用程序直接伪中断回调函数,理论上也是1.5ms进入一次(伪中断里需要读写数据,而且不能太慢),试验下来,在直接安装的windows上运行都没问题,不死机,但在ghost系统的机子上,某些机子也永远不会死,但某些机子上必然死机,后来将伪中断屏蔽掉(不设置伪中断例程),只试驱动程序里的中断,原来肯定死机的不会死机。 后来咨询贵单位技术人员,认为可能是伪中断频率太高,说是小于5ms容易死机,现在我将连接驱动程序和应用程序的那个动态库文件CH365DLL.DLL里处理中断的线程进行处理,每成功读取10次中断才执行一次伪中断例程,这样驱动程序实际中断还是1.5ms,但伪中断实际上是1.5*10=15ms执行一次,但原来肯定死的机器上,有些机器还是出现死机情况,有时是出现蓝屏,显示IRQL_NOT_LESS_OR EQUAL,机器重装系统了也没用。 恳请贵公司技术人员分析一下可能的原因。 注明: 1、中断预处理命令我一直是屏蔽掉的,包括驱动原代码里中断处理里for ( mByte = 0; mByte < 2; ++mByte ) { // 检查两个中断命令缓冲区,这一段代码全部屏蔽了) 2、伪中断里处理时间很短,远远小于1ms。

附代码: 1、中间CH365DLL.DLL文件里中断线程处理,原代码经过修改 ULONG WINAPI dllInterruptThread( // 中断模拟线程,每个需要中断功能的CH365设备都具有一个线程 LPVOID iParameter ) { HANDLE dllHandleOverlap; // CH365设备句柄,可以执行重叠操作 HANDLE mEvent; BOOL mResult; ULONG mIndex, mLength; ULONG mInterruptCount;//中断次数计数:决定应用程序级伪中断的间隔时间(不能小于5ms,否则在某些计算机上容易死机) mWIN32_COMMAND mCommand; OVERLAPPED mOverlapped; mIndex = (ULONG)iParameter; // CH365设备序号 dllHandleOverlap = CreateFile( dllDeviceName[ mIndex ], GENERIC_READ | GENERIC_WRITE, // 打开设备,支持重叠操作 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if ( dllHandleOverlap != INVALID_HANDLE_VALUE ) { // 打开设备成功 mEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); // 初始化完成事件 mInterruptCount=0;//初始化计数 while ( dllIntRoutine[ mIndex ] ) { // 等待中断直到取消 mLength = sizeof( mWIN32_COMMAND ); mCommand.mFunction = mFuncWaitInterrupt; // 等待中断事件 mCommand.mAddress = NULL; mCommand.mLength = 0; mOverlapped.Internal = 0; mOverlapped.InternalHigh = 0; mOverlapped.Offset = 0; mOverlapped.OffsetHigh = 0; mOverlapped.hEvent = mEvent; ResetEvent( mEvent ); // 初始化完成事件 mResult = DeviceIoControl( dllHandleOverlap, IOCTL_CH365_COMMAND, &mCommand, mLength, &mCommand, mLength, &mLength, &mOverlapped ); if ( mResult == FALSE && GetLastError() == ERROR_IO_PENDING ) // 操作未完成,即暂时无中断 mResult = GetOverlappedResult( dllHandleOverlap, &mOverlapped, &mLength, TRUE ); // 等待中断 if ( mResult && dllIntRoutine[ mIndex ] ) { mInterruptCount++; if(mInterruptCount>=10)//本应用驱动程序级中断间隔时间1.5ms,则伪中断间隔1.5*10=15ms { mInterruptCount=0; dllIntRoutine[ mIndex ](); // 发生中断事件则调用中断服务程序 } } if ( mResult == FALSE && dllIntRoutine[ mIndex ] ) Sleep( 5 ); // 出错则延时5毫秒 } CloseHandle( mEvent ); CloseHandle( dllHandleOverlap ); // 关闭句柄 } dllIntThreadId[ mIndex ] = 0; ExitThread( 0 ); // 退出 return( 0 ); }

2、应用程序CH365初始化(屏蔽了中断预处理命令) void InitCH365() { UCHAR cByte;

//1) 先加载DLL if ( LoadLibrary( "CH365DLL.DLL" ) == NULL )//FreeLibrary { AfxMessageBox("加载CH365DLL.DLL失败,可能未安装到系统中,\r\n\r\n请重新安装软件!",16,0);// 加载DLL失败,可能未安装到系统中 exit(0); }

//2) 选择打开CH365设备0,打开存储器和中断 Device_Number=0; if ( CH365mOpenDevice(Device_Number, TRUE, TRUE ) == INVALID_HANDLE_VALUE ) { AfxMessageBox("打开板卡设备失败,\r\n\r\n请确认板卡正确并连接可靠!",16,0); exit(0); }

//3) 通过DLL来调用版本号 //printf( "= %02X \n", CH365GetDrvVersion() );

//4) 通过DLL来调用系统自动分配的I/O基地址 if ( CH365mGetIoBaseAddr( Device_Number,&mIoBase ) == FALSE ) { AfxMessageBox("系统自动分配I/O基地址失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); }

//5) 通过DLL来调用系统自动分配的存储器基地址 if (CH365mGetMemBaseAddr(Device_Number,&mMemBase) ==FALSE) { AfxMessageBox("系统自动分配Memory基地址失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); }

//6) 选择A15作为SCL if ( CH365mReadIoByte(Device_Number,&mIoBase->mCh365IoCtrl,&cByte) == FALSE ) // 检查A15的状态,因为当A15为高电平时I2C不工作 { AfxMessageBox("检查A15的状态失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); } if ( cByte & 0x01 ) CH365mWriteIoByte(Device_Number,&mIoBase->mCh365IoCtrl,(UCHAR)(cByte & 0xFE)); // 设置A15=0,也可由数据线D0下拉电阻进行模式设置

if ( CH365mWriteIoByte(Device_Number,&mIoBase->mCh365I2cCtrl,0) == FALSE ) // 选择A15作为SCL,默认值 { AfxMessageBox("选择SCL失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); } //CH365mWriteIoByte(Device_Number,&mBaseAddr->mCh365I2cCtrl,0x80); // 选择SYS_EX作为SCL

//7) 自动检测CH365所用的中断号 if ( CH365mSetIntLine(Device_Number, mCH365_INT_LINE_AUTO ) == FALSE ) { AfxMessageBox("打开板卡中断失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); }

//8) 调用中断号 if ( CH365mGetIntLine(Device_Number, &mIntLine ) == FALSE ) { AfxMessageBox("系统调用板卡中断号失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); }

//9) 中断命令设定,CH365的WDM驱动程序中支持两条中断预处理命令 //通过使用CH365mWriteIntCommand( // 写入中断命令缓冲区 // ULONG iIndex, // 指定CH365设备序号 // mPWIN32_COMMAND iCommand, // 指向作为中断命令的命令结构 // ULONG iCmdIndex ) // 中断命令序号,为1或者2 // 假定在系统响应中断时设定A0-A15的状态为0x08000,可以撤消外部电路的中断请求 if (mIntLine )// 已经启用中断 { // mWIN32_COMMAND mCommand; // mCommand.mFunction = mFuncWriteIoWord;//发送I/O口写字命令,命令代码,该命令在硬件中断时由驱动程序执行 // mCommand.mAddress = & mIoBase ->mCh365IoPort[0x00]; //设定A0-A15的地址寄存器,操作地址 // mCommand.mLength = 1; //数据长度设定,操作数据长度,以字节计算 // mCommand.mBuffer[0] = 0x00; //要写的数据 // mCommand.mBuffer[1] = 0x00; // A15=1,假定:在外部电路的中断逻辑上,将A15置为高电平可以撤消中断 // if ( CH365mWriteIntCommand(Device_Number, &mCommand, 1 ) == FALSE ) // { // AfxMessageBox("设置中断预处理命令失败,请重新安装板卡驱动程序!",16,0); // //exit(0); // } if ( CH365mSetIntRoutine(Device_Number, InterruptEvent ) == FALSE ) { AfxMessageBox("设置中断服务子程序失败,\r\n\r\n请重新安装板卡驱动程序!",16,0); exit(0); } }

}

伪中断服务例程 //中断服务子程序(一帧数据来一个中断) void CALLBACK InterruptEvent( void ) {

...向驱动程序读写数据

}

出现蓝屏很可能是你改的驱动造成的,一般驱动里面有BUG就会蓝屏,所以驱动的代码不建议随便改动!中断服务InterruptEvent调用的哪些函数?回调函数里面最好不要调用阻塞的函数!你有源代码的话,你可以这样试试,在你的应用程序里去创建dllInterruptThread,而不是DLL里面。


蓝屏不应该是驱动修改造成,因为伪中断只做一个状态监视(读取驱动里的一组数据),屏蔽掉就不出现死机/蓝屏情况了;至于dllInterruptThread倒是可以放到应用程序级试试,但我们认为不应该是因为伪中断处理阻塞问题,因为我们将伪中断里所有处理都屏蔽掉(只留一个空壳),还是会死机,因此我们怀疑会不会是dll里的dllInterruptThread线程处理问题,我看你们把它设为最高级别TIME_CRITICAL级,里面是一死循环,每个循环检测一次中断状态,如果出现错误延时5ms处理,这方面在中断频率较高时是不是可能有问题。 因为我们还一款硬件,中断是5ms,不容易死(至少目前没有发现过)。


驱动里面的函数调用是跟IRQL有关的,有的函数要求IRQL <= DISPATCH_LEVEL等等,不然就会出现IRQL_NOT_LESS_OR EQUAL的蓝屏错误。dllInterruptThread放到应用程序里面,可以省了回调函数,或者不设置线程的优先级,我个人觉得可以解决你的问题。你说的最高级别TIME_CRITICAL级有可能会出现这种现象,在任务管理器中任意改变优先级会提示“导致不希望发生的结果,包括系统不稳定”!


建议不要在BBS 上询问涉及有权限的源码问题,如有相关问题请发 tech@wch.cn 会有专人处理。


只有登录才能回复,可以选择微信账号登录