Bikky
驱动牛犊
驱动牛犊
  • 注册日期2003-12-01
  • 最后登录2017-02-21
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望11点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
  • 社区居民
阅读:984回复:1

USB2.0驱动....

楼主#
更多 发布于:2004-10-08 21:04
在做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
}
}
百克
Bikky
驱动牛犊
驱动牛犊
  • 注册日期2003-12-01
  • 最后登录2017-02-21
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望11点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2004-10-09 17:55
求命啊,没有高手帮我一下吗?
百克
游客

返回顶部