fpga与PC通过cy7c68013a芯片进行通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fpga与PC通过cy7c68013a芯片进行通信相关的知识,希望对你有一定的参考价值。

可以实现fpga向PC发送数据,但是FPGA却接收不到PC发来的数据 请问是怎么回事 是固件的问题么 void TD_Poll( void )这个函数为空可以么

如果你用FPGA的signal tapII监测不到信号,那估计是USB控制器的固件问题。 参考技术A 你这是跑Nios啊?

CY68013 FPGA通信联调总结

1. 简介

CY68013是一款USB 2.0芯片,常用作fpga与pc的接口芯片,其硬件可以自动处理USB协议,也可以在里面下载对应的固件程序,由固件程序来完成USB协议的通信。我们只关心USB数据的传输,协议的不作深究,能用就行。

2. 开发

2.1 CY68013

2.1.1 CY68013资料摘抄

主要参考文档:

参考文档描述
EZ-USB_TRM_001-13670_0E.pdffx2的参考手册,相当于UserGuide
CY7C68013A.pdffx2的电气特性,相当于DataSheet,slave fifo各个控制信号的时序图在这份文档中有写
EZ-USB FX2单片机原理、编程及应用_钱峰编.pdf实际上是TRM的翻译,翻得通俗一点
AN61345.pdfCypress 提供的 slave fifo的接口介绍,以及demo代码的分析
圈圈教你玩USB.pdf这个是一款飞利浦的USB PHY芯片的参考书,USB协议需要自己处理,有助于理解USB的专业术语的含义及协议

详细摘抄

《EZ_USB FX2单片机原理、编程及应用 读书笔记》
《FX2 TRM 摘抄》

其余相关的Cypress USB开发资料:
Cypress的开发环境:
cy3684_ez_usb_fx2lp_development_kit_15.exe
CySuiteUSB_3_4_4_B184.exe

一个是开发固件程序的,里面自带了一个简化版的Keil;另一个是开发上位机软件的,还包含了Cypress默认的驱动程序、API库等等。安装的时候最好默认都安装在C盘下,会省很多麻烦。

cy7c68013 实现slave fifo: AN61345 + 例程demo

AN63787 - EZ-USB® FX2LP GPIF and Slave FIFO Configuration Examples Using an 8-Bit Asynchronous Interface

AN58069 - Implementing an 8-Bit Parallel MPEG2-TS Interface Using Slave FIFO Mode in FX2LP

AN63620 - Configuring a Xilinx Spartan-3E FPGA Over USB Using EZ-USB FX2LP™

CrazyBingo系列:
Crazy Bingo CY68013开发例程
链接地址可能不准,直接百度即可,AET与非网上都有
(1)01:USB+FPGA摄像头算法处理-持续更新中 http://blog.chinaaet.com/detail/34481.html
(2)02:CY7C68013特性介绍 http://blog.chinaaet.com/detail/34482.html
(3)03: CY7C68013A相关驱动版本说明 http://blog.chinaaet.com/detail/34483.html
(4)04: CY7C68013 Slave FIFO及PCB设计 http://blog.chinaaet.com/detail/34484.html
(5)05: CY3684 68013开发套件安装指南 http://blog.chinaaet.com/detail/34485.html
(6)06: USB 68013驱动程序的安装 http://blog.chinaaet.com/detail/34486.html
(7)07: USB68013 Driver数字证书一说 http://blog.chinaaet.com/detail/34487.html
(8)08: USB 68013 自定义VID&PID、版本、生厂商等信息 http://blog.chinaaet.com/detail/34488.html
(9)09: USB 68013调试工具的使用之CyConsole助手的使用 http://blog.chinaaet.com/detail/34489.html
(10)10: USB 68013调试工具的使用之Streamer USB传输测速 http://blog.chinaaet.com/detail/34490.html
(11)11: USB 68013调试开发之各种EEPROM下载处理办法以及为什么??http://blog.chinaaet.com/detail/34534.html
(12)12:USB68013 Firmware开发指南之 CY3684固件例程分析 http://blog.chinaaet.com/detail/34534.html
(13)13:USB68013 Firmware开发指南之Keil UV4工程配置选项 http://blog.chinaaet.com/detail/34533.html
(14)14:USB68013 Firmware开发指南之8051 SFR寄存器说明 http://blog.chinaaet.com/detail/34534.html

前方高能
CY68013资料网盘分享

2.1.2 Firmware开发

2.1.2.1 CY68013驱动安装

Cypress提供了官方驱动,win7 x64 32都是支持的
安装上驱动以后,可以使用库函数来和fx2芯片进行通讯。
需要修改 cyusb.inf 文件来安装对应的驱动

    ;for all platforms
    ;在这里增加对应的 VID 和 PID 设备
    [Device]
    %VID_XXXX&PID_XXXX.DeviceDesc%=CyUsb, USB\\VID_XXXX&PID_XXXX


    ;for windows 2000 non intel platforms
    [Device.NT]
    %VID_XXXX&PID_XXXX.DeviceDesc%=CyUsb, USB\\VID_XXXX&PID_XXXX


    ;for x86 platforms
    [Device.NTx86]
    %VID_XXXX&PID_XXXX.DeviceDesc%=CyUsb, USB\\VID_XXXX&PID_XXXX


    ;for x64 platforms
    [Device.NTamd64]
    %VID_XXXX&PID_XXXX.DeviceDesc%=CyUsb, USB\\VID_XXXX&PID_XXXX

    [Strings]
    ;在这里添加对应于自己的VID PID的描述
    CYUSB_Provider    = "Cypress"
    CYUSB_Company     = "Cypress Semiconductor Corporation"
    CYUSB_Description = "Cypress Generic USB Driver"
    CYUSB_DisplayName = "Cypress USB Generic"
    CYUSB_Install     = "Cypress CYUSB Driver Installation Disk"
    VID_XXXX&PID_XXXX.DeviceDesc="Cypress USB Generic Driver (3.4.7.000)"
    CYUSB.GUID="{AE18AA60-7F6A-11d4-97DD-00010229B959}"
    CYUSB_Unused      = "."

2.1.2.2 程序下载

Cypress 提供了开发工具包里的 CyConsoleCyUSB Center,可以用来下载程序
程序下载分两种,

2.1.2.2.1 直接下载到RAM中运行

如果连接了eeprom,上电会从eeprom里面启动,已经配置了寄存器;
启动后再下载程序到RAM中运行,寄存器又被配置了一遍,但是这样可能会受到第一次配置的影响,USB通信出现问题。
一般是用哪一位就配置哪一位,其余的寄存器的bit保留原值。

regVal |= bmBIT0;

这样其余像 bit7->1 都是保留原值,可能会被第一次配置干扰。

爆出
error code 997,实际上是last error = 997

cy7c68013都搭配有eeprom,eeprom里面存的程序,上电启动的时候,先把程序从eeprom加载到内部ram中,即0000-0x3FFF的区域,然后才开始运行;注意与USB相关的寄存器配置以及EP buffer都在上面0xE200-0xFFFF区域!!!这个区域不会有程序,也就是说程序下载的时候不会覆盖到这片区域。初始程序启动后,对usb相关寄存器进行了配置,然后连上usb,驱动配合脚本自动下载固件,这个固件被下载到0x0000-0x3FFF区域去执行,不会覆盖0xE200-0xFFFF区域的USB急促安琪和EP buffers,下载期间不会断电。新下载的固件启动执行,对USB regs 和EP buffers进行操作,但是只是改变指定位的数据,其他设置保留eeprom中初始程序的USB寄存器设置,所以会发现,新固件的代码功能并没有提现出来或者说不正常!!! 直接把程序烧写到eeprom就可以了!!!

2.1.2.2.2 下载到附带配套的eeprom芯片里

上电从eeprom加载程序运行

下载程序到eeprom中造成USB通信异常的案例
① 现象描述:
一开始的时候,向CY68013的eepron里下载程序,能和pc通信上,只是数据有些不正常;
修改程序以后,重新下载程序到CY68013的eeprom中,再上电,pc提示无法识别的usb设备

无法识别的USB设备

设备管理器上显示 unknown device
设备管理器显示

VID / PID 都没有显示
设备管理器查看VID PID
usb根本没有通信上!!!!

解决办法
推测原因
最后一个版本的程序下载进去有问题,即eeprom里的程序有问题,
然后又每次是通过eeprom来启动,
加载程序运行,然后每次枚举都不成功,所以显示未知设备

最关键的是要擦除eeprom里的原程序,然后更新为新程序即可。

还好,在Crazy Bingo的博客上找到了解决方案:
http://blog.chinaaet.com/crazybingo/p/34531
CrazyBingo CY68013 eeprom设计
EZ_USB手册上如是说:

The EZ-USB boot loader supports two I2C EEPROM types:

■ EEPROMs with slave address 1010 that use an 8-bit internal address (for example, 24LC00, 24LC01/B,24LC02/B).
■ EEPROMs with slave address 1010 that use a 16-bit internal address (for example, 24AA64, 24LC128, 24AA256).
EEPROMs with densities up to 256 bytes require only a single address byte; larger EEPROMs require two address bytes. The EZ-USB must determine which EEPROM type is connected — one or two address bytes — so that it can properly read the EEPROM.

The EZ-USB uses the EEPROM device-address pins A2, A1, and A0 to determine whether to send out one or two bytes of address. As shown in Table 13-11, single byte address EEPROMs must be strapped to address 000, while double byte address EEPROMs must be strapped to address 001.

CY68013 TRM eeprom配置说明

EEPROM是可以配置地址的,A2,A1,A0就是用来配置地址的,而fx2只认 001 的地址,
只要改变了eeprom的地址,eeprom就会失效,fx2就无法从eeprom加载程序,只能硬件回复usb请求

1)先短路J13,使得A0变低
2)usb连接到pc,检测到usb设备,驱动无法自动安装
3)手动安装对应的cypress usb驱动
4)断开J13,使A0变高电平
5)打开CyConsole,下载程序到eeprom,ok,usb通信恢复

2.1.2.3 .a51文件的作用

注意,.a51的文件描述符是用来上报给pc机的,用库函数获取到的描述符都是从这个.a51里来的
相当于这个文件决定了跟pc报告说我有哪些端点,以及端点的大小
.a51文件必须和fx2真正在运行时配置的端点一致才可以,否则会造成,上位机调用库函数和fx2通讯不上

HighSpeedConfigDscr里面需要改成4个端点的,而且下面要写4个端点的描述符!!
.a51配置

2.1.2.4 Max PktSize含义

最大只能发这么多

端点大小 和 Max PktSize是不一样的
端点大小是缓存区的大小,2和6可以配置为512 和 1024两种
4 和 8就只能配置为512

Max PktSize可以设置为64,最大usb包长为64

2.1.2.5 芯片没办法软件复位!!!!

如果端点fifo满了,仍旧连续发送,芯片会挂点,软件复位没有用,必须重新上电,hard reset!!!
清空FIFO,在TD_Poll()中进行FIFO_RESET,严格来说是在outpkt_end后进行FIFO_RESET,然后再bulkout就失败了!!!!不知道什么原因!!!

    //FIFO复位
    SYNCDELAY;
    FIFORESET = 0x80;             // activate NAK-ALL to avoid race conditions
    SYNCDELAY;                    // see TRM section 15.14
    FIFORESET = 0x02;             // reset, FIFO 2
    SYNCDELAY;                    //
    FIFORESET = 0x04;             // reset, FIFO 4
    SYNCDELAY;                    //
    FIFORESET = 0x06;             // reset, FIFO 6
    SYNCDELAY;                    //
    FIFORESET = 0x08;             // reset, FIFO 8
    SYNCDELAY;                    //
    FIFORESET = 0x00;             // deactivate NAK-ALL
    SYNCDELAY;                    //


    //清空usb残留,不让usb残留提交到slave fifo接口处
    //这样fpga端在接收的时候不会收到乱七八糟的数据
    //加了下面这几句话,再在这个后面执行FIFORESET就不能bulkout了,不知为何
    OUTPKTEND = 0x82; // Arm both EP2 buffers to "prime the pump"
    SYNCDELAY;
    OUTPKTEND = 0x82;
    SYNCDELAY;
    OUTPKTEND = 0x84;
    SYNCDELAY;
    OUTPKTEND = 0x84;
    SYNCDELAY;

上下两段换一下先OUTPKTEND 然后再 FIFORESET就会出现上面说的问题

2.2 fpga

2.2.1 slve fifo 接口控制通讯

参考文档:

AN61345.pdf
CY69013A.pdf

截图全部取自CY7C68013A的datasheet,不是TRM,TRM里面没有标出来时间
IFCLK是fx2输入脚的IFCLK,确实是上升沿去采样的,

2.2.1.1 基本连接



2.2.1.2 时序分析

这里只采用同步读写的方式!!!
读:



ToeOn 以后的数据才是有效的数据。

写:


最坏情况下,写入以后,满的FLAGS需要13.5ns才能出来,超过周期的一半了,得等到下降沿以后才能检测到IN FIFO满

2.2.1 实验调试经历

2.2.1.1 stream_in

2.2.1.1.1 上电后fpga发送了很多0x00回来

PC端从USB处收到很多的0x00
一开始以为是fifo里面有缓存,而且因为配置的是512 x4大小,所以收到了512 x4的 0x00 实际上是fpga实际一直控制在写00 00
用万用表来测量fx2的slwr脚一直显示为0V!!!
后来发现,fpga管脚锁错了!!!!!!没有把slwr脚锁到对应的fx2的slwr脚,造成了slave fifo的异常写入
心中千万只草泥马呼啸而过………………

2.2.1.1.2 fpga的短包发送出现问题

发送短包要拉低pkt_end信号脚,但什么时候拉低,某不知名网友说:

pkt_end <= slwr_n

然而,

pkt_end <= slwr_n 处理短包,结果不对,完全不对!!!

才发到001D,就写了0x1D个数,flagd就拉低了,显示fifo满了,但是fifo可是512bytes x4大小的!!!

尝试pkt_end <= ‘1’; 每次等齐512字节自动发送的话,这样子,flagd就是正常的。
估计是pkt_end的操作有问题

重新翻看时序图:

短包发送时序图

还有TRM里的一句说明

then pulse the PKTEND pin,就是slwr_n写到fifo里面,然后都结束了,再拉低PKTEND一个周期就可以了。

修改后重新下载,实验结果符合预期,能够正常收到短包数据,每次7个16bit数据;
Bulk in failed是故意尝试只让fpga发一次,pc机上请求读取两次中的第二次,返回失败是正常的,因为fifo里确实没有数据了。

另外注意一点,EP6FIFOCNT看起来一直为0,实际上含义不一样,只要pkt_end以后,EP6FIFOCNT就会被清0,说这些数据已经被打包出去了,但是实际还是占用空间的,FIFO的flag该是Full还是full,所以会出现EP6 为Full,但是EP6FIFOCNT= 0。

超过512bytes用pktend发送出现问题:
开启短包发送,但是fpga发送超过512字节给pc的时候出现问题,会收到两个512字节数据,后面的512字节是一串乱码
原因:
fx2程序中开了autoin,然后fpga发送端又有pkt_end拉低一个周期造成的矛盾,到了512字节已经autoin发送了,然后由pkt_end发送一遍,第二遍的时候发送的不知道是什么数据

2.2.1.2 stream_out

2.2.1.3 bulk_loopback

配置情况
fpga内配置1024 x16bit的fifo
fx2 配置为
EP2OUT 512 x4
EP6IN 512 x4

连续发9个512byte过去,然后收到的数据并不完整,收到第5包,后面的数据就没有了(工程关闭ep6 autoin,无论是长包还是短包,都是用pkt_end来驱动发送的
ep6fifocnt 一直为2
通过chipscope观察,发现死在了read_sig状态

实际上是因为fpga内部fifo提前发出了full信号,即没到1024就发出了full信号,导致没法把存在EP2OUT端点的6,7,8,9包数据全部都写入fpga内部fifo,还剩了2个byte数据在EP2OUT内,EP2OUT数据又没读空,死在read状态过不去,状态又没法跳转。

修正后,只能读到7包数据,最后两个数还不对,变成了08

发现第7包的前两个字节会丢
在第七包只发了两个字节4C4B的情况下,什么也收不到
chipscope

dout能看到有4C4B说明确实这个值是写入到fpga的fifo中的,但是从fifo中读出然后写入到fx2的slave fifo中是有问题的。

关键的关键是,EP6IN fifo满的时候,按照检测flagd然后控制rden,又由fifo返回的valid信号来驱动slwr_n, 就会造成少写入一个数据到EPIN6 FIFO里面,但是这个数据已经从fpga内部fifo中读出来了,就造成了丢失一个数据。归根到底,是因为valid信号和rd_en信号有一个时钟周期的延时。
为了弥补这一个数据,需要在fx2中设置EP IN full的标志位提前一个单位告知FIFO FULL,
EP6FIFOCFG = 0x41; // AUTOIN=0, WORDWIDE=1 , ZEROLENIN=0, INFM1 = 1,这样就不会漏数据了。

数据通路分析:
EP2OUT 到 fpga内部fifo:
在往fpga内部fifo写的时候,fpga内部fifo会提前一个单元给出fifo满信号,这样会导致有一个单元的数据,这里对应2bytes数据,残留在EPOUT FIFO中,得等到pc把EPIN fifo的数据读掉一些,然后fpga内部fifo释放出来一些空间,才会把EPOUT的残留数据读出来写入fpga内部fifo。但是这个并不影响最终pc接收的情况,因为看起来还是和原来一样512bytes取出来。

fpga内部fifo 到EP6IN:
就是前面关键的关键分析的

2.2.2 fpga小技巧

2.2.2.1 同步电路外面加一层逻辑电路保护,保证不会误读出来然后没人接收

2.2.2.2 inout口处理

fdata_in专门用作输入,真实值 或者 0
data_out专门用作输出,真实值 或者 0

    --fdata_in作为输入
    process (sloe)
    begin
        if (sloe)               --输入
            fdata_in <= fdata;
        else
            fdata_in <= conv(0, 16);
        end if;
    end process;
    data <= fdata_in            --以后输入就从fdata_in去取就行

    --data_out作为输出
    process (sloe)
    begin
        if (sloe = '0')             --输出
            fdata <= data_out;
        else
            fdata <= (whenothers=>'z');
        end if;
    end process;

    data_out <= "xxxxxxxxxx";   --以后输出都给到data_out就行  

2.2.2.3 高低字节序

从pc到fpga:

fpga fifo
din 16
dout 64

din 按顺序写入0xabcd, 0xefgh,0xijkl, 0xmnop
dout 0xabcd_efgh_ijkl_mnop (即先存入的为高16bit)

一个数 Num = 0x0102030405060708;
全部是以高字节在高地址来画的表格,字节数变大时间在后

路径byte0byte1byte2byte3byte4byte5byte6byte7
inbuf0x080x070x060x050x040x030x020x01
slave fifo dout 16bit0x080x070x060x050x040x030x020x01
fpga fifo din 16bit0x080x070x060x050x040x030x020x01
fpga fifo dout 64bit0x020x010x040x030x060x050x080x07

读出来 Num2 = 0x0708050603040102

Num2 和 Num1 的关系为,高低字节倒序排列,然后每16bit内部两字节交换。
想要输入Num 和 读出来的 Num2相等,
必须先对 Num 作 高低字节倒序排列,然后每16bit内部两字节交换

从fpga 到 pc

fpga fifo
din 32
dout 16

din 0xab_cd_ef_gh
dout 按顺序读出 0xabcd, 0xefgh

同理的,reg fifo out dout为32位, Num = 0x05060708;
byte3为最高字节

路径byte0byte1byte2byte3
reg fifo out din 32bit0x080x070x060x05
reg fifo out dout 16bit0x060x050x080x07
slave fifo dout0x060x050x080x07
outbuf0x060x050x080x07

Num2 = 0x07080506

2.2.2.4 用modelsim仿真的时候会出现红色线段

红色线段表示非稳定状态,数值状态为未知,可能的原因如下
① 信号未赋予初始值
② inout口处理不当,两端同时进行out输出造成不稳定状态

2.2.2.5 chipscope无法捕获信号

停留在转圈圈的状态,提示 waiting for core to be armed,slow or stopped clock

这个问题肯定是因为输给chipscope的时钟没有跑起来!!!
有一些复位信号的原因,外部复位信号没有锁定也没有赋值,可能就接到pll的rst上,导致一直在复位,时钟就没有跑起来

时钟最好从pll的bufg之后接到chipscope上!!!

奇奇葩葩的问题:
今天碰到一个很奇怪的现象,原来的工程死活就不行,fpga程序一烧进去,就收到一大坨数据,EP6直接满了,EP8也有数据,特别奇怪!!!后来换了一个工程就好了

2.3 上位机

2.3.1 开发环境配置

fx2上位机开发 vs2013配置1

fx2上位机开发 vs2013配置2

剩下的就是

#include "CyAPI.h"

就可以使用了

2.3.2 Cypress 库函数的使用

Cypress C++库函数参考文档

CyAPI.pdf

主要函数

2.3.2.1 open()
    Example
    CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);
    // Attempt to open device #0
    if (USBDevice->DeviceCount() && !USBDevice->Open(0)) {
    USBDevice->Reset();
    USBDevice->Open(0);
    }
2.3.2.2 EndPointOf( )
    Example
    UCHAR eptAddr = 0x82;
    CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);
    CCyUSBEndPoint *EndPt = USBDevice->EndPointOf(eptAddr);
    if (EndPt) EndPt->Reset( );
2.3.2.3 XferData( )

这个函数 IN 和 OUT端点都可以用的, bulkin的话就是接收,bulkout就是发送

    Example
    CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);
    unsigned char buf[] = "hello world";
    LONG length = 11;
    if (USBDevice->BulkOutEndPt)
    USBDevice->BulkOutEndPt->XferData(buf, length);

2.3.2 调试

1)控制端点操作不成功

一个是因为地址不对,另一个是因为长度不对,length必须是LONG,然后如果有连续的函数套用,必须把长度设成可更改的引用,LONG &lenth,否则会返回失败。

2)上位机短包发送限制

每一个短包实际上占用了一个buffer缓冲,512x4 16bit的端点配置,一共就只能发送4次短包就会满
如下图所示:

每次发送12字节,只能发送4次,再发送就失败了!!!!
而且一旦出现发送失败,无论是软件复位还是其他什么的都不好使!!!必须重新上电才可以!!!

3)大小端顺序

要注意,无论是发还是收,都是小端序。
PC机先发0x03,再发0x04, 在slave_fifo里读出来是0x0403
另外pc机内部于是小端序,所以

u8 outbuf[2];
*(u16*)&(outbuf[0]) = 0x0403;          //outbuf[0]= 0x03, outbuf[1]= 0x04

然后outbuf发送,在fpga端收到的就是0x0403,正好和发送的时候的数据是一样的!!!

fpga发送 0x0304, pc上先收到0x04,后收到0x03

    u8 inbuf[2];
    regVal = *(u16*)&(inbuf[0]);    //inbuf[0]= 0x04, inbuf[1]= 0x03; regVal = 0x0304

3. 核心代码

===It’s a secret!!!===

以上是关于fpga与PC通过cy7c68013a芯片进行通信的主要内容,如果未能解决你的问题,请参考以下文章

EZ_USB salveFIFO

(转)USB小白学习之路FX2LP cy7c68013——Slave FIFO 与FPGA通信

cy7c68013A 为啥会烧录失败

cy7c68013a56pin的芯片,固件设置它工作在slaveFIFO模式,EP2设置为out,1024字节

庖丁解牛——CY7C68013A开发框架

CY7C68013A控制传输