windriver指南(二)

三、寄存器的读写
   寄存器的读写用到一个非常好用的函数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 = 每次累加4
 WD_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 DMA
BOOL DMARoutine(WDC_DEVICE_HANDLE hDev, DWORD dwBufSize,
UINT32 u32LocalAddr, 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 DMA
BOOL 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;
}
 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值