转载引用于 http://blog.csdn.net/chenyujing1234
一、固件的修改
修改是基于CYPRESS官方提供的固件工程Bulkloop基础上。(获得方法参考http://blog.csdn.net/chenyujing1234/article/details/7622901)
1、修改VID、PID
1、1 修改hex文件中的VID与PID
在固件工程下的dscr.a51文件中修改。
1、2 修改EEPROM中的VID、PID
Hex2bix.exe(具体源码自己查看http://download.csdn.net/detail/chenyujing1234/4423966)把hex文件转为iic文件时加入了VID与PID。
其中IIC_Hdr结构体中存放默认的VID、PID: IIC_HDR IIC_Hdr = { 0xB2, 0x0547, 0x2131, 0x0000, 0x04, 0x00 };(VID: 4750 PID: 3121)
解释VID、PID高低字节反掉的原因:
在 x86 系统中,低位地址存放的是低位字节,高位地址存放的是高位字节。比如一个short 型的变量0x0102,内存中存放位置是02 01,02 在低地址,01 在高地址。
USB总线上的传输顺序是先低地址,再高地址,也就是02 01。到达 FX2 后的接收顺序是从低地址到高地址顺序存储,这样02 在低地址,01 在高地址。
而 8051 的变量是低地址存放的是高位字节,高地址存放的是低位字节,这样02 01 所表示的变量就变成了0x0201 的unsigned short型的变量。
下面是Hex2bix.exe的部分源码:
- case FT_IIC:
- {
- switch (IIC_Hdr.prom_type)
- {
- case 0xB0: // EZ-USB
- case 0xB2:
- fwrite(&IIC_Hdr,7,1,file); // Write type, VID, PID, DID (7 bytes)
- bytes = 7;
- break;
- case 0xB4: // EZ-USB FX
- case 0xB6:
- fwrite(&IIC_Hdr,9,1,file); // Write type, VID, PID, DID, Config (9 bytes)
- bytes = 9;
- break;
- case 0xC0: // EZ-USB FX2
- case 0xC2:
- fwrite(&IIC_Hdr,8,1,file); // Write type, VID, PID, DID, Config (8 bytes)
- bytes = 8;
- break;
- default:
- Error(ERR_UNRECOGNIZED_FIRSTBYTE);
- }
- }
当然此结构体中的VID、PID字段可以通过Hex2bix.exe 的命令行指定。
根据CY7C68中的要求,我们会在iic文件中的第一个字节中放C2 ,第二三放VID,第四五放PID
得到的iic文件头如下:
2、设计成Slave FIFO模式。
根据 <<http://blog.csdn.net/chenyujing1234/article/details/7604266>>对我的系统的设计,把CY7C68配置成Slave FIFO模式。
2、1 配置端点
根据与FPGA的约定我决定只使用两个端点:
把端点2配置成OUT,BULK类型;把端点6配置成IN,BULK类型。
在固件工程中的dscr.a51中定义了两种类型的配置描述符:HighSpeedConfigDscr和FullSpeedConfigDscr。(两种类型的设备类似,这里只以HighSpeedConfigDscr为例)
每种类型都含有两种节点: 接口描述、端点描述
(1)因为我们只用到端点2和端点6两个端点,把以我们把接口描述中的Number of end points设置为2。
- ;; Interface Descriptor
- db DSCR_INTRFC_LEN ;; Descriptor length
- db DSCR_INTRFC ;; Descriptor type
- db 0 ;; Zero-based index of this interface
- db 0 ;; Alternate setting
- db 2 ;; Number of end points
- db 0ffH ;; Interface class
- db 00H ;; Interface sub class
- db 00H ;; Interface sub sub class
- db 0 ;; Interface descriptor string index
(2)然后再修改端点
解释上图:
db 02H: 2表示是端点2,0表示是OUT方向;
db 86H: 6表示是端点6,8表示是INT方向。
2、2 修改void TD_Init(void)函数
- void TD_Init(void) // Called once at startup
- {
- CPUCS = 0x10; // 0001 0000
- // Bit Value Register Function
- // bit.7 0 reserved
- // bit.6 0 reserved
- // bit.5 0 PORTCSTB PortC access generates /RD & /WR strobes
- // bit.4:3 10 CLKSPD[1:0] 00 : 12M Hz (Default)
- // 01 : 24M Hz
- // 10 : 48M Hz
- // 11 : Reserved
- // bit.2 0 CLKINV 0 : CLKOUT signal not inverted
- // 1 : CLKOUT signal inverted
- // bit.1 0 CLKOE 0 : CLKOUT pin floats
- // 1 : CLKOUT pin driven
- // bit.0 0 reserved
- IFCONFIG = 0x43;// 0100 0011
- // Bit Value Register Function
- // bit.7 0 IFCLKSRC 0 : External clock on the IFCLK pin
- // 1 : Internal 30 or 48MHz (default)
- // bit.6 1 3048MHZ 0 : 30M Hz
- // 1 : 48M Hz
- // bit.5 0 IFCLKOE 0 : Tri-state
- // 1 : Drive
- // bit.4 0 IFCLKOL 0 : clock not inverted
- // 1 : clock is inverted
- // bit.3 0 ASYNC 0 : FIFO/GPIF operate synchronously
- // 1 : FIFO/GPIF operate asynchronously
- // bit.4 0 GSTATE 1 : GPIF states, Port E Alternate Functions.
- // PE0 GSTATE[0]
- // PE1 GSTATE[1]
- // PE2 GSTATE[2]
- // bit.1:0 11 IFCFG[1:0] 00 : Ports
- // 01 : Reserved
- // 10 : GPIF Interface (internal master)
- // 11 : Slave FIFO Interface(external master)
- SYNCDELAY;
- EP6CFG = 0xE8; // 1110 1000, (Size = 1024, buf = Quad (Buf x4), BULK)
- // Bit Value Register Function
- // bit.7 1 VALID 0 : Does not respond to any USB traffic.
- // 1 : Activate an endpoint(default)
- // bit.6 1 DIR 0 : OUT
- // 1 : IN
- // bit.5:4 10 TYPE[1:0] 0 : Invalid
- // 01 : ISOCHRONOUS
- // 10 : BULK (default)
- // 11 : INTERRUPT
- // bit.3 1 SIZE 0 : 512 bytes
- // 1 : 1024 bytes
- // bit.2 0 reserved
- // bit.1:0 0 BUF[1:0] 00 : Quad
- // 01 : Invalid
- // 10 : Double
- // 11 : Triple
- SYNCDELAY;
- EP4CFG = 0x7F; SYNCDELAY; // EP4 not valid
- EP2CFG = 0x7F; SYNCDELAY; // EP2 not valid
- EP8CFG = 0x7F; SYNCDELAY; // EP8 not valid
- FIFORESET = 0x80; // activate NAK-ALL to avoid race conditions
- SYNCDELAY; // see TRM section 15.14
- FIFORESET = 0x02; SYNCDELAY; // reset, FIFO 2
- FIFORESET = 0x04; SYNCDELAY; // reset, FIFO 4
- FIFORESET = 0x06; SYNCDELAY; // reset, FIFO 6
- FIFORESET = 0x08; SYNCDELAY; // reset, FIFO 8
- FIFORESET = 0x00; SYNCDELAY; // deactivate NAK-ALL
- PINFLAGSAB = 0x00; SYNCDELAY; // FLAGA - fixed EP2EF, FLAGB - fixed EP4EF
- PINFLAGSCD = 0x00; SYNCDELAY; // FLAGC - fixed EP6FF, FLAGD - fixed EP8FF
- PORTACFG |= 0x80; SYNCDELAY; // FLAGD, set alt. func. of PA7 pin (alt. func.=alternate functions)
- FIFOPINPOLAR = 0x00;SYNCDELAY; // all signals active low
- EP6FIFOCFG = 0x0C; SYNCDELAY; // AUTOIN=1, ZEROLENIN=1, WORDWIDE=0
- }
2、3 修改void TD_Init(void)Bug(Time:2012-07-28):
2、3、1、Bug描述
从端点6可以读到FPGA送过来的数据,可是我写到端点2的数据FPGA却收不到;调试现象为:
第一次写端点2是成功的,第二次写就失败了。
2、3、2、解决方法分析
一开始以为是FPGA读时序有问题,可是FPGA工程师坚信没有问题;
后来从网上 http://bbs.ednchina.com/BLOG_ARTICLE_192827.HTM 得到启发,是因为没有对PINFLAGSAB、PINFLAGSCD进行配置。
(1)当autoout=1时,主机和外部设备直接连接,68013的8051失效,此时外部设备是master,也就是说读写时序要有外部设备产 生,你不能向68013写数据是不可能的,原则上说你至少可以写两个512的数据进去,然后就写不下去了,我验证过了确实是这样。
(2)如果你没有专门的设定相关寄存器,所有的标志默认的都是低有效的,所以应该是0是full,1是not full!
(3)FLAGB is EP2EF , FLAGA is EP2FF
FLAGD is EP6EF, FLAGC is EP6FF
2、3、3、解决方法
- void TD_Init(void) // Called once at startup
- {
- // set the CPU clock to 48MHz
- CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1) ;
- // set the slave FIFO interface to 48MHz
- // IFCONFIG |= 0x40;
- IFCONFIG = 0x43;// 0100 0011
- // Registers which require a synchronization delay, see section 15.14
- // FIFORESET FIFOPINPOLAR
- // INPKTEND OUTPKTEND
- // EPxBCH:L REVCTL
- // GPIFTCB3 GPIFTCB2
- // GPIFTCB1 GPIFTCB0
- // EPxFIFOPFH:L EPxAUTOINLENH:L
- // EPxFIFOCFG EPxGPIFFLGSEL
- // PINFLAGSxx EPxFIFOIRQ
- // EPxFIFOIE GPIFIRQ
- // GPIFIE GPIFADRH:L
- // UDMACRCH:L EPxGPIFTRIG
- // GPIFTRIG
- // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
- // ...these have been replaced by GPIFTC[B3:B0] registers
- // default: all endpoints have their VALID bit set
- // default: TYPE1 = 1 and TYPE0 = 0 --> BULK
- // default: EP2 and EP4 DIR bits are 0 (OUT direction)
- // default: EP6 and EP8 DIR bits are 1 (IN direction)
- // default: EP2, EP4, EP6, and EP8 are double buffered
- // we are just using the default values, yes this is not necessary...
- EP1OUTCFG = 0xA0; // 10100000
- EP1INCFG = 0xA0; // 10100000
- SYNCDELAY; // see TRM section 15.14
- EP2CFG = 0xA2; // 1010 0010
- SYNCDELAY;
- // chenyujing
- //EP4CFG = 0xA0;
- EP4CFG = 0xA0;
- SYNCDELAY;
- EP6CFG = 0xE2; // 1110 0010
- SYNCDELAY;
- EP8CFG = 0xE0; // 1110 1000, (Size = 1024, buf = Quad (Buf x4), BULK)
- // Bit Value Register Function
- // bit.7 1 VALID 0 : Does not respond to any USB traffic.
- // 1 : Activate an endpoint(default)
- // bit.6 1 DIR 0 : OUT
- // 1 : IN
- // bit.5:4 10 TYPE[1:0] 0 : Invalid
- // 01 : ISOCHRONOUS
- // 10 : BULK (default)
- // 11 : INTERRUPT
- // bit.3 1 SIZE 0 : 512 bytes
- // 1 : 1024 bytes
- // bit.2 0 reserved
- // bit.1:0 0 BUF[1:0] 00 : Quad
- // 01 : Invalid
- // 10 : Double
- // 11 : Triple
- PINFLAGSAB = 0x8c; // defines FLAGA as prog-level flag, pointed to by FIFOADR[1:0]
- SYNCDELAY; // FLAGB as full flag, as pointed to by FIFOADR[1:0]
- PINFLAGSCD = 0xae; // FLAGC as empty flag, as pointed to by FIFOADR[1:0]
- PORTACFG = 0x80; // used PA7/FLAGD as a port pin, not as a FIFO flag
- FIFOPINPOLAR = 0x00; // set all slave FIFO interface pins as active low
- // out endpoints do not come up armed
- EP2FIFOCFG = 0x15; SYNCDELAY; // 0001 0101 AUTOOUT=1, ZEROLENIN=1, WORDWIDE=1
- EP6FIFOCFG = 0x0D; SYNCDELAY; // 0000 1101 AUTOIN=1, ZEROLENIN=1, WORDWIDE=1
- //bit.7 0
- //bit.6 INFM1
- //bit.5 OEP1
- //bit.4 AUTOOUT
- //bit.3 AUTOIN
- //bit.2 ZEROLENIN
- //bit.1 0
- //bit.0 WORDWIDE
- // since the defaults are double buffered we must write dummy byte counts twice
- SYNCDELAY;
- EP2BCL = 0x80; // arm EP2OUT by writing byte count w/skip.
- SYNCDELAY;
- EP2BCL = 0x80;
- SYNCDELAY;
- //EP4BCL = 0x80; // arm EP4OUT by writing byte count w/skip.
- //SYNCDELAY;
- //EP4BCL = 0x80;
- //SYNCDELAY;
- EP6BCL = 0x80; // arm EP4OUT by writing byte count w/skip.
- SYNCDELAY;
- EP6BCL = 0x80;
- SYNCDELAY;
- FIFORESET = 0x80; // reset all FIFOs
- SYNCDELAY;
- FIFORESET = 0x02;
- SYNCDELAY;
- FIFORESET = 0x04;
- SYNCDELAY;
- FIFORESET = 0x06;
- SYNCDELAY;
- FIFORESET = 0x08;
- SYNCDELAY;
- FIFORESET = 0x00;
- // enable dual autopointer feature
- AUTOPTRSETUP |= 0x01;
- }
二、测试固件方法
测试就是去读取FPGA写入的数据,但怎么判断FPAG工程师的代码使写入是有效呢?
为了在与FPGA工程师为为什么端点时没数据而争执时,能让FPGA工程师心服口服地知道是自己的问题,我们应该知道在Slave FIFO模式下的写时序图。
1、FPGA端的设计
在开发技术手册上有:
翻译成中文是:
(1)FX2LP接收内部或外部的时钟(IFCLK最大为48MHz);
(2)SLCS#、SLRD、SLWR、SLOE、PKTENT信号作为外部的逻辑;
(3)当用外部时钟时,外部时钟必须在用IFCLKSRC bit转化到外部时钟时表现出来;
(4)每个端点能有byte或word两种方式可选,可通过内部的配置bit来配置;SLOE信号使能被选择的数据;
(5)外部的控制逻辑要保证在写数据到一个slave FIFO时,output enable 信号是不可用的。
3、1 Slave FIFO 同步写
写时序图:
包结束触发时序图:
PKTEND能把最后的数据值按时钟输入到FIFOs.
(1)虽然PKTEND的断言没有特殊的要求,但是那里有一个特殊的拐角的条件要满足。
(2)当FIFO被配置成自动模式时,有一个增加的时序要求需要被满足,此时它被要求连续地发送两个包:
一个满包(满被定义作为满足AUTOENLEN寄存器中设置的级别的比特数)被自动提交,随在它后面的是一个short one byte或word包(它们是用PKTEND手动提交的)。
在这种场景中,用户必须确保在最后byte或word被输入到之前的自动提交包后的上升沿后断言PKTEND至少一个时钟周期。
下图表示的就是这样应用场景,其中X表示在IN端点被配置成自动模式时AUTOINLEN寄存器被设置的值。