USB固件开发流程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
USB固件开发流程.txt36母爱是一缕阳光,让你的心灵即便在寒冷的冬天也能感受到温暖如春;母爱是一泓清泉,让你的情感即使蒙上岁月的风尘仍然清澈澄净。标题:USB固件开发流程2008-10-20 17:11:35
由于固件架构和固件的函数库的开发环境是Keil C51,所以针对本系统的开发也是基于这个开发环境。下图的项目窗口反映了对于本设计所需要的文件:
文件描叙如下:
(1)FW.C-固件框架,处理USB的请求和调用工作分配器中的函数。
(2)gpif.c-包含波形描述符表的文件,实现GPIF传输的波形。
(3)gpif_fifo_rw.c-用户应用程序代码,修改TD-Poll()和TD-Init()以满足用户的要求。
(4)DSCR.A51-设备描述符表。报告在FX2设备中使用哪些端点,如何配置等信息。本设计中设置EP0作为控制传输端点,EP2作为USB OUT传输端点,EP6作为USB IN传输端点。
(5)USBjmpTb.OBJ-中断向量跳转表:USB中断源INT2和GPIF/SLAVE FIFO中断源INT4。
(6)Ezusb.lib-处理设备挂起(suspend),重新开始操作(resume),I2C串口操作的函数集。
初始化:
首先在对设备读写之前,对CY7C68013的寄存器进行初始设置,这部分工作在TD_Init()函数中实现。位于gpif_fifo_rw.c文件中。实现其设置的代码如下:
void TD_Init( void )
{
CPUCS = ((CPUCS & ~ bmCLKSPD) | bmCLKSPD1); // 配置芯片时钟方式
GpifInit( ); // 初始GPIF波形
EP2CFG = 0xA0; // 配置端点2 out BULK传输模式 512字节
EP6CFG = 0xE0; // 配置端点6 in BULK传输模式 512字节 4 倍缓存区
EP4CFG = 0x00; // 无效端点4
EP8CFG = 0x00; // 无效端点8
……
EP2FIFOCFG = 0x11; // 设置端点2的USB传输方式 AUTOOUT=1
EP6FIFOCFG = 0x09; // 设置端点6的USB传输方式 AUTOIN=1
……
EP2GPIFFLGSEL = 0x01; // 设置端点2输出的GPIF标识 OUT传输 FS1=0 ,FS0=1 空标志有效
EP6GPIFFLGSEL = 0x02; //设置端点6的输入GPIF标识 IN传输 FS1=1 ,FS0=0 满标志有效
……
//配置GPIF以数据流状态传输
FLOWLOGIC = FlowStates[19];
FLOWSTB = FlowStates[23];
GPIFHOLDAMOUNT = FlowStates[26];
FLOWSTBEDGE = FlowStates[24];
FLOWSTBHPERIOD = FlowStates[25];
……
}
利用GPIF实现对控制器数据流的控制:
(1)单字的读写
为了区分所操作的数据来自哪个寄存器,在设备请求剖析器中的DR_VendorCmnd(void)函数编写不同的用户请求命令程序,如发送设备请求命令OxB3,表示读通道寄存器,然后在DR_VendorCmnd(void)中写相应的处理代码。以下是DR_VendorCmnd(void)中读通道寄存器的部分代码:
单字的读:
DR_VendorCmnd(void)
{
switch( SETUPDAT[ 1 ] )
{
……
case VX_B3: //单字读取
{
Peripheral_SetAddress(0x0002); //设置读取寄存器的地址
P
eripheral_SingleWordRead( &gdata2 );//调用单字节波形读取通道寄存器
EP0BUF[0]=VX_B3; //标准请求
EP0BUF[1]= gdata2 >>8; //高8位
EP0BUF[2]= gdata2 ; //低8位
EP0BCH= 0; //发送到上位机
EP0BCL= 3;
EP0CS |= bmHSNAK;
break;
}
……
}
}
单字的写:
单字写代码如下:
DR_VendorCmnd(void)
{
switch( SETUPDAT[ 1 ] )
{
……
case VX_B4: //单字读取
{
Peripheral_SetAddress(0x0002); //设置读取寄存器的地址
Peripheral_SingleWordWrite( &gdata2 );//调用单字节波形写取通道寄存器
EP0BUF[0]=VX_B4; //标准请求
EP0BUF[1]= gdata2 >>8; //高8位
EP0BUF[2]= gdata2 ; //低8位
EP0BCH= 0; //发送到上位机
EP0BCL= 3;
EP0CS |= bmHSNAK;
break;
}
……
}
}
(2)FIFO读写
FX2与FPGA的接口采用GPIF主模式,对于大批量的测试响应采用FIFO读的传输方式,将这些数据传送到大端点EP6的缓冲区。这是主机读FIFO操作的第一个阶段。第二过程就是数据从端点EP6缓冲区读回到主机,即USB的IN传输,在USB的IN传输中,设计不要求8051对数据进行处理,将要传输的数据自动打包 (置AUTOIN = 1),采用批量传输方式,将数据传回给主机。对于数据的最后传输阶段,采用手动模式。
FIFO读的部分代码如下所示:
if(in_enable) // IN数据传输使能
{
if ( GPIFTRIG & 0x80 ) // 若 GPIF 空闲
{
if ( !( EP68FIFOFLGS & 0x01 ) ) // if EP6 FIFO 非满
{
SYNCDELAY;
GPIFTCB1 = 0x01; // 设置传输字节数 (512 bytes/2 for word )
SYNCDELAY;
GPIFTCB0 = 0x00;
SYNCDELAY;
Setup_FLOWSTATE_Read(); // 设置数据流状态寄存器
SYNCDELAY;
GPIFTRIG = GPIFTRIGRD | GPIF_EP6; //触发GPIF读波形,//开始写数
//据到FIFO
SYNCDELAY;
while( !( GPIFTRIG & 0x80 ) ) // 等待 GPIFTRIG.7 GPIF
//Done bit
{ ; }
SYNCDELAY;
xFIFOTC_IN = ( ( EP6FIFOBCH << 8 ) + EP6FIFOBCL );//读取的
//字节数
if( xFIFOTC_IN < 512 ) //不满512字节数据包的处理
{
INPKTEND = 0x06; //发送短数据包给上位机
}
Tcount= 0 ;
}
}
}
首先判断EP6缓冲区是否为满,若EP6缓冲区已满则不能往里写数据,TD_Poll( )不停判断直到EP6缓冲区为空,或放弃FIFO读操作。然后设置FIF0的地址,要读的数据的个数;最后触发FIFO读波形,等待直到GPIFDONE位为1。设置EP6缓冲区数据的个数,完成数据从JTAG主控芯核到端点EP6缓冲区的读操作。
FIFO写:
在TD_Poll( )函数中负责处理块数据的传输,处理代码如下所示:
if( GPIF
TRIG & 0x80 ) // if GPIF interface IDLE
{ if ( ! ( EP24FIFOFLGS & 0x02 ) ) //判断EP2是否非空,即EP2中有数据
{
SYNCDELAY;
GPIFTCB1 = MSB(Tcount) ; // 设置传输字节数
SYNCDELAY;
GPIFTCB0 = LSB(Tcount) ;
SYNCDELAY;
Setup_FLOWSTATE_Write( ); //设置数据流状态寄存器
SYNCDELAY;
GPIFTRIG = GPIFTRIGWR|GPIF_EP2; //触发GPIF写波形,
//开始写数据到FIFO
SYNCDELAY;
while( !( GPIFTRIG & 0x80 ) ) // 等待GPIFTRIG.7 GPIF Done bit
{
;
}
}
}
首先判断EP2缓冲区是否为空,若EP2缓冲区为空则其中并无数据可写,TD Poll ( )不停判断直到EP2缓冲区为不空,或放弃FIFO写操作;然后设置FIFO传输字节数;最后触发FIFO写波形,完成数据从端点EP2缓冲区到FIFO的写操作。