superrobust
驱动牛犊
驱动牛犊
  • 注册日期2003-01-04
  • 最后登录2007-08-07
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
阅读:1912回复:7

9052中断蓝屏的问题请教[50分](急)

楼主#
更多 发布于:2004-03-28 00:56
大概原来也有朋友遇到同样的问题,请指点一下。感觉就差一层
窗户纸,但是不得其入。为了以后也方便别人解决类似问题,我把
我的问题描述的详细些。请有经验的朋友耐心帮我看一下,不胜
感激。

1,问题的现象:
对pld片子编程产生时钟中断(大约每两秒一次)后,机器重启并蓝屏显示
STOP:0X00000D1(0X00000004,0X00000002,0X00000000,0XBFE476F2)
DRIVER_IRQL_NOT_LESS_OR_EQUAL

2,硬件连接:32MHz晶振时钟输入到PLD芯片中,在内部分频后将2Hz的时钟输出连接到9052的LINTi1引脚上作为外部中断输入。
EEPROM中把INTCSR寄存器的值设为0。

3,主要想做的事情:中断到达的时候,INTCSR的第2位status位应该会从0变作1,想把这时候的INTCSR寄存器的值读出并保存,返回给应用程序。

4,软件功能描述:应用程序分两个线程,主线程创建事件对象,并把句柄hEvent通过DeviceIoControl()函数传给驱动程序,之后主线程创建系统服务线程ServiceThread,等待键盘输入Enter后退出。
ServiceThread等待驱动把事件对象设为已通知状态后,通readfile()读取中断来临时INTCSR的值。

5,应用程序的部分代码:
...
DWORD WINAPI ServiceThread(PVOID hEvent)
{

while (TRUE)
{
WaitForSingleObject(hEvent, INFINITE);
printf("New event:\n");
doRead(); //从驱动中读取INTCSR的值
}
return 0;
}

int __cdecl main(int argc, char *argv[])
{
...
// 创建一个事件对象,把句柄传给驱动

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (! DeviceIoControl(
hDevice,
IOCTL_SET_NOTIFICATION_EVENT,
&hEvent,
sizeof(hEvent),
NULL,
0,
&nRet,
NULL
) )
{
printf("Ioctl failed: %x\n", GetLastError());
exit(1);
}

// 创建一个线程等待事件对象
CreateThread(0, 0x1000, ServiceThread,(PVOID)    hEvent, 0, &Tid);
//当键盘输入Enter后退出
printf("press return to exit . . .\n");
while (TRUE)
if (_getche() == 0xd)
break;
CloseHandle(hEvent);
CloseHandle(hDevice);
return 0;
}

6,驱动程序的部分代码:
class Pci9052Device : public KPnpDevice
{...
protected:
    ULONG    m_InterruptValue;  //用来保存INTCSR的值
    KEvent*  m_pEvent;
...
}

Pci9052Device::Pci9052Device(PDEVICE_OBJECT Pdo, ULONG Unit) :KPnpDevice(Pdo, &Pci9052Device_Guid)
{...
#define INTCSR 0x4C//定义INTCSR偏移量
m_InterruptValue = 0; //初始化变量
 ...
}

NTSTATUS Pci9052Device::OnStartDevice(KIrp I)
{...
m_pEvent = NULL;
m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);

//允许PCI中断,使能lint1,active状态为高电平,边缘触发中断.
m_IoPortRange0.outd(INTCSR,0x143);
 ...
}

NTSTATUS Pci9052Device::OnStopDevice(KIrp I)
{...

m_IoPortRange0.outd(INTCSR,0); //禁止PCI中断和LINTi1中断
m_Irq.Disconnect();
Invalidate();
 ...
}

NTSTATUS Pci9052Device::OnRemoveDevice(KIrp I)
{...
m_IoPortRange0.outd(INTCSR,0);
m_Irq.Disconnect();
Invalidate();
 ...
}

NTSTATUS Pci9052Device::DeviceControl(KIrp I)
{
    I.Information() = 0;
    switch (I.IoctlCode())
    {
    case IOCTL_SET_NOTIFICATION_EVENT:
        {
HANDLE hEvent = *(HANDLE*I.IoctlBuffer();
if (m_pEvent)
delete m_pEvent;
m_pEvent = new (NonPagedPool) KEvent(hEvent, OBJECT_TYPE_ALL_ACCESS);
return I.Complete(STATUS_SUCCESS);
}
break;
default:
return I.Complete(STATUS_INVALID_PARAMETER);
}
}

BOOLEAN Pci9052Device::Isr_Irq(void)
{

ULONG status;
status = m_IoPortRange0.ind(INTCSR);
//判断INTCSR的第2位是否变为1,如果是,说明是来自9052的中断
if ((status & 0x4) == 0)
{
return FALSE;
}
m_InterruptValue = status;//保存此时INTCSR的值

//禁止LINTi1中断
m_IoPortRange0.outd(INTCSR, 0x140);
//清除LINTi1中断
m_IoPortRange0.outd(INTCSR, 0x543);

//调用DPC例程
if (!m_DpcFor_Irq.Request(NULL, NULL))
{
}
return TRUE;
}

VOID Pci9052Device::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
//把事件设为已通知状态
m_pEvent->Set();
//重新使能LINTi1中断
m_IoPortRange0.outd(INTCSR, 0x143);
...
}

NTSTATUS Pci9052Device::Read(KIrp I)
{
        ...
NTSTATUS status = STATUS_SUCCESS;
ULONG INTStatus = m_InterruptValue;
//下面把INTCSR的值返回给应用程序的ServiceThread线程
KMemory Mem(I.Mdl());
PULONG pBuffer = (PULONG)                 Mem.MapToSystemSpace();                        
*pBuffer = INTStatus;
ULONG   dwTotalSize = I.ReadSize(CURRENT);
ULONG   dwBytesRead = dwTotalSize;
I.Information() = dwBytesRead;
//重新把事件设为未通知状态
m_pEvent->Reset();
return I.PnpComplete(this, status);
}


我的邮箱:superrobust@hotmail.com

最新喜欢:

mapoflmapofl
everything is developing
mydrive
驱动牛犊
驱动牛犊
  • 注册日期2001-06-21
  • 最后登录2004-05-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-03-28 11:06
好像在你初始化m_pEvent之前,就已经有中断过来,使用了m_pEvent,从而引起死机。
superrobust
驱动牛犊
驱动牛犊
  • 注册日期2003-01-04
  • 最后登录2007-08-07
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-03-28 13:13
mydrive兄
是不是CPU接收到中断后直接把控制交给了驱动中的ISR例程。
我设计的硬件中,外部时钟中断一直是在产生的。

那这样是否意味着要在ISR中对m_pEvent进行初始化


everything is developing
mydrive
驱动牛犊
驱动牛犊
  • 注册日期2001-06-21
  • 最后登录2004-05-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-03-28 13:47
你可以初始化m_pEvent以后,再打开中断屏蔽。
superrobust
驱动牛犊
驱动牛犊
  • 注册日期2003-01-04
  • 最后登录2007-08-07
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-03-28 13:55
具体怎么做?

我是在OnStartdevice()例程中先把m_pEvent初始化为NULL,
然后开中断的。 但就是这样出的问题
everything is developing
mydrive
驱动牛犊
驱动牛犊
  • 注册日期2001-06-21
  • 最后登录2004-05-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-03-28 14:11
在你的IOCTL_SET_NOTIFICATION_EVENT的处理程序中,先初始化m_pEvent,然后开中断。不要在OnStartdevice()中开中断。
superrobust
驱动牛犊
驱动牛犊
  • 注册日期2003-01-04
  • 最后登录2007-08-07
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-03-28 15:24
谢谢mydriver兄
我准备再试试

还有一个问题:
我发现9052自动把INTCSR中LINTi1和LINTi2的status位设成了
active,这两位是不可写的。 那么中断来的时候我该如何判断是否为LINTi1的中断?
everything is developing
superrobust
驱动牛犊
驱动牛犊
  • 注册日期2003-01-04
  • 最后登录2007-08-07
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-03-28 20:20
再次感谢mydrive,问题算是解决了。

但是我发现在INTCSR中disable LINTi1的话,status位总是active
的。LINTi2也是一样。 但是如果Enable LINTi1,status位会变为
0。不知道别人做的是不是一样。
everything is developing
游客

返回顶部