原创
EZ-FX2 USB开发
2010-5-28 21:07
3190
0
1
分类:
通信
这段时间一直在弄EZ-FX2(LP),现在总结一下。EX-FX2(LP)支持USB2.0高速设备接口,内部集成了一个高性能51单片机,高速USB2.0接口引擎,内部RAM/FIFO,以及GPIF(通用可编程接口)。Cypress提供了开发套件,通用驱动,并编写了一个规范的固件框架(Firmware framework)。开发时主要的工作包括三个部分:
■ 固件编程--使用Cypress提供的固件框架
■ 驱动设计--直接修改通用驱动(CYUSB.SYS)比较简单
■ 应用程序设计--直接调用CYAPI
EZ-FX2与EZ-FX2LP
区别主要是工艺不同而带来功耗不同,片内RAM大小不同,同时封装不同,还有一些小细节可以在FX2 to FX2LP文档里找到。但内部固件基本上可以不用修改直接使用。
EZUSB与CYUSB开发套件(固件框架,驱动)
EZUSB是比较老的,而CYUSB比较新。直接到Cypress网站去下载开发套件里的东西。
Slave FIFO
当外围器件为Master时,可以把FX2配置为Slave FIFO模式,可惜我自己项目中硬件连接不是这种方式,而是GPIF方式。
GPIF
GPIF是FX2(LP)通用可编程接口,能实现很多常用接口的master。其主要包括七个可编程状态机。使用Cypress提供的GPIF designer会使设计变得简单。每个可编程状态里可以执行:
■ Drive (high or low) or float the CTL outputs
■ Sample or drive the FIFO Data bus
■ Increment the value on the GPIF Address bus
■ Increment the pointer into the current FIFO
■ Trigger a GPIFWF (GPIF Waveform) interrupt
同时还可以读取以下寄存器或者外部引脚信号
■ The RDYx input pins
■ A FIFO flag
■ The INTRDY (internal RDY) flag
■ The Transaction-Count-Expired flag
TCXpire
传输计数(TC)只有在IDLE的时候才被EZ-USB检查,只有设置GPIFREADYCFG.5为1才能使得传输计数完成(TCXpire)能被一个DP state检查。注意这时GPIF的RDY5被这个内部信号替代,实际上这个信号是内部连接过去的,与GPIF外部线路无关。
flow state
1.如果不使用flow state则需要状态不停的跳转,因为GPIF状态机只允许两种状态间跳转。定义当前状态为S1,则在S1中需要查询是否已经读入或者写出相应字节数(TCXpire),如果完成则到IDLE,否则继续。但是同时还应该check端点FLAG甚至GPIF外部输入FLAG来判断是否执行读入或者写出操作。这样就必须要在两个状态里循环,读入或者写出的操作就不可能连续。
2.而用flow state则允许多种条件判断,多种状态跳转:flow或者stop flow,或者跳出flow state到IDLE。这样就能使读写操作连续,在16bit模式下GPIF的带宽可达96MB/s。
driver
驱动其实直接用通用驱动,修改cyusb.sys和cyusb.inf就行了。可以修改的地方在cyusb.pdf里有介绍。可以把VID/PID以及manufacture,string,GUID以及这两个文件名本身进行修改。一开始不知道是修改不当还是什么原因怎么都不能正常加载驱动,后来网上重新下了一个cyusb.sys和cyusb.inf,并把VID/PID重新改值才行了。同时注意在USBConsole里还是能检测到器件,说明不管你怎么改了前面的名字,通用驱动还是能被lib所调用。这样再使用cyAPI就没问题了。
应用程序
1.打开设备,并设置端点指针
do {
USBDevice->Open(d); // Open automatically calls Close() if necessary
usb_id = d;
vID = USBDevice->VendorID;
pID = USBDevice->ProductID;
d++;
} while ((d < devices ) && (vID != mVID) && (pID != mPID));
if(usb_id == devices)
AfxMessageBox("没有找到设备!",0);
else
{
int eptCount = USBDevice->EndPointCount();
for (int i=1; i<eptCount; i++)
{
bool bIn = ((USBDevice->EndPoints->Address & 0x80) == 0x80);
bool bBulk = (USBDevice->EndPoints->Attributes == 2);
if (bBulk && bIn) BulkInEpt = (CCyBulkEndPoint *) USBDevice->EndPoints;
if (bBulk && !bIn) BulkOutEpt = (CCyBulkEndPoint *) USBDevice->EndPoints;
}
}
2.BULK发送
OVERLAPPED outOvLap;
outOvLap.hEvent = CreateEvent(NULL, false, false, "CYUSB_OUT");
for(int i=0; i<512; i++)
outBuf = i;
LONG length = 512;
UCHAR *outContext = BulkOutEpt->BeginDataXfer(outBuf, length, &outOvLap);
BulkOutEpt->WaitForXfer(&outOvLap,100);//100ms
bool success;
success = BulkOutEpt->FinishDataXfer(outBuf, length, &outOvLap, outContext);
CloseHandle(outOvLap.hEvent);
3.BULK接收
OVERLAPPED inOvLap;
inOvLap.hEvent = CreateEvent(NULL, false, false, "CYUSB_IN");
ZeroMemory(inBuf, 512);
LONG length = 512;
UCHAR *inContext = BulkInEpt->BeginDataXfer(inBuf, length, &inOvLap);
BulkInEpt->WaitForXfer(&inOvLap,100); //100mS
bool success;
success = BulkInEpt->FinishDataXfer(inBuf, length, &inOvLap,inContext);
CloseHandle(inOvLap.hEvent);
billzhu_345737527 2012-12-8 10:12
zl_felix 2010-10-15 10:31