• 多个设备共享同一个硬件中断


    硬件中断线总是有限的,我们可能需要在已有的系统上做一些扩展,比如将串口扩展成好几个,有些硬件本身就设计成多个设备共享一条中断线,比如我的系统中两个串口就共享同一个CPU中断,任何一个串口发生中断以后都会触发CPU的同一条中断线,需要判断别的寄存器来确定是哪个串口发生了什么中断。
    我们可以在OAL中分析各个中断源,然后返回不同的SYSINTR值,但这种做法扩展性不好。例如,OAL中设值某个中断源最多会产生三个SYSINTR,但以后扩展成了四个设备,有一个设备就无法正常工作了。

    WINCE引入了可装载中断处理例程的概念。即在需要与别的设备共享中断的驱动程序中加载一个ISR,一般使用WINCE提供的GIISR即成满足需求。将其安装到内核。OAL中发生中断时调用NKCallIntChain来得到SYSINTR,这个函数会引起系统逐个调用在该IRQ上加载的所有可装载的ISR,当某个ISR认为这个中断是由它引发的时就返回其SYSINTR,否则就返回SYSINTR_CHAIN,系统就会接着调用其它的ISR,甚至所有的ISR都被调用或者有一个ISR返回了正确的SYSINTR。

    驱动程序中的调用办法如下(CE帮助文档):

    if (InstallIsr) {

    // Install ISR handler

    g_IsrHandle = LoadIntChainHandler(IsrDll, IsrHandler, (BYTE)Irq);

    if (!g_IsrHandle) {

    DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: Couldn't install ISR handler\r\n"));

    } else {

    GIISR_INFO Info;

    PVOID PhysAddr;

    DWORD inIoSpace = 1; // io space

    PHYSICAL_ADDRESS PortAddress = {ulIoBase, 0};


    if (!TransBusAddrToStatic(PCIBus, 0, PortAddress, ulIoLen, &inIoSpace, &PhysAddr)) {

    DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: Failed TransBusAddrToStatic\r\n"));

    return FALSE;

    }


    DEBUGMSG(ZONE_PDD, (L"WAVEDEV: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n", IsrDll, IsrHandler, Irq, PhysAddr));


    // Set up ISR handler

    Info.SysIntr = ulSysIntr;

    Info.CheckPort = TRUE;

    Info.PortIsIO = TRUE;

    Info.UseMaskReg = FALSE;

    Info.PortAddr = (DWORD)PhysAddr + ES1371_dSTATUS_OFF;

    Info.PortSize = sizeof(DWORD);

    Info.Mask = ES1371_INTSTAT_PENDING;


    if (!KernelLibIoControl(g_IsrHandle, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {

    DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: KernelLibIoControl call failed.\r\n"));

    }

    }

    }


    这里需要注意一下,因为ISR在内核态运行,Info.PortAddr必须是系统最原始的虚拟地址,即没有用VirtualCopy映射过的,从OEMAddressTable中计算出来的虚拟地址。在这个例子中用TransBusAddrToStatic函数可以直接把物理地址转换成这种地址。而MmMapIoSpace得到是在当前程序空间中的地址,不能使用。而且GIIR要被加载到内核空间,所以在加入到OS包中时需要加上K标志,否则LoadIntChainHandler函数会失败。

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Vichard/archive/2009/08/29/4497641.aspx

  • 相关阅读:
    算法学习(十五)
    学习正则表达式笔记(三)
    学习正则表达式笔记(二)
    事件监听器
    socket(套接字)
    (转载)表驱动法
    C++文件读写
    齐次表示
    线性插值(linear interpolation)
    向上取整Ceil,向下取整Floor,四舍五入Round
  • 原文地址:https://www.cnblogs.com/ceblog/p/1772371.html
Copyright © 2020-2023  润新知