阅读:984回复:1
USB2.0驱动....
在做USB2.0驱动时,有如下代码,是用DS2.7自动生成后稍加修改的,其中Read例程原来是接收到应用程序的读请求后即向总线驱动发一URB,现在我改成收到应用程序读请求后即在1M的环形缓冲区内取数,而不与硬件打交道。具体向USB硬件采集数据是另开一线程,一旦采集到数据后,即写入环形缓冲区,USB硬件设备上电后,此线程便启动了,一直监视是否有数据发往PC机,而不管应用程序是否来读,若环形缓冲区满,则用最新数据覆盖最旧的数据。
下面只给出Read例程和数据采集线程源码,该驱动的主要问题是,在应用程序中开了一个0.1s的Timer,每次定时中断一到,即向驱动发ReadFile,每10次计数一次读取到的数据,以便测USB传输速度,当应用程序定时器开启后,应用程序和驱动和固件都运行正常,但3分钟后,应用程序发的ReadFile返回为False,用Monitor观察,也看不到驱动进入Read例程,不知为何?此后,应用程序发WriteFile,正常,但再发ReadFile,驱动就是收不到,即应用程序返回为FALSE,即以后再也收不进数据了,但下面的固件工作正常,数据采集线程也工作正常,因为用其它方法测得此时环形缓冲区内数据正在不停地更新。此后,若关闭应用程序界面(是用MFC写的),PC机自动重起。下面的源码仅为驱动的一部分,也是更改后的一部分,其它是DS2.7自动生成的,也没必要给出。请各位大侠帮忙看下问题出在哪儿? NTSTATUS UDAQDevice::Read(KIrp I) { ULONG i; unsigned char* UserPointer=NULL; unsigned char* KernelPointer=NULL; unsigned char* SavePointer=NULL; t << "UDAQDevice::Read(KIrp I) \n"; // 用户要读的数据数 i=I.ReadSize(); // Declare a memory object KMemory Mem(I.Mdl()); // 环形缓冲池内有效数据数 ULONG dwMaxSize = (m_BFull)? Length_of_fifo:(((m_pTail-m_pHead)+Length_of_fifo)%Length_of_fifo); // 用户能读到的数据数 ULONG dwTotalSize = ( i > dwMaxSize )? dwMaxSize : i; t << "dwMaxSize = " << dwMaxSize << "\n"; t << "dwTotalSize = " << dwTotalSize << "\n"; // Always ok to read 0 elements. if (dwTotalSize == 0) { I.Information() = 0; return I.PnpComplete(this, STATUS_SUCCESS); } // 以下代码将有效数据返回用户,并调整环形缓冲池 if(Mem.IsValid()) { UserPointer = (unsigned char*) Mem.VirtualAddress(); KernelPointer = m_pHead; SavePointer = m_pHead; Mem.LockPages(IoWriteAccess,KernelMode); for(i=0;i<dwTotalSize;i++) { *UserPointer++ = *KernelPointer++; if(KernelPointer >= m_pTop) KernelPointer = m_pBase; } Mem.UnlockPages(); if(m_pHead != SavePointer) //此段代码是判断是否在读FIFO时,采集线程已采集完1M数据而使缓冲区Full。若FULL了,则此次读到的数据无效,丢掉。 { I.Information() = 0; //读出的数丢掉,并返回读到0个数 return I.PnpComplete(this, STATUS_ABANDONED); } m_BFull = false; I.Information() = dwTotalSize; m_pHead = KernelPointer; } else { I.Information() = 0; return I.PnpComplete(this, STATUS_ABANDONED); } return I.PnpComplete(this, STATUS_SUCCESS); } // 数据采集线程,将USB传来的数据填入环形缓冲池 VOID UDAQDevice::Sample(void) { ULONG nBytesRead; bool Tag; LONG i,gap; t << "UDAQDevice::Sample(void)\n"; while(1) { if(!BTerminate) { pSampleThread->Terminate(STATUS_SUCCESS); return; } PURB pUrb = m_BULKIN.BuildBulkTransfer( m_pTail, // Where is data go to m_Size, // How much data to read? TRUE, // direction (TRUE = IN) NULL, // Link to next URB TRUE // Allow a short transfer ); m_BULKIN.SubmitUrb( pUrb,NULL,NULL,2000); //设置成2000以使驱动程序可以自动卸载 nBytesRead = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength; delete pUrb; if(!nBytesRead) continue; //如果此次提交URB没采集到数据,则立即返回,重新循环 Tag = ((m_pTail < m_pHead) || m_BFull ); //新数据放入前的缓冲区状态 m_pTail += nBytesRead; gap = m_pTail - m_pTop; if( gap > 0 ) { m_pTail = m_pBase; for(i=0;i<gap;i++) *m_pTail++ = *m_pTop++; m_BFull = ( m_pTail >= m_pHead ) ; } else if( gap == 0 ) { m_pTail = m_pBase ; m_BFull = ( m_pTail == m_pHead ) ; } else { m_BFull = ( m_pTail >= m_pHead && Tag ); } //以上为调整m_pTail if( m_BFull ) m_pHead =m_pTail ; //此为调整m_pHead } } |
|
|
沙发#
发布于:2004-10-09 17:55
求命啊,没有高手帮我一下吗?
|
|
|