68013 燒錄方式 及iic生成
硬體程式燒錄
1)因為本產品要求將二進位制程式碼和硬體PID/VID燒錄在EEPROM,而不是使用CYPRESS推薦的線上下載方式,所以外部採用了8K的EEPROM。上電後68013A會將EEPROM中的資料和程式載入到RAM中執行。
2)HEX檔案只是68013A上8051的程式程式碼,還要加上PID/VID等資訊才能正確執行,CYPRESS在開發包中提供了HEX2BIN.EXE這個工具,可以根據HEX生成完備的IIC檔案,將此檔案燒錄到EEPROM上即可。
3)HEX2BIN.EXE的使用方法如下:
將XXX.HEX檔案拷貝到HEX2BIN.EXE所在目錄,開啟CMD,按如下格式輸入:
hex2bix -i -o xxx.iic xxx.hex -f 0xC2( -v 0x1234 -p 0x1234 )這個地方的PID VID 不用加,沒有用,生成的IIC檔案的pid vid 碼是與hex檔案相關,即有程式檔案中裝置描述符設定。
-i 表示輸出檔案,也就是IIC檔案
-o 表示輸入檔案,也就是HEX檔案
-f 表示68013A傳送PID/VID的方式,這裡為C0,即從EEPROM上讀取。
-v 表示VID的BCD碼,開發階段使用1234
-p 表示PID的BCD碼,開發階段使用1234
4)將生成的IIC檔案用燒寫器燒錄到EEPROM上,本專案使用的是深圳思泰佳電子公司的NSP通用燒寫器,此燒寫器不支援IIC型別,選擇BIN型別可替代
韌體除錯完畢後,可以將其轉化為IIC檔案燒寫到EEPROM中,採用C2方式啟動,這樣68013就會從EEPROM中獲取程式和VID、PID,不需要每次上電都下載韌體了。
首先需要將KEIL編譯好的hex檔案轉化為iic檔案,可以使用cypress提供的hex2bix,格式如下:
Hex2bix -i -f 0xC2 -o usb_sfifo.iic usb_sfifo.hex
-i表示要生成iic檔案,-f表示燒寫後採用C2方式啟動(程式、VID、PID都從EEPROM讀取),後面依次是要生成IIC檔案的檔名和原始檔的檔名,關於其他引數的用法可以參見hex2bix的幫助。
通過USB連線到計算機後,通過Cypress USB Console即可燒寫。開啟EZ-USB Interface,點選Lg EEPROM,然後選擇剛才生成好的IIC檔案可以。
需要注意的是在硬體上不同容量的EEPROM接法是不一樣的,否則燒寫之後也無法啟動。如下圖所示,大容量EEPROM的A0管腿需要上拉。
另外需要注意的是SCL SDA需要上拉,否則也會出現讀取問題。
1.先把68013與EEPROM連線的I2C的SDA斷開。
2.插上USB線連線電腦
3.啟動軟體
4.把68013與EEPROM連線的I2C的SDA連上
5.在USB CONSOLE上點lg eeprom就可以下載了
相當於開始的時候68013沒有EEPROM裝置,EEPROM用片記憶體儲的描述符資料進行列舉。
主機就通過這個自動的描述符同68013進行通訊。接著連上把68013與EEPROM連線的I2C的SDA連上,
4.3 驅動的識別
1)將EEPROM連到 68013A 上後,接上USB線,上電。計算機提示找到新硬體,要求安裝驅動。
2)CYPRESS針對 68013A 提供了全新的驅動程式CYUSB.SYS。這個驅動使用了新的API,所以上位機的編寫上和舊的方式完全不同。底層的IOCTL控制字的定義也完全不同,詳見CYAPI.PDF和CYUSB.PDF。
3)安裝驅動之前,必須先根據VID/PID正確編輯CYUSB.INF檔案,在檔案中新增自己的PID/VID程式碼和裝置描述,連線裝置時,將根據硬體上的PID/VID查詢INF檔案中對應的驅動,如果找不到,在裝置管理器中將顯示“68013 EEPROM MISSING”的字樣。
4)詳細的INF配置方法參考CYUSB.PDF PART1/PART2/PART3。這裡不在贅述。
5)安裝驅動時候找到修改好的CYUSB.INF檔案,驅動將被正確安裝,此時裝置可以正常使用。
4.4 測試過程
1)被正確識別的裝置可以在CYPRESS CONSOLE上看到裝置資訊。如圖:
2)CYPRESS CONSOLE的具體使用方法請參考CyConsole.chm。
3)要注意的是,除EP0/EP1外,當其他端點Max Pkt Size大小為64位元組時,表示工作在USB 1.1模式,有可能是軟體的原因,也有可能是外圍上拉電阻的問題。開發中要特別注意。
5. 推薦開發流程
5.1 看本介紹USB 2.0協議的書,對USB 2.0協議有所瞭解。推薦《USB 2.0原理與工程開發》
5.2 看CYUSB.PDF文件。瞭解驅動安裝方法。
5.3 看KEIL C51的書籍,熟悉C51的程式設計方法,熟悉KEIL C程式設計環境。
5.4 看CYPRESS提供的例程,瞭解 68013A 程式設計框架。推薦《EZ-USB 2100系列微控制器原理、程式設計及應用》(基本框架類似,部分暫存器定義不同)。
5.5 對照USB 2.0協議,編寫dscr.a51檔案,配置各種描述符。
5.6 結合FX2 TechRefManual.pdf,研讀FW.C、PERIPH.C、FX2REGS.H、FX2.H,瞭解暫存器的定義。
5.7 根據系統需求編寫響應程式碼,有開發板時,根據開發版上的LED來測試程式正確與否。
5.8 根據CYAPI.PDF CYUSB.PDF編寫上位機通訊程式。
同步讀取資料方法 XferData();
非同步讀取資料方法 BeginDataXfer()/WaitForXfer()/FinishDataXfer();
5.9 除錯程式。
5.10 編寫其他8051上的程式,並繼續除錯。
6. 釋出時應提供的檔案
1)CYUSB.SYS
2)CYUSB.INF
3)XXX.IIC
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_Ep 0in (void) interrupt 0
void ISR_Ep0out(void) interrupt 0
void ISR_Ep 1in (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、APTR 1L 、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收到的資料需要轉發到EP 6IN 上(一些轉換類裝置);再比如從RAM中拷貝資料到EP 4IN 上,傳統的做法是申明兩個指標,指向源和目的地址,然後用迴圈一個個位元組拷貝,同時還要考慮增加指標地址,對於連續的空間這到不是問題,關鍵是如果資料需要拷貝到多個緩衝時,指標地址是迴圈的。這時候如果手工完成操作很容易出錯。
因此CYPRESS提供了兩組自動指標,用的時候一組指向源,一組指向目的地址。然後迴圈拷貝資料就行了,自動指標會自動指向下一個源或目的空間,不論是否是迴圈地址方式。這樣減少了程式出錯的機率。
下面的程式將EP2OUT接受到的資料拷貝到EP 6IN 傳送出去:
if(!(EP2468STAT & bmEP6FULL))
{ // check EP6 FULL(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is full
APTR1H = MSB( &EP2FIFOBUF );
APTR 1L = LSB( &EP2FIFOBUF );
AUTOPTRH2 = MSB( &EP6FIFOBUF );
AUTOPTRL2 = LSB( &EP6FIFOBUF );
count = (EP2BCH << 8) + EP2BCL;
// loop EP2OUT buffer data to EP 6IN
for( i = 0x0000; i < count; i++ )
{
// setup to transfer EP2OUT buffer to EP 6IN buffer using AUTOPOINTER(s)
EXTAUTODAT2 = EXTAUTODAT1;
}
EP6BCH = EP2BCH;
SYNCDELAY;
EP6BCL = EP2BCL; // arm EP 6IN
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其他模組的編寫請參考相應書籍。