WinDriver教程

  • 格式:doc
  • 大小:78.00 KB
  • 文档页数:11

WinDriver教程一、如何用windrive打开、关闭设备以及查看设备的信息1.所有有关的WD_API在安装后的相关目录下可以找到,建议打印出来,仔细看下。

2.打开、关闭设备与查看相应信息:HANDLE m_hPex;DWORD Bus,Slot,Fun,Interrupt;DWORD BaseAddrCS0,BaseAddrCS1,BaseAddrCS2,BaseAddrCS3;DWORD RangeAddrCS0,RangeAddrCS1,RangeAddrCS2,RangeAddrCS3;//打开设备:WD_LICENSE lic;m_hPex=WD_Open();if (m_hPex==INVALID_HANDLE_VALUE) {str="INVALID_HANDLE_VALUE"; }else{//重新注册wd,去除过期限制strcpy(lic.cLicense, "你的注册号");WD_License(m_hPex, &lic); }//检查WD版本WD_VERSION ver;BZERO(ver);WD_Version(m_hPex, &ver);if (ver.dwVer<WD_VER){str="Windriver Overdue";}WD_PCI_SCAN_CARDS pciScan;WD_PCI_SLOT pciSlot;BZERO(pciScan);//以PEX8311为例pciScan.searchId.dwVendorId = 0x10b5; pciScan.searchId.dwDeviceId = 0x86e1; WD_PciScanCards (m_hPex, &pciScan); if (pciScan.dwCards>0) {pciSlot = pciScan.cardSlot[0];WD_PCI_CARD_INFO pciCardInfo;WD_CARD Card;BZERO(pciCardInfo);pciCardInfo.pciSlot = pciSlot;WD_PciGetCardInfo (m_hPex, &pciCardInfo);if (pciCardInfo.Card.dwItems!=0){Card = pciCardInfo.Card;}else{str="Pcicard=0";}WD_CARD_REGISTER cardReg;//Card.Item[0]PC机基本端口操作//Card.Item[1]中断信息BZERO(cardReg);cardReg.Card = Card;cardReg.fCheckLockOnly = FALSE;WD_CardRegister(m_hPex,&cardReg);if (cardReg.hCard == 0){str="cardReg=0";}str="open successfully";//取得当前设备信息并显示Interrupt=Card.Item[1].I.Int.dwInterrupt); Bus=pciScan.cardSlot[0].dwBus;Slot=pciScan.cardSlot[0].dwSlot;Fun=pciScan.cardSlot[0].dwFunction;//CS0-CS3的地址映射信息BaseAddrCS0=Card.Item[2].I.Mem.dwPhysicalAddr; RangeAddrCS0=Card.Item[2].I.Mem.dwBytes; BaseAddrCS1=Card.Item[3].I.IO.dwAddr; RangeAddrCS1=Card.Item[3].I.Mem.dwBytes; BaseAddrCS2=Card.Item[4].I.Mem.dwPhysicalAddr; RangeAddrCS2=Card.Item[4].I.Mem.dwBytes;BaseAddrCS3=Card.Item[5].I.Mem.dwPhysicalAddr;RangeAddrCS3=Card.Item[5].I.Mem.dwBytes; else{str="Open Failed";WD_Close(m_hPex);}AfxMessageBox(str);注:Card.Item[0-5]就是DEVICE/IO/MEM映射的地方,这里得到的值和windrive wizard里看到的是一样的。

二、设备的读写操作1.写操作WD_TRANSFER trans;BZERO(trans);trans.cmdTrans = WP_BYTE; //(WORD/DWORD)trans.dwPort = BaseAddrCS0;//可为其它的映射基地址trans.Data.Byte = 0x00; //需要写的数据WD_Transfer (m_hPex, &trans);2.读操错WD_TRANSFER trans;BZERO(trans);trans.cmdTrans = RP_BYTE; //(WORD/DWORD)trans.dwPort = BaseAddrCS1;//可为其它的映射基地址WD_Transfer (m_hPex, &trans);return trans.Data.Bytes;三、其它有关windriver对寄存器的操作要用到WDC_***函数,还有DMA操作在(二)中阐述。

三、寄存器的读写寄存器的读写用到一个非常好用的函数WD_PciConfigDump();具体的参数定义参照WD的API手册。

WD_PCI_CONFIG_DUMP pciConfig;DWORD dwStatus;WORD arBuffer[2];BZERO(pciConfig);pciConfig.pciSlot.dwBus = Bus;pciConfig.pciSlot.dwSlot = Slot;pciConfig.pciSlot.dwFunction = Fun;pciConfig.pBuffer = arBuffer;pciConfig.dwBytes = sizeof(arBuffer);pciConfig.fIsRead = TRUE;pciConfig.dwOffset = 每次累加4WD_PciConfigDump(m_hPex, &pciConfig);四、数据的块操作DWORD dataBuffer[8192];WD_TRANSFER trans;*****************trans.Data.pBuffer=dataBuffer;利用WD_Transfer()函数来完成数据的块操作。

五、DMA控制WinDriver为提供了一组API函数,但是其提供的DMA 函数不是基于突发方式的,并且是以查询方式来检测DMA是否结束,比较适用于一次DMA读写。

因此需要对其提供的DMA API函数及中断相关的函数进行改写,即在DMAOpen()函数中,需对DMAMODE寄存器的本地突发使能位(BIT8)与BTERM输入使能位(BIT7)置位,否则,DMA操作只能完成一个双字的突发传输,只有将此二位置1 后,才能完成指定长度的DMA传输。

因为传输量超过4 KB,所以要置为分散/聚拢(scatter/gather)模式(BIT9),同时使能DMA 中断完成位(BIT10)与DMA通道0 中断选择位(BIT17)。

重写DMA 启动函数DMAStart(),设置每次DMA 传输所需的PCI 地址(主机物理内存地址)、本地地址、传输大小、传输方向等,并置DMA 启动位。

这样每次数据捕获满中断到来,启动DMA 传输时,只需调用DMAStart()函数即可。

如果采用Windriver 提供的DMAWriteRead 函数,每进行一次DMA 传输都要重新打开一个DMA,分配空间,设置各种相应的寄存器等,增加了DMA 传输的CPU 开销。

经过测试,当进行数据全速捕获时,如果采用Windriver 提供的DmaWriteRead 函数及DMA 完成查询方式,CPU 的负荷最高可达80%,严重影响了系统其他程序的执行。

当采用修改后的DmaStart()函数及DMA 中断方式后,全速进行数据捕获时,CPU 的负荷只有25%左右,大幅降低了CPU 的负荷,保证了整个系统软件的正常执行。

在DMAStart()函数中,需要注意的是PCI 地址寄存器的设置,因为传输数据量大于一页(4KB),所以采用了分散/聚集方式,即以分散的物理内存块映射连续分配的用户地址空间。

与内存块分配方式不同,这时不是设置DMA的PCI地址与本地地址寄存器,而是设置DMA通道的描述符寄存器(DMADPR)。

通过函数WD_DMALock()在物理内存中锁定所需大小的存储空间,取得每页的物理地址,大小以及相应的本地地址放入地址描述块链表中,在DMADPA寄存器中设置初时的描述块地址。

1)Scatter/Gather DMABOOL DMARoutine(WDC_DEVICE_HANDLE hDev, DWORD dwBufSize, UINT32u32LocalAddr, DWORD dwOptions, BOOL fPolling, BOOL fToDev) { PVOID pBuf;WD_DMA *pDma = NULL;BOOL fRet = FALSE;/* Allocate a user-mode buffer for Scatter/Gather DMA */ pBuf =malloc(dwBufSize);if (!pBuf)return FALSE;/* Lock the DMA buffer and program the DMA controller */ if(!DMAOpen(hDev, pBuf, u32LocalAddr, dwBufSize, fToDev, &pDma)) goto Exit;/* Enable DMA interrupts (if not polling) */if (!fPolling){if (!MyDMAInterruptEnable(hDev, MyDmaIntHandler, pDma)) goto Exit;/* Failed enabling DMA interrupts */}/* Flush the CPU caches (see documentation of WDC_DMASyncCpu()) */ WDC_DMASyncCpu(pDma);/* Start DMA - write to the device to initiate the DMA transfer */ MyDMAStart(hDev, pDma);/* Wait for the DMA transfer to complete */MyDMAWaitForCompletion(hDev, pDma, fPolling);/* Flush the I/O caches (see documentation of WDC_DMASyncIo()) */WDC_DMASyncIo(pDma);fRet = TRUE;Exit:DMAClose(pDma, fPolling);free(pBuf);return fRet;}2)Contiguous Buffer DMABOOL DMARoutine(WDC_DEVICE_HANDLE hDev, DWORD dwDMABufSize, UINT32 u32LocalAddr, DWORD dwOptions, BOOL fPolling, BOOL fToDev) { PVOID pBuf = NULL;WD_DMA *pDma = NULL;BOOL fRet = FALSE;/* Allocate a DMA buffer and open DMA for the selected channel */ if (!DMAOpen(hDev, &pBuf, u32LocalAddr, dwDMABufSize, fToDev, &pDma)) goto Exit;/* Enable DMA interrupts (if not polling) */if (!fPolling){if (!MyDMAInterruptEnable(hDev, MyDmaIntHandler, pDma)) goto Exit; /* Failed enabling DMA interrupts */}/* Flush the CPU caches (see documentation of WDC_DMASyncCpu()) */ WDC_DMASyncCpu(pDma);/* Start DMA - write to the device to initiate the DMA transfer */ MyDMAStart(hDev, pDma);/* Wait for the DMA transfer to complete */MyDMAWaitForCompletion(hDev, pDma, fPolling);/* Flush the I/O caches (see documentation of WDC_DMASyncIo()) */ WDC_DMASyncIo(pDma);fRet = TRUE;Exit:DMAClose(pDma, fPolling);return fRet;}六、windriver API的深入分析windriver作为Jungo公司出品的一个高效易用的驱动开发软件,方便用户基于此开发自己设备的驱动程序,而不需要对windows DDK作更深入的研究(当然,要想称为驱动的高手,DDK是一定要钻研的)。