搜索
bottom↓
回复: 63

【求助】FPGA USB数据采集,丢失数据包

[复制链接]

出0入0汤圆

发表于 2012-4-13 23:04:24 | 显示全部楼层 |阅读模式
本帖最后由 feiwa 于 2012-4-14 00:10 编辑

小弟目前采用Altera FPGA + Cypress USB (68013A) 架构,以实现多路音频信号采集。目前遇到一个问题,信号采集并传输到电脑后,疑似数据包有丢失。
USB传输使用的方法:异步slave FIFO,8位或16位。
判断的依据:在FPGA端自定义产生循环数据,在接受端发现数据不连续。
初步判断错误来源:上位机端对数据包的获取。上位机中对每次取得的数据定义了大小,(8192、4096),每个数据包的数据是连续的,但数据包之间的数据不连续。
附取数据程序代码:

BOOL CUSBDlg::EzusbShortdataIn(HANDLE hDevice, BYTE *data, DWORD &lenBytes)
{
    bResult = DeviceIoControl (hDevice,
                IOCTL_EZUSB_BULK_READ,
                &bulkControl,
                sizeof (BULK_TRANSFER_CONTROL),
                data,
                8192,   //4096,
                &lenBytes,
                NULL);       
    ...
}

一直无法定断错误发生在软件读数上还是硬件发送数据上。
诸位前辈若不吝点拨一二,当不胜感谢。

出0入0汤圆

发表于 2012-4-14 06:45:21 | 显示全部楼层
用HUSBOUND看下

出0入442汤圆

发表于 2012-4-14 07:36:50 | 显示全部楼层
注意了,你犯了一个最大的错误,USB没有8K的数据包,最大的包一个才512字节(Bulk)。所以你一个8K的包USB是分16次传的!
你的那个8192只是接收缓冲区的大小,不是每次收到字节数量大小!

出0入0汤圆

发表于 2012-4-15 17:56:56 | 显示全部楼层
wye11083 发表于 2012-4-14 07:36
注意了,你犯了一个最大的错误,USB没有8K的数据包,最大的包一个才512字节(Bulk)。所以你一个8K的包USB ...

但是这个函数只有全部接收到数据后才会返回结果的,所以在上位机看来,一次请求8K没什么错误。

但是,楼主你这样只请求那么小,速度是上不去的,可以一次请求大一点的包,至少几百K吧,我也在做68013的项目,不过我是用C#写的,Win7,一次请求4M

出0入0汤圆

发表于 2012-4-15 19:10:41 | 显示全部楼层
NJ8888 发表于 2012-4-14 06:45
用HUSBOUND看下

请教一下HUSBOUND是什么东东,好像百度也搜不到。。。

出0入442汤圆

发表于 2012-4-15 20:25:02 | 显示全部楼层
Chouc 发表于 2012-4-15 17:56
但是这个函数只有全部接收到数据后才会返回结果的,所以在上位机看来,一次请求8K没什么错误。

但是,楼 ...

我怀疑你没有接收过大数据吧,我也是用68013的!固件我都自己改过的!
你可以试试,68013的缓冲区一共只有4KB,顶多够两个四倍512字节缓冲,所以不要希望一次收到8KB的数据。
另外,IOCTL函数不是说必须收满才会返回,它只要收到一个包,管它多大,立刻返回!所以你收一次0个包的,只要你把PKTEND拉低,它就立刻返回0包了。IOCTL倒数第二?个参数返回的是实际收发的字节数。
你发送的时候IOCTL自动给你换成小包,你接收的时候IOCTL不会这么做。上面那个8192是缓冲区大小,不是你要接收的数据大小。

出0入0汤圆

发表于 2012-4-15 20:26:59 | 显示全部楼层
Chouc 发表于 2012-4-15 19:10
请教一下HUSBOUND是什么东东,好像百度也搜不到。。。

非常抱歉是BUSHound

出0入0汤圆

发表于 2012-4-16 00:22:22 | 显示全部楼层
本帖最后由 Chouc 于 2012-4-16 00:31 编辑
wye11083 发表于 2012-4-15 20:25
我怀疑你没有接收过大数据吧,我也是用68013的!固件我都自己改过的!
你可以试试,68013的缓冲区一共只 ...


当然是做过高速采集我才这么说的啊。。。我现在做的这个,如果FPGA以48Mhz频率产生的假数据,我接收可以做到38MB/s,单次请求4MB都没问题(win7,C#),驱动会帮你自动解包的,根本不用自己去考虑太底层的东西

PS:忘了说,autoin模式

出0入442汤圆

发表于 2012-4-16 11:00:42 | 显示全部楼层
Chouc 发表于 2012-4-16 00:22
当然是做过高速采集我才这么说的啊。。。我现在做的这个,如果FPGA以48Mhz频率产生的假数据,我接收可以 ...

DeviceIoControl (hDevice,
                IOCTL_EZUSB_BULK_READ,
                &bulkControl,
                sizeof (BULK_TRANSFER_CONTROL),
                data,
                8192,   //4096,
                &lenBytes,
                NULL);

我怀疑你是不是真正做过, 8192是data的长度,每次传的数据长度在&lenBytes中,&lenBytes保存的是实际接收到的数据。

建议你再做些实验。DeviceIoControl收到一个包立刻返回。它不会帮你做这些事!除非你用的是别人给你封装好的接口!如果你不用C++,那我可以赌你用的别人的接口。我就是做底层的,没必要跟你较劲。

出0入442汤圆

发表于 2012-4-16 11:13:21 | 显示全部楼层
Chouc 发表于 2012-4-16 00:22
当然是做过高速采集我才这么说的啊。。。我现在做的这个,如果FPGA以48Mhz频率产生的假数据,我接收可以 ...

你看清楚了,LZ用的是DeviceIoControl,是C++底层的东西。你只有写过底层才会真正知道底层到底发生了什么。

出0入0汤圆

发表于 2012-4-16 15:13:14 | 显示全部楼层
wye11083 发表于 2012-4-16 11:00
DeviceIoControl (hDevice,
                IOCTL_EZUSB_BULK_READ,
                &bulkControl,

不想多说什么了,反正我项目都做出来了,用的官方CYUSB.dll驱动和官方的传输函数(begin/wait/finishxferdata)(如果这也算是“别人“提供的封装好的函数).如果你是自己写的驱动,那我无话可说了。

另附上一篇帖子:bbs.21ic.com/viewthread.php?tid=114226&highlight=68013,作用很大

出0入442汤圆

发表于 2012-4-16 15:20:42 | 显示全部楼层
官方的传输函数(begin/wait/finishxferdata),就是封装好的函数,也就是说,你不需要再用IOCTL来传输了,就不需要考虑数据分包的问题了,要不然你就必须纠结数据包分帧了。这样答案就清楚了,你用包装好的CyAPI库收发数据,我们用WINDOWS底层的IOCTL来收发数据。
另:这里讨论的是数据包的大小,不是数据收发速率。如果没有外挂FPGA时,没办法,只能用IO来控制,速度不会快到哪去。所以你不知道LZ是怎么接的,就不要评论。PS:我现在FPGA还是外挂设备之一,还没有用它做Slave FIFO,最大处理速率约2MB/s。

出0入442汤圆

发表于 2012-4-16 15:24:36 | 显示全部楼层
Chouc 发表于 2012-4-16 15:13
不想多说什么了,反正我项目都做出来了,用的官方CYUSB.dll驱动和官方的传输函数(begin/wait/finishxfer ...

还有一点,我是用的ezusb.sys,然后自己写的DLL,然后在C#里调用自己整的这个DLL,估计跟LZ差不多,所以我和LZ是确定用的ioctl里面的函数,使用系统调用的方式直接和驱动打交道。而你是用CYUSB.dll,这样就不需要自己写dll,直接调cyusb.dll就可以运行了,剩下的就是cyusb.dll的工作了。

出0入0汤圆

 楼主| 发表于 2012-4-16 22:24:10 | 显示全部楼层
NJ8888 发表于 2012-4-14 06:45
用HUSBOUND看下

谢谢!网络的原因,没能及时上网来感谢,抱歉。
我没用过HUSBOUND,先去了解一下。

出0入0汤圆

发表于 2012-4-16 22:28:18 | 显示全部楼层
feiwa 发表于 2012-4-16 22:24
谢谢!网络的原因,没能及时上网来感谢,抱歉。
我没用过HUSBOUND,先去了解一下。 ...

再次抱歉,是BUSHound

出0入0汤圆

 楼主| 发表于 2012-4-16 22:36:01 | 显示全部楼层
本帖最后由 feiwa 于 2012-4-17 02:52 编辑
wye11083 发表于 2012-4-16 11:00
DeviceIoControl (hDevice,
                IOCTL_EZUSB_BULK_READ,
                &bulkControl,


谢谢wye11083,你的讨论对我很有帮助。

由于我对C++底层不是很清楚,所以一直找不到原因。
对于缓冲的大小,就是我一开始怀疑的地方。在Firmware里我设置的包大小是512字节;在接收端,我尝试过各种缓冲区大小,8192,4096,等等。
测试时的现象是:在FPGA内部产生循环数发送,在接收端,如果是8192的数据包内部,数据是连续的,数据包之间数据是不连续的。

我开始的理解是:USB端每次发送512字节的数据包,上位机端接收512字节的数据包;使用的是例程的上位机软件,发现数据包设置的大小是8192,然后判断出数据丢失的现象。
在上位机端,需要数据连续,需要有什么特别的设定吗?先不考虑速度的问题。

出0入0汤圆

 楼主| 发表于 2012-4-16 22:51:08 | 显示全部楼层
本帖最后由 feiwa 于 2012-4-16 23:21 编辑
Chouc 发表于 2012-4-16 15:13
不想多说什么了,反正我项目都做出来了,用的官方CYUSB.dll驱动和官方的传输函数(begin/wait/finishxfer ...


谢谢Chouc。
我目前的情况是使用的IOCTL函数,这也是按照一个例程来做的,所以自己还不是很清楚底层驱动的工作原理。
你提到的用CYUSB.dll驱动和官方传输函数的方法我看到过,但还没来得及去实现。
要是不介意的话,可否将具体的实现过程方法告诉我?

出0入0汤圆

 楼主| 发表于 2012-4-16 23:00:32 | 显示全部楼层
本帖最后由 feiwa 于 2012-4-16 23:11 编辑
Chouc 发表于 2012-4-16 15:13
不想多说什么了,反正我项目都做出来了,用的官方CYUSB.dll驱动和官方的传输函数(begin/wait/finishxfer ...


在你给的链接里找到这样的一句答复,感觉很有用:

“我也遇到这个问题,在网上疯狂地寻找答案而最终基本得到解决,请教了若干Q友,在此表示感谢。
上位机采集68013时丢数的原因是上位机两次读间隙,68013的FIFO满了,没能及时读出,导致FPGA没能将部分数据写入68013中,从而产生了丢数现象,增加上位机每次读的数据量可以明显减少这种丢数现象。
当速度设置为16MB/s时,上位机虽然有丢数,但是在一定的时间内采集的数据总量是没有减少的,从这点可以断定,上位机的采集速度是跟得上的。解决这种丢数现象的办法是在68013之前加入FIFO或其他类似功能的缓冲区。这时使用的USB驱动依然是官方的Cy驱动,使用CyAPI库编写上位机程序。
网上有许多牛人的观点说丢数是USB驱动的问题。当然可以改写驱动,减少每次读间隔,也可以解决丢数现象。但驱动不是一般人能够写的。”

但是我之前也尝试过将缓冲区设置更大的方法,发现变大后软件不能取到数。
要再纠结一下,尝试各种方法看...

出0入442汤圆

发表于 2012-4-17 00:13:06 | 显示全部楼层
feiwa 发表于 2012-4-16 22:36
谢谢wye11083,你的讨论对我很有帮助。

由于我对C++底层不是很清楚,所以一直找不到原因。

噢,我想你丢包的原因应该是你收到一个包立刻处理,然后再收下一个包。注意这是不可以的。收包必须用多线程,然后插入一个链表中(互斥或临界区),再用另一个线程来处理数据。另外,FX2有三个FLAG,其中有一个是满,你可以用FPGA读这个管脚。其实你可以这样做:
读满FLAG -> 再读满FLAG,同时设置数据 -> 如果不满,则拉低WR,否则等待,回到开始。
这样就不会出现丢数据的情况了。
我开始开发时也是无论如何都找不到例程,最后在Ezmon这个附带的程序里把IOCTL的代码抠出来,然后就是测试。IOCTL每次最大只能读取FIFO大小的包,BULK模式每包512字节,ISO模式每包最大1024字节,但是ISO模式只能达到16MB左右的速率。因此你没必要开8K的缓冲,用IOCTL的话每次进去开一个512字节的缓冲,然后把缓冲插到链表中。处理线程提出来一个包,处理完后再销毁就行了。

出0入0汤圆

 楼主| 发表于 2012-4-17 00:30:26 | 显示全部楼层
本帖最后由 feiwa 于 2012-4-17 06:03 编辑
wye11083 发表于 2012-4-17 00:13
噢,我想你丢包的原因应该是你收到一个包立刻处理,然后再收下一个包。注意这是不可以的。收包必须用多线 ...


Good!很好的方案!
我现在欠考虑的地方:FPGA里的循环处理和上位机的多线程处理。FPGA方面还好一点,修改和调试应该问题不大,多线程对我来说就有点麻烦了。
先去摸索一下,有进展再上来发布。

出0入0汤圆

发表于 2012-4-17 02:58:05 | 显示全部楼层
feiwa 发表于 2012-4-17 00:30
Good!很好的方案!
我现在欠考虑的地方:FPGA里的循环处理和上位机的多线程处理。FPGA方面还好一点,修 ...

上位机部分确实需要使用多线程+链表的方式处理,固件设置好FPAGA后,FPGA检测FLAGA管脚状态,快满的时候停止往USB里写,但此时可能会出现FPGA端信号丢失的情况,因此要将FPGA内部缓冲开大,或者使用外部存储器。固件部分如果用的是SLAVEFIFO的话,真没什么要研究的,把官方文档的后面的例程好好看一遍就懂了(记得要下最新的文档)

出0入0汤圆

 楼主| 发表于 2012-4-17 06:10:40 | 显示全部楼层
Chouc 发表于 2012-4-17 02:58
上位机部分确实需要使用多线程+链表的方式处理,固件设置好FPAGA后,FPGA检测FLAGA管脚状态,快满的时候 ...

了解。谢过了!
多线程+链表,真不知道如何下手了 -,-!...
先把FPGA端的 FLAG信号处理,再着手软件,一步步来吧。

出0入0汤圆

 楼主| 发表于 2012-4-21 05:55:53 | 显示全部楼层
wye11083 发表于 2012-4-17 00:13
噢,我想你丢包的原因应该是你收到一个包立刻处理,然后再收下一个包。注意这是不可以的。收包必须用多线 ...

在FPGA里增加4K的FIFO缓存,增加读 EP6 FULL FLAG,重新设计FPGA增加控制逻辑,测试时反而不能通信。
从仿真结果看信号是正确的,FPGA与USB的连线也就几根线。伤脑筋.

再好好检查一遍,有时间能否多请教你一下?

出0入442汤圆

发表于 2012-4-21 08:42:33 | 显示全部楼层
是不是把FLAG搞反了?所有FLAG均是低电平有效,高电平无效(没有修改极性的话)。

出0入0汤圆

 楼主| 发表于 2012-4-23 22:24:59 | 显示全部楼层
本帖最后由 feiwa 于 2012-4-24 00:52 编辑
wye11083 发表于 2012-4-21 08:42
是不是把FLAG搞反了?所有FLAG均是低电平有效,高电平无效(没有修改极性的话)。 ...


FLAG是低电平有效,这个没有问题。我在仿真的时候设置FLAG输入为高电平,可以一直有写信号。
我把后仿真的结果帖出来,你看看对不对。使用的是 异步slave FIFO,SLWRn 信号标示出来了


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入442汤圆

发表于 2012-4-23 23:54:25 | 显示全部楼层
feiwa 发表于 2012-4-23 22:24
FLAG是低电平有效,这个没有问题。我在仿真的时候设置FLAG输入为高电平,可以一直有写信号。
我把后仿真 ...

等我先试验试验再说。我的FX2和FPGA连起来了,不过我现在只把它用作CPUIO模式。
你要不下个Bus Hound软件抓抓USB包,看看具体什么情况。这个软件我也是刚下几天,用着特别方便。

出0入0汤圆

 楼主| 发表于 2012-4-24 00:52:17 | 显示全部楼层
我今天下了Bus Hound软件,正在尝试抓包进行分析。
用旧的FPGA设计的循环数验证结果是,每512个字节的包之间不连续,包内数据连续。
在尝试把重新设计的FPGA也调整成产生循环数发送的方式,看是否也有类似的丢包问题。

出0入0汤圆

 楼主| 发表于 2012-4-25 05:00:24 | 显示全部楼层
Chouc 发表于 2012-4-17 02:58
上位机部分确实需要使用多线程+链表的方式处理,固件设置好FPAGA后,FPGA检测FLAGA管脚状态,快满的时候 ...

Hi Chouc,
目前FPGA和Firmware都已经重新设计过,用Bus Hound接收2M数据,数据都是连续的,没有数据包丢失。硬件端工作基本正常。
现在软件的问题对我来说比较棘手,能否请你将软件端接收数据的部分程序再说得仔细一些?我先考虑把数据存储到电脑上,不去做处理,这样应该可以保证数据不会丢失。
务请指教!先谢过了。

出0入0汤圆

发表于 2012-4-26 00:19:33 | 显示全部楼层
feiwa 发表于 2012-4-25 05:00
Hi Chouc,
目前FPGA和Firmware都已经重新设计过,用Bus Hound接收2M数据,数据都是连续的,没有数据包丢 ...

其实只接收是比较简单的。如果还要存储的话,存储和接收各一个线程,每次接收,都开一个新的buffer,接收完后将这个buffer用队列管理(也可以用链表实现),存储线程将队列里的buffer依次存储。这里由于引入了存储,CPU分给接收线程的时间片断会比 只接受收 的少(我这里4核的i7机器也很明显),因此,即使接收程序不丢包,合起来写也可能会有“丢包”现象(取决于电脑配置,实际传输速率,下位机缓冲等等)。之前我只用FPGA内部FIFO做缓冲,存储时偶尔有丢包现象,半小时40G的数据丢了几十兆,后来分析是由于由于PC端线程没有来得及切换,导致FPGA端缓冲(只有64k...)溢出,而且CPU主频越低,丢包越明显(换另一台i7的笔记本测试得出的结论),我觉得这就是为什么很多论文里的高速采集都会配一个外部大容量高速存储芯片(SDRAM或者DDR)作为缓冲池的原因。
只用FPGA内部FIFO(cyclone 3c25)做缓冲,接收+存储 还能不丢包,我还做不到,之前一直觉得是程序方面的问题,但是改了几天都没能解决,后来采用了片外缓冲的方式。
如果有人能够只用片内的少量ram就做到,也请不吝赐教,能使系统简化不少。

出0入0汤圆

发表于 2012-4-26 09:49:10 | 显示全部楼层
feiwa 发表于 2012-4-25 05:00
Hi Chouc,
目前FPGA和Firmware都已经重新设计过,用Bus Hound接收2M数据,数据都是连续的,没有数据包丢 ...

lz上位机程序多线程其实不是想象中的那么难,最近也在做这方面的,由于有个小demo,花一周看多线程这块,注意线程之间的关系就行了,我做的东西的电脑不断的写到FPGA 像楼上说的那样,在FPGA收数据时我加了个8k的RAM ip核,每次等RAM满了之后再给我下一步要用的SDRAM上。由于FPGA速度快,RAM只是一个保险作用,但是你读数据的话,68013发数据的速度跟不上FPGA的速度,如果你flag在状态机里没处理好的话有可能出现丢数据的问题

出0入0汤圆

 楼主| 发表于 2012-4-26 22:40:43 | 显示全部楼层
chadusb 发表于 2012-4-26 09:49
lz上位机程序多线程其实不是想象中的那么难,最近也在做这方面的,由于有个小demo,花一周看多线程这块, ...

谢谢,由于我没有编程经验,C++的代码看得我头都大了。
在FPGA里我设置了一个4K的FIFO作为缓存,读FLAG满时停止发送;目前在FPGA里内部产生循环数,在PC端读了2M的数据,一直是连续循环的。说明FPGA发的数据没有问题。
我现在主要的问题就在于收数据端,测试用的Bus Hound,但我需要自己写一个收数据的程序,这个程序还要对数据进行一定的处理。这个就是我的主要问题。快要抓狂了。。。
你的demo或者参考示例,能否给我传一份?

出0入0汤圆

发表于 2012-4-27 08:15:46 | 显示全部楼层
哥们  做东西先得评估需求。  如果采集音频  数据率能有多大。 为什么非得使用同步模式。
用bulk不好吗。 我做过用bulk采集数字电视码流的  照样用bulk, 唯一不丢包的方法。 很久以前了 如果模拟测试的话,好像能到20MB/s  足够了吧?

出0入0汤圆

 楼主| 发表于 2012-4-27 08:33:27 | 显示全部楼层
McBee 发表于 2012-4-27 08:15
哥们  做东西先得评估需求。  如果采集音频  数据率能有多大。 为什么非得使用同步模式。
用bulk不好吗。  ...

正是使用的Bulk

出0入0汤圆

发表于 2012-4-27 08:53:38 | 显示全部楼层
呃 那。。。。。。。。。
给你提供个我们当时做的思路吧。 当时用的官方驱动和api。 用了一个还是两个工作线程忘记了。 用了两个buffer 好像。
我那会用了一个cpld 纯是asi 和spi接口的复用, 用了一片64k的双端口ram。 实际测试的结果看,数字码流几兆的带宽完全满足。 时间太久了 5~6年了。

出0入0汤圆

 楼主| 发表于 2012-4-27 09:33:09 | 显示全部楼层
谢谢你。
硬件端应该没有问题了, 我用Bus Hound接收了2M的数据,没有丢失的现象。而且我对速度的要求也不高。
因为我不是做软件的,赶鸭子上架来写软件,所以问题比较多。
再说我就会变祥林嫂了...但这就是我面临的问题诶

出0入0汤圆

 楼主| 发表于 2012-4-27 15:49:11 | 显示全部楼层
最新的进展,PC端已能较稳定地接收数据。
接下去进一步调试系统的正确和稳定性。
谢谢各位的帮助。

出0入0汤圆

发表于 2012-4-27 23:16:30 | 显示全部楼层
都是高手啊,看得我云里雾里的

出0入0汤圆

发表于 2012-5-2 12:16:38 | 显示全部楼层
上传失败了  明天再传吧 或者给个q

出0入0汤圆

发表于 2012-5-2 15:55:40 | 显示全部楼层
关注一下,这种问题应该好解决;看看是丢包还是上溢了;
最好驱动是自己的,加调试信息,另外就是不能把BUFFER都能得太满了,最好就是把数据平摊开;
那样对系统比较好;

出0入0汤圆

发表于 2012-5-3 08:59:28 | 显示全部楼层
重点看read thread,这个demo是用ezusbsys.h的

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-5-3 14:15:08 | 显示全部楼层
楼主的现象是在FPGA内部产生的连续的数据,这个和上层用不用线程没有太大的关系(除非楼主的驱动使用了异步的机制,及IOCTRL返回PENDING),
使用线程等只能让楼主更加迷惑,还是最好能在驱动中调试比较好,APP使用简单的DOS程序就可以了;

感谢楼上提供的代码;我看了一下,感觉用处不大,使用的MFC的框架,是一个写一个读使用线程,单独的读使用线程的意义不大(完全是为了UI的不停顿);

出0入0汤圆

发表于 2012-5-3 14:30:43 | 显示全部楼层
McBee 发表于 2012-4-27 08:15
哥们  做东西先得评估需求。  如果采集音频  数据率能有多大。 为什么非得使用同步模式。
用bulk不好吗。  ...

顶这个,问问, bulk是什么意思,是异步的意思吗?

出0入0汤圆

发表于 2012-5-3 22:24:07 | 显示全部楼层
好样的,我也在自己弄这个  但是好难呀

出0入0汤圆

 楼主| 发表于 2012-5-4 00:50:56 | 显示全部楼层
chadusb 发表于 2012-5-3 08:59
重点看read thread,这个demo是用ezusbsys.h的

谢谢,我下载到了。
先仔细研读一下。

出0入0汤圆

 楼主| 发表于 2012-5-4 00:52:13 | 显示全部楼层
Julius20110 发表于 2012-5-3 22:24
好样的,我也在自己弄这个  但是好难呀

FPGA端硬件设计,USB的固件设计,PC端的软件设计,一步步来。

出0入0汤圆

 楼主| 发表于 2012-5-4 00:52:55 | 显示全部楼层
jm2011 发表于 2012-5-3 14:30
顶这个,问问, bulk是什么意思,是异步的意思吗?

bulk是块传输的意思,异步是 asynchronous

出0入0汤圆

发表于 2012-5-4 17:19:26 | 显示全部楼层
feiwa 发表于 2012-5-4 00:52
FPGA端硬件设计,USB的固件设计,PC端的软件设计,一步步来。

看样子现在我才完成第一步--FPGA端硬件设计了,还最重要的两步了,但是不知道怎么下手。可以大致的帮我说一下后面两个步骤的开发流程或者说学习的路线。
USB的固件设计:主要可以看看Cypress公司的哪些资料呀?用什么软件(开发环境)来写固件??
PC端的软件设计:感觉这个是不是就是写电脑端的应用程序呀,这个应该不太想涉及。不过应该Cypress公司自己也出了这些软件吧??比如EZ-USB Control Panel软件呀??

出0入0汤圆

 楼主| 发表于 2012-5-4 22:41:51 | 显示全部楼层
Julius20110 发表于 2012-5-4 17:19
看样子现在我才完成第一步--FPGA端硬件设计了,还最重要的两步了,但是不知道怎么下手。可以大致 ...

上传一份 68013A 开发指南给你参考一下。里面有详细的开发环境、开发流程,以及推荐的参考资料。要好好读懂 FX2技术手册。
上位机的程序你可以参考用官方的来验证通信链路,如果要完成自己定义的工作,还是得自己来开发。
PS:EZ-USB都十多年了,是很成熟的技术,Cypress提供了全面的开发例程供参考。用心做yin

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-5-5 08:52:07 | 显示全部楼层
赞 feiwa,跟着学习;

出0入0汤圆

发表于 2012-5-5 09:03:58 | 显示全部楼层
feiwa 发表于 2012-5-4 22:41
上传一份 68013A 开发指南给你参考一下。里面有详细的开发环境、开发流程,以及推荐的参考资料。要好好读 ...

真好!!谢谢啦!!

出0入0汤圆

发表于 2012-5-8 09:58:25 | 显示全部楼层
楼主解决了吗?更新一下进度吧

出0入0汤圆

 楼主| 发表于 2012-5-9 00:35:45 | 显示全部楼层
jm2011 发表于 2012-5-8 09:58
楼主解决了吗?更新一下进度吧

Hi jm2011, 我的系统目前PC端已经稳定接收数据,工作正常。
多谢关注哈!

出0入0汤圆

发表于 2012-5-9 10:09:27 | 显示全部楼层
先恭喜了,说说怎么解决的,是哪里的问题?

出0入0汤圆

 楼主| 发表于 2012-5-9 22:53:00 | 显示全部楼层
jm2011 发表于 2012-5-9 10:09
先恭喜了,说说怎么解决的,是哪里的问题?

呼呼……!!
之前的帖子已经描述得很清楚了哦。主要是PC端软件的问题。

出0入0汤圆

发表于 2012-5-19 07:00:09 | 显示全部楼层
楼主,我遇到了和你一样的问题。
你说是上位机接收的问题,是驱动的问题吗?你是加大驱动程序的缓冲区解决问题的么?能不能说说解决的思路?谢谢!

出0入0汤圆

 楼主| 发表于 2012-5-22 00:13:16 | 显示全部楼层
cf5257 发表于 2012-5-19 07:00
楼主,我遇到了和你一样的问题。
你说是上位机接收的问题,是驱动的问题吗?你是加大驱动程序的缓冲区解决 ...

Hi cf5257
我主要的问题在于上位机对数据的接收。观察到的结果是:每次接收到一个数据包,并立即处理;再接收下一个数据包时,中间有数据遗失。后采取持续接收数据,等数据接收完成以后再处理的方法,解决了丢失数据的问题。可以判断不是驱动的问题,也不是驱动程序加大缓冲区,而是在上位机软件上取了大块存储空间。
你可以用排除法,先把问题定位。要找到问题到底发生在硬件端还是软件端,然后解决掉问题就好了。

出0入0汤圆

发表于 2012-6-24 01:07:58 | 显示全部楼层
路过,顶一下

出0入0汤圆

发表于 2012-7-5 14:37:33 | 显示全部楼层
chadusb 发表于 2012-5-3 08:59
重点看read thread,这个demo是用ezusbsys.h的

您好,请问您有同步传输相关的资料吗?弄了很长时间了,接收到的数据一直不全,不知道怎么解决了。。。QQ:274684936,希望做过同步传输的高人指点,不胜感激!

出0入0汤圆

发表于 2012-12-11 22:20:31 | 显示全部楼层
wye11083 发表于 2012-4-17 00:13
噢,我想你丢包的原因应该是你收到一个包立刻处理,然后再收下一个包。注意这是不可以的。收包必须用多线 ...

有例子吗?           

出0入442汤圆

发表于 2012-12-12 15:55:10 | 显示全部楼层
mcuprogram 发表于 2012-12-11 22:20
有例子吗?

多线程可以用来保证线程挂起时不影响其它的操作。这是我的USB转HDMI的发包例子,

bool DaemonExit = false;

void CLVDSDDlg::OnBnClickedBtnStart()
{
        // TODO: Add your control notification handler code here
        if(!hDaemon)
                CreateDaemon();
}

void CLVDSDDlg::OnBnClickedBtnStop()
{
        // TODO: Add your control notification handler code here
        if(!hDaemon)
                return;
        DaemonExit = true;
        WaitForSingleObject(hDaemon,INFINITE);
        DaemonExit = false;
        hDaemon = NULL;
        dDaemon = 0;
}

#define WIDTH 1920
#define HEIGHT 1080

BYTE * pScreenBuffer = new BYTE[WIDTH*HEIGHT*2];
//BYTE * pNewScreenBuffer = new BYTE[WIDTH*HEIGHT*2];
BYTE * pUSBBuffer = new BYTE[65536-32];

struct BufferQueue
{
        BYTE * data;
        long length;
        BufferQueue * next;
        BufferQueue()
        {
                data = NULL;
                next = NULL;
                length = 0;
        }
};

struct BufferWriteThread
{
        BYTE ** Queue;
        int StartIndex;
        int EndIndex;
        CCyUSBDevice *USBDevice;
};

BufferQueue * Head = new BufferQueue();
BufferQueue * cursor = Head;

int BufferCount = 0;
HANDLE hLockBufferCount = CreateMutex(NULL,FALSE,NULL);

#define AddCounterThreashold 16
#define RemoveCounterThreashold 36

void RefreshBuffer()
{
        CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);
        while(true)
        {
                BYTE * Data = NULL;
                long Length = 0;
                WaitForSingleObject(hLockBufferCount,INFINITE);
                if(Head->next)
                {
                        Data = Head->data;
                        Length = Head->length;
                        BufferQueue * tmp = Head;
                        Head = Head->next;
                        delete tmp;
                }
                BufferCount--;
                ReleaseMutex(hLockBufferCount);
                if(Data == NULL)
                        Sleep(15);
                else
                {
                        // Write data
                        USBDevice->BulkOutEndPt->XferData(Data, Length, NULL, false);
                        // Delete buffer
                        delete []Data;
                }
                if(DaemonExit)
                        break;
        }
        USBDevice->Close();
}

#define THCNT 4
HANDLE ThreadsWriteUSB[THCNT] = {0};
DWORD ThreadsIDWriteUSB[THCNT] = {0};

void Daemon()
{
        VIDEODRIVER * videoDrv = new VIDEODRIVER();
        DWORD LastErr = 0;
        videoDrv->VIDEODRIVER_start(0,0,WIDTH,HEIGHT,16);
        if(!videoDrv->mypVideoMemory)
        {
                LastErr = GetLastError();
                MessageBox(NULL,"Error opening device.","Error opening device.",1);
                return;
        }
        if(!videoDrv->HardwareCursor())
        {
                LastErr = GetLastError();
        }
        // Monitors screen change. Color depth MUST be 16 bits
        int Count = 0;
        int StartPt = 0;
        while(true)
        {
                int BufferIndex = 0;
                //int PixelIndex = 0;
                PCHAR pNewScreenBuffer = videoDrv->myframebuffer;
                int FrameRefreshCount = 0;
                StartPt = WIDTH * 2 - StartPt;
                for(int ScreenPt = 0; ScreenPt < WIDTH * HEIGHT * 2; ScreenPt +=8)
                {
                        if(*((__int64 *)(&pScreenBuffer[ScreenPt])) != *((__int64 *)(&pNewScreenBuffer[ScreenPt])))
                        {
                                ScreenPt &= 0xFFFFFFF0;
                                *((unsigned short *)(&pUSBBuffer[BufferIndex]))=0x8007;
                                // Note the buffer is byte-addressable thus the address is byte address.
                                *((unsigned int *)(&pUSBBuffer[BufferIndex+2]))=ScreenPt;
                                *((unsigned __int64 *)(&pUSBBuffer[BufferIndex+6])) = *((unsigned __int64 *)(&pNewScreenBuffer[ScreenPt]));
                                *((__int64 *)(&pScreenBuffer[ScreenPt])) = *((__int64 *)(&pNewScreenBuffer[ScreenPt]));
                                ScreenPt += 8;
                                *((unsigned __int64 *)(&pUSBBuffer[BufferIndex+14])) = *((unsigned __int64 *)(&pNewScreenBuffer[ScreenPt]));
                                *((__int64 *)(&pScreenBuffer[ScreenPt])) = *((__int64 *)(&pNewScreenBuffer[ScreenPt]));
                                BufferIndex += 32;
                                if(BufferIndex == 65536-32)
                                {
                                        // Add Buffer
                                        cursor->data = pUSBBuffer;
                                        cursor->length = 65536-32;
                                        pUSBBuffer = new BYTE[65536-32];
                                        cursor->next = new BufferQueue();
                                        cursor = cursor->next;
                                        //long length = 65536-32;
                                        //USBDevice->BulkOutEndPt->XferData(pUSBBuffer, length, NULL, false);
                                        BufferIndex = 0;
                                        Count++;
                                        if(Count == AddCounterThreashold)
                                        {
                                                WaitForSingleObject(hLockBufferCount,INFINITE);
                                                BufferCount+=Count;
                                                Count = 0;
                                                ReleaseMutex(hLockBufferCount);
                                        }
                                        while(BufferCount >= RemoveCounterThreashold)
                                                Sleep(15);
                                        FrameRefreshCount++;
                                }
                        }
                }
                if(BufferIndex > 0)
                {
                        cursor->data = pUSBBuffer;
                        cursor->length = BufferIndex;
                        pUSBBuffer = new BYTE[65536-32];
                        cursor->next = new BufferQueue();
                        cursor = cursor->next;
                        //long length = 65536-32;
                        //USBDevice->BulkOutEndPt->XferData(pUSBBuffer, length, NULL, false);
                        BufferIndex = 0;
                        Count++;
                        if(Count == AddCounterThreashold)
                        {
                                WaitForSingleObject(hLockBufferCount,INFINITE);
                                BufferCount+=Count;
                                Count = 0;
                                ReleaseMutex(hLockBufferCount);
                        }
                        while(BufferCount >= RemoveCounterThreashold)
                                Sleep(15);
                        FrameRefreshCount++;
                }
                if(DaemonExit)
                        break;
                if(FrameRefreshCount < AddCounterThreashold)
                        Sleep(15);
        }
        videoDrv->VIDEODRIVER_Stop();
}

void CLVDSDDlg::CreateDaemon()
{
        if(ThreadsWriteUSB[0] == 0)
        {
                // Create Buffer Write daemon
                for(int i=0; i<THCNT; i++)
                {
                        ThreadsWriteUSB = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RefreshBuffer,NULL,CREATE_SUSPENDED,&ThreadsIDWriteUSB);
                        SetThreadPriority(ThreadsWriteUSB,THREAD_PRIORITY_ABOVE_NORMAL);
                        ResumeThread(ThreadsWriteUSB);
                }
        }
        hDaemon = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Daemon,NULL,CREATE_SUSPENDED,&dDaemon);
        SetThreadPriority(hDaemon,THREAD_PRIORITY_NORMAL);
        ResumeThread(hDaemon);
}

void CLVDSDDlg::OnClose()
{
        // TODO: Add your message handler code here and/or call default
        DaemonExit = true;
        CDialog::OnClose();
}

注意这不是USB显卡,而是用MirrorDriver把显示缓冲刷到FPGA板上面。
开始用的是单线程,速度奇慢,跟放幻灯片一样,然后改成全多线程,现在相当流畅了(新台机上能达到几乎无停顿的效果,老机上刷屏时比较卡)。
MirrorDriver用的是UVNC的。
其实多线程的目的,一是让一个线程不影响另一个线程,二是使用线程,同步更方便,更容易并行化。所谓GPU运算速度快,实质是GPU由几百上千个运算单元同时并行运算,速度自然就上去了。多线程程序也如此。只不过受限于USB2的速度,最大可达速度为50MB/s左右。

出0入0汤圆

发表于 2013-2-25 23:46:46 | 显示全部楼层
mark   

出0入0汤圆

发表于 2013-4-16 10:02:05 | 显示全部楼层
跟着学习,谢谢各位大神的讨论,获益匪浅

出0入0汤圆

发表于 2022-9-24 11:52:17 | 显示全部楼层
wye11083 发表于 2012-4-15 20:25
我怀疑你没有接收过大数据吧,我也是用68013的!固件我都自己改过的!
你可以试试,68013的缓冲区一共只 ...
(引用自6楼)

您好,在做68013上位机的相关开发,方便留个联系方式和您请教吗

出0入0汤圆

发表于 2022-9-24 13:33:02 | 显示全部楼层
方便留个联系方式请教解决方案吗?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 10:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表