dyzix
驱动牛犊
驱动牛犊
  • 注册日期2007-10-30
  • 最后登录2008-09-04
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2585回复:14

【分享】USB通信,PC端通信编程及常见问题解决方法

楼主#
更多 发布于:2008-07-22 13:02
请教:68013USB通信,PC端读取数据时程序反应慢的解决方法
如题,DSP通过USB(68013)与计算机通信,固件、驱动、通信程序均能正常工作。采用中断传输,在PC端使用一个线程一直读USB数据。监测到的情况是,向USB发送一个读取命令时,程序就等待读取完成,程序假死,造成程序响应比较慢。
驱动采用的是Cypress的驱动,没有更改。在驱动中,我做如下更改
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
0);//<----不等待、立即返回不起作用
也不行。
不知道哪位朋友有过这方面的经验,还请多多指教。

做USB过程实在是不易,将来在USB做好之后,我想将自己的经验跟大家共享。同时,朋友们如果有什么问题可以跟帖问,知无不言言无不尽。


上文为我昨天发的帖子,多谢zhoujiamurong和summerfruit朋友的热心帮助。现问题已经解决,如前承诺,将经验和大家分享,希望我走过的弯路,大家不要再走了。

USB入手真是不太容易,光USB协议都那么多,每一款都又有好几百页的芯片手册,涉及到的东西包括固件、驱动和通信,做起来真的不容易。一个地方没有看到,可能就在那停滞不前了。

我用的是Cy7c68013芯片,用于DSP与上位机传输大量数据(目前传输速度最快测试可以达到20M Byte/s)。

有时间我会将开发过程中的经验与大家分享下
dyzix
驱动牛犊
驱动牛犊
  • 注册日期2007-10-30
  • 最后登录2008-09-04
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-07-22 13:36
为什么程序反应慢,我想应该是有个函数在一直检测,直到有数据或设备断开时才返回。研究了下驱动,没找到原因。如果能改成没有数据就返回0就不至于这么慢了。
驱动没有做过,还请各位指点。

我现在是用Delphi调用C写的动态链接库通信,如果哪位朋友需要参考,我可以提供一些方法。
zhoujiamurong
驱动小牛
驱动小牛
  • 注册日期2006-03-20
  • 最后登录2009-05-06
  • 粉丝4
  • 关注0
  • 积分1081分
  • 威望360点
  • 贡献值0点
  • 好评度215点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-07-22 14:22
程序就等待读取完成,程序假死,造成程序响应比较慢
============
这个使用线程是否是后台的工作线程,还是直接用的死循环在用户线程中跑的?

如果是后台线程还是假死,看读取的时候是否是停滞在ReadFile等待返回?

如果是寻找是否有异步读取的方法?一般驱动里面都是异步的,改应该改在应用层。
summerfruit
驱动牛犊
驱动牛犊
  • 注册日期2004-06-12
  • 最后登录2013-12-07
  • 粉丝0
  • 关注0
  • 积分395分
  • 威望67点
  • 贡献值0点
  • 好评度36点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-07-22 14:38
你可以在驱动中自建一个thread,在这个thread中发送读URB,然后等待返回,读到数据放入buffer里面,读不到这个包含URB的IRP会pending的。主程序继续运行。
summerfruit
驱动牛犊
驱动牛犊
  • 注册日期2004-06-12
  • 最后登录2013-12-07
  • 粉丝0
  • 关注0
  • 积分395分
  • 威望67点
  • 贡献值0点
  • 好评度36点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-07-22 14:41
如果不想自建thread,可以调用系统线程,使用work item。
dyzix
驱动牛犊
驱动牛犊
  • 注册日期2007-10-30
  • 最后登录2008-09-04
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-07-22 14:54
引用第2楼zhoujiamurong于2008-07-22 14:22发表的  :
这个使用线程是否是后台的工作线程,还是直接用的死循环在用户线程中跑的?

如果是后台线程还是假死,看读取的时候是否是停滞在ReadFile等待返回?
.......


多谢楼上两位指点!我使用的是如下过程读取USB数据。创建一个线程,死循环读数据放到Buffer中,主循环中处理这些数据。读的时候,如果我的MCU不发数据的话,就等待读取Pending。
正像你说的,停滞在ReadFile等待返回。

int _stdcall ReadData(char *pbuf)
{
    DWORD nBytes;
    BOOL bResult;

    if(hDevice!=INVALID_HANDLE_VALUE)
    {
        bulkControl.pipeNum = 1;
        // Pipe 1 (EP 6)
        bResult = DeviceIoControl(hDevice,     // 设备句柄
            IOCTL_EZUSB_BULK_READ,                // 控制码
            &bulkControl,                        // 输入数据缓冲区指针
            sizeof(BULK_TRANSFER_CONTROL),        // 输入数据缓冲区长度
            pbuf,                                // 输出数据缓冲区指针
            FIFO_LEN,                            // 输出数据缓冲区长度
            &nBytes,                            // 输出数据实际长度
            NULL                                // 重叠操作结构指针
            );
        //bResult=ReadFile(hDevice,Buf,len,&rCount,NULL);
        if(bResult==0)
        {
            return 0;
        }
        return nBytes;
    }
    else
    {
        return 0;
    }
}
dyzix
驱动牛犊
驱动牛犊
  • 注册日期2007-10-30
  • 最后登录2008-09-04
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2008-07-22 15:04
引用第3楼summerfruit于2008-07-22 14:38发表的  :
你可以在驱动中自建一个thread,在这个thread中发送读URB,然后等待返回,读到数据放入buffer里面,读不到这个包含URB的IRP会pending的。主程序继续运行。


多谢指点。
正像你说的,我读的这个线程挂起(对驱动理解不深),随之导致主线程也不动作了。(做这个时,我真的感觉到,其实本没有多线程,所谓的多线程是时间片轮流而已~)
我正想在驱动中寻找解决方法,不让它pengding,读不到数据立即返回0(不等待),这样读线程就不至于影响主线程了。不知道各位朋友有高招没有。

其实我发现,很多使用USB与设备通信的软件也存在这个问题,比如我使用的DSP仿真器,经常出现不响应挂起的情况。此时拔掉USB就可以正常响应了。

还请各位继续发表高见。我对驱动不了解,正在学习中……
zhoujiamurong
驱动小牛
驱动小牛
  • 注册日期2006-03-20
  • 最后登录2009-05-06
  • 粉丝4
  • 关注0
  • 积分1081分
  • 威望360点
  • 贡献值0点
  • 好评度215点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2008-07-22 15:39
创建一个线程,死循环读数据放到Buffer中
================
我的理解,不知道对否:
如果原有驱动没有实现异步,那 ....
USB驱动中要实现异步读取就有点麻烦了,USB驱动中开两个线程一读一写,没有状况发生就在KeWaitforSingleObject(或Muti),读取是设置较短的超时。

应用层也要改改,开线程使用WaiforSingleObject等,没有状况不读,有了状况SetEvent,开始读。
dyzix
驱动牛犊
驱动牛犊
  • 注册日期2007-10-30
  • 最后登录2008-09-04
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2008-07-22 15:54
引用第7楼zhoujiamurong于2008-07-22 15:39发表的  :
USB驱动中要实现异步读取就有点麻烦了,USB驱动中开两个线程一读一写,没有状况发生就在KeWaitforSingleObject(或Muti),读取是设置较短的超时.......

 
谢谢再次指导!
有道理,给超时设短点,如果是毫秒级,估计程序应该有一些改善。
USB实现异步…… 现在我还不会,边学习边改驱动试试。
我的上位机程序中,可以采样串口或USB与设备通信,串口通信慢,但是程序反应很快;USB很强劲,但带来的是程序返回缓慢,虽然要的大量数据已经收到,可就是操作太不爽。故想在驱动中寻求突破口。继续学习……
summerfruit
驱动牛犊
驱动牛犊
  • 注册日期2004-06-12
  • 最后登录2013-12-07
  • 粉丝0
  • 关注0
  • 积分395分
  • 威望67点
  • 贡献值0点
  • 好评度36点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2008-07-22 17:40
按照你的想法,其实我认为不需要在驱动里面设置线程,只要在应用程序里面设置线程就可以了。这个线程就是读数据,读不到就一直pending都可以啊。
dyzix
驱动牛犊
驱动牛犊
  • 注册日期2007-10-30
  • 最后登录2008-09-04
  • 粉丝1
  • 关注0
  • 积分3分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2008-07-23 08:30
关键是,新创建的线程一挂起,整个程序都无响应……
zhang3
驱动牛犊
驱动牛犊
  • 注册日期2002-05-26
  • 最后登录2008-08-20
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望4点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2008-08-01 11:31
ezusb.sys驱动不支持异步方式,在应用层只能用多线程方式。

如果上行数据够快,还应该开多个线程同Pending,这样才不会丢数据。
hoguowi
驱动牛犊
驱动牛犊
  • 注册日期2006-07-22
  • 最后登录2012-12-20
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望213点
  • 贡献值1点
  • 好评度19点
  • 原创分0分
  • 专家分10分
12楼#
发布于:2008-08-02 09:52
不知道楼主的如何解决PC端读取数据时程序反应慢(当USB设备没发数据的时候,PC又在读会卡在读函数那里)这个问题我一直没有很好的解决,如果解决了这个问题,弄USB又是一个突破,我也愿意把我之前弄USB一点经验共享出来!之前已经写了 《USB驱动的制作过程与体会》但现在觉得还有很多要注意的问题要解决!!!所以想重新写份更详细的,包括硬件电路和PC上的软件!
jack_qi
驱动牛犊
驱动牛犊
  • 注册日期2008-07-15
  • 最后登录2008-11-25
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望12点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2008-08-06 11:45
引用第9楼summerfruit 于2008-07-22 17:40:39发表的
"应用程序里面设置线程就可以了。这个线程就是读数据,读不到就一直pending都可以啊。"
我也这么想的,不过在软件里怎么实现?
交流是为了更好的学习
jack_qi
驱动牛犊
驱动牛犊
  • 注册日期2008-07-15
  • 最后登录2008-11-25
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望12点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2008-08-06 11:52
dyzix 在5楼里的程序代码只是读USB设备数据的,没有启动线程方面的问题,所说的“创建一个线程,死循环读数据放到Buffer中,主循环中处理这些数据。读的时候,如果我的MCU不发数据的话,就等待读取Pending。”想请教下软件部分怎么实现?在这读数据函数里怎么加多线程来处理?
交流是为了更好的学习
游客

返回顶部