打印

EZ-USB 68013A开发指南(二)--转

[复制链接]
3145|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lh8008|  楼主 | 2010-8-25 11:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

7.
重点讲解
7.1

如何理解CYPRESS 68013A程序框架
CYPRESS提供了非常好的程序框架,免去了用户自己编写一些通用性比较强、模式化的程序(如果不提供,很少有人能写出如此高效,结构紧凑的程序,实际上此框架和68013A内部结构关系密切,一般人也没有足够的内部资料也不可能写出来)。在框架的基础上,用户只需在相应的地方写相应的代码即可完成USB工作。
一般来说框架可以分成3个部分。
1)
描述符文件。例如dscr.a51文件,里面定义了枚举设备的时候要用的各种描述符信息,这部分用户需要根据实际的情况自己编写。我写的时候发现一个最大的问题就是各种书籍协议版本不同,翻译质量不同,同一字段的意义表述不同,容易让人产生困惑。例如USB 1.1/2.0/2.13对设备类型的子类定义都不完全相同,所以写的时候最好几种文档对比起来写。由于USB官方网站的文档中字段解释过于专业化,所以对USB不是很熟悉的人比较难以理解其真正含义。所以要多参考不同的书籍,某种程度上降低了开发速度,但对第一次做USB开发的人来说,这也是值得的。
2)
固件文件,例如FW.C文件,这是硬件程序的函数入口。主要有以下这些方法:
void SetupCommand(void);

//
握手命令处理
void TD_Init(void);
//
初始化,完成配置,启动时调用一次
void TD_Poll(void);
//
用户处理程序,循环调用
void IO_Init(void);
//8051 IO
初始化
void REG_Init(void);
//8051
寄存器初始化
BOOL TD_Suspend(void);
//
挂起处理
BOOL TD_Resume(void);
//
唤醒处理
//以下为各种描述符的获取和设置函数,重枚举时自动调用
BOOL DR_GetDescriptor(void);

BOOL DR_SetConfiguraTIon(void);
BOOL DR_GetConfiguration(void);
BOOL DR_SetInteRFace(void);
BOOL DR_GetInterface(void);
BOOL DR_GetStatus(void);
BOOL DR_ClearFeature(void);
BOOL DR_SetFeature(void);
BOOL DR_VendorCmnd(void);
3)
功能文件,处理各种中断。例如PERIPH.C文件。8051一般默认只有四个中断,这显然不够USB使用,所以CYPRESS引入了自动向量的概念,相当于软中断,大大扩展了现有的中断数量。主要的中断有:
void ISR_Sudav(void) interrupt 0
//
收到setup包
void ISR_Sutok(void) interrupt 0 //收到SETUP令牌
void ISR_Sof(void) interrupt 0 //收到起始帧
void ISR_Ures(void) interrupt 0 //收到RESET
void ISR_Susp(void) interrupt 0
//
收到挂起信息
void ISR_Highspeed(void) interrupt 0 //高速模式
void ISR_Ep0ack(void) interrupt 0
//
正常响应ACK
void ISR_Stub(void) interrupt 0
void ISR_Ep0in(void) interrupt 0
void ISR_Ep0out(void) interrupt 0
void ISR_Ep1in(void) interrupt 0
void ISR_Ep1out(void) interrupt 0 //EP1输入中断
void ISR_Ep2inout(void) interrupt 0
//EP2
中断
void ISR_Ep4inout(void) interrupt 0
void ISR_Ep6inout(void) interrupt 0
void ISR_Ep8inout(void) interrupt 0
void ISR_Ibn(void) interrupt 0
void ISR_Ep0pingnak(void) interrupt 0
void ISR_Ep1pingnak(void) interrupt 0
void ISR_Ep2pingnak(void) interrupt 0
void ISR_Ep4pingnak(void) interrupt 0
void ISR_Ep6pingnak(void) interrupt 0
void ISR_Ep8pingnak(void) interrupt 0
void ISR_Errorlimit(void) interrupt 0
void ISR_Ep2piderror(void) interrupt 0
void ISR_Ep4piderror(void) interrupt 0
void ISR_Ep6piderror(void) interrupt 0
void ISR_Ep8piderror(void) interrupt 0
void ISR_Ep2pflag(void) interrupt 0
void ISR_Ep4pflag(void) interrupt 0
void ISR_Ep6pflag(void) interrupt 0
void ISR_Ep8pflag(void) interrupt 0
void ISR_Ep2eflag(void) interrupt 0
void ISR_Ep4eflag(void) interrupt 0
void ISR_Ep6eflag(void) interrupt 0
void ISR_Ep8eflag(void) interrupt 0
void ISR_Ep2fflag(void) interrupt 0
void ISR_Ep4fflag(void) interrupt 0
void ISR_Ep6fflag(void) interrupt 0
void ISR_Ep8fflag(void) interrupt 0
void ISR_GpifComplete(void) interrupt 0
void ISR_GpifWaveform(void) interrupt 0
特别是对于接受数据,一般都在中断中完成相应处理,“中断中适合进行少量简短的操作,不适合进行复杂操作”,这句话在此依然有效。如果要进行复杂的操作可以在TD_POLL()中进行(多数操作都是在这个函数中完成的)。
另外非常重要的一点是,中断程序的结尾应该让中断复位,允许下一次中断,有些端点的计数器也要清零并允许接受新的中断请求。例如:

EP1OUTBC = 0;
//
清空计数

EZUSB_IRQ_CLEAR(); //USB
中断复位

EPIRQ = 0x08;
//
允许EP1中断请求

7.2

68013A
端点寄存器介绍
68013A内部的寄存器约有300个上下,一次都记住是不可能的,而且每个寄存器都有8个位,也就是说一共有2000多个可以配置的位,一次都理解掌握这些位的含义也是不可能的,所幸地是开发中并不会用到所有的寄存器,但是依然强烈建议把FX2REGS.H和FX2.H走读一边,这就像读书一样,没有学会识字,再看都是天书。结合FX2 TechRefManual.pdf走读这些寄存器大约需要一到两天时间,这点时间投入还是值得的。
在通讯过程中,打交道最多的是各种端点寄存器,掌握好这些寄存器地使用对提升开发效率是很有帮助。值得特别关注的寄存器和配置位如下:
Rwuen、REVCTL、EP1OUTCFG、EP1INCFG、EP2CFG、EP4CFG、EP6CFG、EP8CFG、EP2FIFOCFG、EP4FIFOCFG、EP6FIFOCFG、EP8FIFOCFG、FIFORESET、EPIRQ、EPIE、EP1OUTBC、APTR1H、APTR1L、EXTAUTODAT1、AUTOPTRH2、AUTOPTRL2、EXTAUTODAT2、EP2BCH、EP2BCL
其中有些寄存器的设置需要连续设置多次,看似重复了,其实不然,这和设置的缓冲区数量有关。有些寄存器中间必须用SYNCDELAY来延时。这类寄存器FX2 TechRefManual.pdf上有说明。
对于EP0,用于系统握手,相关的寄存器操作基本上都由68013A的内核(SIE)来完成了。
对于EP1,分为OUT/IN两组配置和寄存器。
对于EP2~EP8,不分OUT/IN输入输出,主要有EP2CFG/ EP2FIFOCFG/ EP2BCH/EP2BCL寄存器。

7.3   
什么是自动指针
自动指针是CYPRESS提供的一个非常有用的特性。在数据交互的过程中,很多时候都涉及到数据的搬迁,比如从EP2OUT收到的数据需要转发到EP6IN上(一些转换类设备);再比如从RAM中拷贝数据到EP4IN上,传统的做法是申明两个指针,指向源和目的地址,然后用循环一个个字节拷贝,同时还要考虑增加指针地址,对于连续的空间这到不是问题,关键是如果数据需要拷贝到多个缓冲时,指针地址是循环的。这时候如果手工完成操作很容易出错。
因此CYPRESS提供了两组自动指针,用的时候一组指向源,一组指向目的地址。然后循环拷贝数据就行了,自动指针会自动指向下一个源或目的空间,不论是否是循环地址方式。这样减少了程序出错的几率。
下面的程序将EP2OUT接受到的数据拷贝到EP6IN发送出去:

if(!(EP2468STAT & bmEP6FULL))


{
// check EP6 FULL(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is full


APTR1H = MSB( &EP2FIFOBUF );


APTR1L = LSB( &EP2FIFOBUF );



AUTOPTRH2 = MSB( &EP6FIFOBUF );


AUTOPTRL2 = LSB( &EP6FIFOBUF );



count = (EP2BCH << 8) + EP2BCL;



// loop EP2OUT buffer data to EP6IN


for( i = 0x0000; i < count; i++ )


{


// setup to transfer EP2OUT buffer to EP6IN buffer using AUTOPOINTER(s)


EXTAUTODAT2 = EXTAUTODAT1;


}


EP6BCH = EP2BCH;


SYNCDELAY;


EP6BCL = EP2BCL;
// arm EP6IN


SYNCDELAY;


EP2BCL = 0x80;
// re(arm) EP2OUT


}


}

APTR1H/APTR1H通过MSB和LSB获取EP2FIFOBUF的高位地址和地位地址。
EXTAUTODAT1表示APTR1H/APTR1H指向的数据。
AUTOPTRH2/AUTOPTRL2通过MSB和LSB获取EP6FIFOBUF的高位地址和地位地址。
EXTAUTODAT2表示AUTOPTRH2/AUTOPTRL2指向的数据。

7.4

CYUSB
和CYAPI的关系
以前68013上位机程序的编写过程中,应用程序端通过调用DeviceIoControl() API或CREATEPIPE() API与驱动进行交互,继而读写控制硬件设备,在新的68013A的驱动中采用了两种新的调用方法:
第一种是继续使用DeviceIoControl()函数读写,不同的是,IOCTL控制字和老驱动完全不同,具体定义参考CYUSB.PDF。用户可以通过这些底层API完成操作。
第二种是使用CYPRESS提供的面对对象的类,一共有9个类,调用这些类的方法就可以和硬件打交道。这些类是对第一种方法的封装,使用起来非常简便。
用户可以根据需要选择这两种方法或混合使用,使用时需要加上头文件CyAPI.h和cyioctl.h,另外在项目中还要引用CyAPI.lib。

7.5

同步和异步读写的比较
CYAPI提供了同步和异步读写方式。同步方式的时候调用线程阻塞在哪里,直到读写到数据或超时;异步方式的时候调用线程立即返回。具体实例参考CYAPI.PDF。

7.6

如何用C++ BUILDER写上位机程序
1)
首先确定使用7.4中的第几种方法,添加相应的头文件和库文件。
2)
连接USB设备,确保驱动已经被正确加载。
3)
编写收发数据线程。通过开发板上的LED或CYPRESS CONSOLE或BUS HOUND分析收发正确与否。

7.7

U
盘如何正确加载驱动
在WINDOWS 2000/XP上U盘使用的PID/VID应该直接能加载操作系统默认的海量存储器的驱动程序。为了使用正确的PID/VID,可以通过以下途径:
1)
找一个现有品牌的U盘,看看他的PID/VID是何值。
2)
在注册表中查找海量存储器信息。

8.
其他问题
1)
编写上位机的时候要注意添加异常处理。
2)
调试上位机的时候,USB外设应正确连接。
3)
8051其他模块的编写请参考相应书籍。
沙发
飞翔的猪| | 2010-8-25 14:56 | 只看该作者
支持,学习

使用特权

评论回复
板凳
wangpe| | 2010-8-25 22:28 | 只看该作者
支持,支持

使用特权

评论回复
地板
Go_PSoC| | 2010-8-26 08:43 | 只看该作者
帮你顶,放置顶贴了

使用特权

评论回复
5
lh8008|  楼主 | 2010-8-26 09:54 | 只看该作者
呵呵.COOL.谢谢啦.

使用特权

评论回复
6
whzzz| | 2010-10-18 15:50 | 只看该作者
好的,好的,好的,好的,雪中送炭啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

151

帖子

1

粉丝