原创
EZ-FX2 USB开发
2010-5-28 21:07
3881
9
10
分类:
通信
这段时间一直在弄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);
用户377235 2012-12-8 10:12
用户245457 2010-10-15 10:31