1. 程式人生 > >Window XP驅動開發(十七) 晶片韌體程式設計 (程式碼實現,針對USB2.0 晶片CY7C68013A)

Window XP驅動開發(十七) 晶片韌體程式設計 (程式碼實現,針對USB2.0 晶片CY7C68013A)

 一、韌體的修改

1、修改VID、PID

1、1   修改hex檔案中的VID與PID

在韌體工程下的dscr.a51檔案中修改。

1、2  修改EEPROM中的VID、PID

其中IIC_Hdr結構體中存放預設的VID、PID:    IIC_HDR IIC_Hdr = { 0xB2, 0x0547, 0x2131, 0x0000, 0x04, 0x00 };(VID: 4750  PID: 3121)

解釋VID、PID高低位元組反掉的原因:

在 x86 系統中,低位地址存放的是低位位元組,高位地址存放的是高位位元組。比如一個short 型的變數0x0102,記憶體中存放位置是02 01,02 在低地址,01 在高地址。
USB總線上的傳輸順序是先低地址,再高地址,也就是02 01。到達 FX2 後的接收順序是從低地址到高地址順序儲存,這樣02 在低地址,01 在高地址。

而 8051 的變數是低地址存放的是高位位元組,高地址存放的是低位位元組,這樣02 01 所表示的變數就變成了0x0201 的unsigned short型的變數。

下面是Hex2bix.exe的部分原始碼:

  1. case FT_IIC:  
  2.          {  
  3.             switch (IIC_Hdr.prom_type)  
  4.             {  
  5.             case 0xB0:                       // EZ-USB
  6.             case 0xB2:  
  7.                 fwrite(&IIC_Hdr,7,1,file);    // Write type, VID, PID, DID (7 bytes)
  8.                     bytes = 7;  
  9.                break;  
  10.             case 0xB4:                       // EZ-USB FX
  11.             case 0xB6:  
  12.                 fwrite(&IIC_Hdr,9,1,file);    // Write type, VID, PID, DID, Config (9 bytes)
  13.                     bytes = 9;  
  14.                break;  
  15.             case 0xC0:                       
    // EZ-USB FX2
  16.             case 0xC2:  
  17.                 fwrite(&IIC_Hdr,8,1,file);    // Write type, VID, PID, DID, Config (8 bytes)
  18.                     bytes = 8;  
  19.                break;  
  20.             default:  
  21.                Error(ERR_UNRECOGNIZED_FIRSTBYTE);  
  22.             }  
  23.          }  

當然此結構體中的VID、PID欄位可以通過Hex2bix.exe 的命令列指定。

根據CY7C68中的要求,我們會在iic檔案中的第一個位元組中放C2 ,第二三放VID,第四五放PID

得到的iic檔案頭如下:

2、設計成Slave FIFO模式。

2、1  配置端點

根據與FPGA的約定我決定只使用兩個端點:

把端點2配置成OUT,BULK型別;把端點6配置成IN,BULK型別。

在韌體工程中的dscr.a51中定義了兩種型別的配置描述符:HighSpeedConfigDscr和FullSpeedConfigDscr。(兩種型別的裝置類似,這裡只以HighSpeedConfigDscr為例)

每種型別都含有兩種節點: 介面描述、端點描述

(1)因為我們只用到端點2和端點6兩個端點,把以我們把介面描述中的Number of end points設定為2。

  1. ;; Interface Descriptor  
  2.       db   DSCR_INTRFC_LEN      ;; Descriptor length  
  3.       db   DSCR_INTRFC         ;; Descriptor type  
  4.       db   0               ;; Zero-based index of this interface  
  5.       db   0               ;; Alternate setting  
  6.       db   2               ;; Number of end points   
  7.       db   0ffH            ;; Interface class
  8.       db   00H               ;; Interface sub class
  9.       db   00H               ;; Interface sub sub class
  10.       db   0               ;; Interface descriptor string index  

(2)然後再修改端點

解釋上圖:

db 02H: 2表示是端點2,0表示是OUT方向;

db 86H: 6表示是端點6,8表示是INT方向。

2、2 修改void TD_Init(void)函式
  1. void TD_Init(void)    // Called once at startup
  2. {  
  3.         CPUCS = 0x10;   // 0001 0000
  4.                     // Bit      Value   Register    Function
  5.                     // bit.7    0       reserved
  6.                     // bit.6    0       reserved
  7.                     // bit.5    0       PORTCSTB    PortC access generates /RD & /WR strobes
  8.                     // bit.4:3  10      CLKSPD[1:0] 00 : 12M Hz (Default)
  9.                     //                              01 : 24M Hz
  10.                     //                              10 : 48M Hz
  11.                     //                              11 : Reserved
  12.                     // bit.2    0       CLKINV      0  : CLKOUT signal not inverted
  13.                     //                              1  : CLKOUT signal inverted
  14.                     // bit.1    0       CLKOE       0  : CLKOUT pin floats
  15.                     //                              1  : CLKOUT pin driven
  16.                     // bit.0    0       reserved
  17.     IFCONFIG = 0x43;// 0100 0011
  18.                     // Bit      Value   Register    Function
  19.                     // bit.7    0       IFCLKSRC    0  : External clock on the IFCLK pin
  20.                     //                              1  : Internal 30 or 48MHz (default)
  21.                     // bit.6    1       3048MHZ     0  : 30M Hz
  22.                     //                              1  : 48M Hz
  23.                     // bit.5    0       IFCLKOE     0  : Tri-state
  24.                     //                              1  : Drive
  25.                     // bit.4    0       IFCLKOL     0  : clock not inverted
  26.                     //                              1  : clock is inverted
  27.                     // bit.3    0       ASYNC       0  : FIFO/GPIF operate synchronously
  28.                     //                              1  : FIFO/GPIF operate asynchronously
  29.                     // bit.4    0       GSTATE      1  : GPIF states, Port E Alternate Functions.
  30.                     //                                   PE0 GSTATE[0]
  31.                     //                                   PE1 GSTATE[1]
  32.                     //                                   PE2 GSTATE[2]
  33.                     // bit.1:0  11      IFCFG[1:0]  00 : Ports
  34.                     //                              01 : Reserved
  35.                     //                              10 : GPIF Interface (internal master)
  36.                     //                              11 : Slave FIFO Interface(external master)
  37.     SYNCDELAY;  
  38.     EP6CFG = 0xE8;  // 1110 1000, (Size = 1024, buf = Quad (Buf x4), BULK)
  39.                     // Bit      Value   Register    Function
  40.                     // bit.7    1       VALID       0  : Does not respond to any USB traffic.
  41.                     //                              1  : Activate an endpoint(default)
  42.                     // bit.6    1       DIR         0  : OUT
  43.                     //                              1  : IN
  44.                     // bit.5:4  10      TYPE[1:0]   0  : Invalid
  45.                     //                              01 : ISOCHRONOUS
  46.                     //                              10 : BULK (default)
  47.                     //                              11 : INTERRUPT
  48.                     // bit.3    1       SIZE        0  : 512 bytes
  49.                     //                              1  : 1024 bytes
  50.                     // bit.2    0       reserved
  51.                     // bit.1:0  0       BUF[1:0]    00 : Quad
  52.                     //                              01 : Invalid
  53.                     //                              10 : Double
  54.                     //                              11 : Triple
  55.     SYNCDELAY;  
  56.     EP4CFG = 0x7F;      SYNCDELAY;  // EP4 not valid
  57.     EP2CFG = 0x7F;      SYNCDELAY;  // EP2 not valid
  58.     EP8CFG = 0x7F;      SYNCDELAY;  // EP8 not valid
  59.     FIFORESET = 0x80;               // activate NAK-ALL to avoid race conditions
  60.     SYNCDELAY;                      // see TRM section 15.14
  61.     FIFORESET = 0x02;   SYNCDELAY;  // reset, FIFO 2
  62.     FIFORESET = 0x04;   SYNCDELAY;  // reset, FIFO 4
  63.     FIFORESET = 0x06;   SYNCDELAY;  // reset, FIFO 6
  64.     FIFORESET = 0x08;   SYNCDELAY;  // reset, FIFO 8
  65.     FIFORESET = 0x00;   SYNCDELAY;  // deactivate NAK-ALL
  66.     PINFLAGSAB = 0x00;  SYNCDELAY;  // FLAGA - fixed EP2EF, FLAGB - fixed EP4EF
  67.     PINFLAGSCD = 0x00;  SYNCDELAY;  // FLAGC - fixed EP6FF, FLAGD - fixed EP8FF
  68.     PORTACFG  |= 0x80;  SYNCDELAY;  // FLAGD, set alt. func. of PA7 pin (alt. func.=alternate functions)
  69.     FIFOPINPOLAR = 0x00;SYNCDELAY;  // all signals active low
  70.     EP6FIFOCFG = 0x0C;  SYNCDELAY;  // AUTOIN=1, ZEROLENIN=1, WORDWIDE=0
  71. }  

2、3   修改void TD_Init(void)Bug(Time:2012-07-28)

2、3、1、Bug描述

從端點6可以讀到FPGA送過來的資料,可是我寫到端點2的資料FPGA卻收不到;除錯現象為:

第一次寫端點2是成功的,第二次寫就失敗了。

2、3、2、解決方法分析

一開始以為是FPGA讀時序有問題,可是FPGA工程師堅信沒有問題;

(1)當autoout=1時,主機和外部裝置直接連線,68013的8051失效,此時外部裝置是master,也就是說讀寫時序要有外部裝置產 生,你不能向68013寫資料是不可能的,原則上說你至少可以寫兩個512的資料進去,然後就寫不下去了,我驗證過了確實是這樣。
(2)如果你沒有專門的設定相關暫存器,所有的標誌預設的都是低有效的,所以應該是0是full,1是not full!
(3)FLAGB is EP2EF , FLAGA is EP2FF

          FLAGD is EP6EF,   FLAGC is EP6FF

2、3、3、解決方法
  1. void TD_Init(void)             // Called once at startup
  2. {  
  3.    // set the CPU clock to 48MHz
  4.    CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1) ;  
  5.    // set the slave FIFO interface to 48MHz
  6.   // IFCONFIG |= 0x40;
  7.    IFCONFIG = 0x43;// 0100 0011
  8.   // Registers which require a synchronization delay, see section 15.14
  9.   // FIFORESET        FIFOPINPOLAR
  10.   // INPKTEND         OUTPKTEND
  11.   // EPxBCH:L         REVCTL
  12.   // GPIFTCB3         GPIFTCB2
  13.   // GPIFTCB1         GPIFTCB0
  14.   // EPxFIFOPFH:L     EPxAUTOINLENH:L
  15.   // EPxFIFOCFG       EPxGPIFFLGSEL
  16.   // PINFLAGSxx       EPxFIFOIRQ
  17.   // EPxFIFOIE        GPIFIRQ
  18.   // GPIFIE           GPIFADRH:L
  19.   // UDMACRCH:L       EPxGPIFTRIG
  20.   // GPIFTRIG
  21.   // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
  22.   //      ...these have been replaced by GPIFTC[B3:B0] registers
  23.   // default: all endpoints have their VALID bit set
  24.   // default: TYPE1 = 1 and TYPE0 = 0 --> BULK  
  25.   // default: EP2 and EP4 DIR bits are 0 (OUT direction)
  26.   // default: EP6 and EP8 DIR bits are 1 (IN direction)
  27.   // default: EP2, EP4, EP6, and EP8 are double buffered
  28.   // we are just using the default values, yes this is not necessary...
  29.   EP1OUTCFG = 0xA0; // 10100000
  30.   EP1INCFG = 0xA0;  // 10100000
  31.   SYNCDELAY;                    // see TRM section 15.14
  32.   EP2CFG = 0xA2;   // 1010 0010       
  33.   SYNCDELAY;   
  34.   // chenyujing                   
  35.   //EP4CFG = 0xA0;
  36.   EP4CFG = 0xA0;  
  37.   SYNCDELAY;                      
  38.   EP6CFG = 0xE2;  // 1110 0010
  39.   SYNCDELAY;                      
  40.   EP8CFG = 0xE0;    // 1110 1000, (Size = 1024, buf = Quad (Buf x4), BULK)
  41.     // Bit      Value   Register    Function
  42.                     // bit.7    1       VALID       0  : Does not respond to any USB traffic.
  43.                     //                              1  : Activate an endpoint(default)
  44.                     // bit.6    1       DIR         0  : OUT
  45.                     //                              1  : IN
  46.                     // bit.5:4  10      TYPE[1:0]   0  : Invalid
  47.                     //                              01 : ISOCHRONOUS
  48.                     //                              10 : BULK (default)
  49.                     //                              11 : INTERRUPT
  50.                     // bit.3    1       SIZE        0  : 512 bytes
  51.                     //                              1  : 1024 bytes
  52.                     // bit.2    0       reserved
  53.                     // bit.1:0  0       BUF[1:0]    00 : Quad
  54.                     //                              01 : Invalid
  55.                     //                              10 : Double
  56.                     //                              11 : Triple
  57.  PINFLAGSAB = 0x8c;         // defines FLAGA as prog-level flag, pointed to by FIFOADR[1:0]
  58.  SYNCDELAY;                 // FLAGB as full flag, as pointed to by FIFOADR[1:0]
  59.  PINFLAGSCD = 0xae;         // FLAGC as empty flag, as pointed to by FIFOADR[1:0]
  60.  PORTACFG = 0x80;           // used PA7/FLAGD as a port pin, not as a FIFO flag
  61.  FIFOPINPOLAR = 0x00;       // set all slave FIFO interface pins as active low
  62.   // out endpoints do not come up armed
  63.   EP2FIFOCFG = 0x15;    SYNCDELAY;  // 0001 0101 AUTOOUT=1, ZEROLENIN=1, WORDWIDE=1         
  64.   EP6FIFOCFG = 0x0D;    SYNCDELAY;  // 0000 1101 AUTOIN=1, ZEROLENIN=1, WORDWIDE=1  
  65.                                       //bit.7 0 
  66.                                       //bit.6 INFM1 
  67.                                       //bit.5 OEP1 
  68.                                       //bit.4 AUTOOUT 
  69.                                       //bit.3 AUTOIN 
  70.                                       //bit.2 ZEROLENIN 
  71.                                       //bit.1 0 
  72.                                       //bit.0 WORDWIDE
  73.   // since the defaults are double buffered we must write dummy byte counts twice
  74.   SYNCDELAY;                      
  75.   EP2BCL = 0x80;                // arm EP2OUT by writing byte count w/skip.
  76.   SYNCDELAY;                      
  77.   EP2BCL = 0x80;  
  78.   SYNCDELAY;                      
  79.   //EP4BCL = 0x80;                // arm EP4OUT by writing byte count w/skip.
  80.   //SYNCDELAY;                    
  81.   //EP4BCL = 0x80;   
  82.   //SYNCDELAY;                    
  83.   EP6BCL = 0x80;                // arm EP4OUT by writing byte count w/skip.
  84.   SYNCDELAY;                      
  85.   EP6BCL = 0x80;     
  86.    SYNCDELAY;  
  87.  FIFORESET = 0x80; // reset all FIFOs
  88.  SYNCDELAY;  
  89.  FIFORESET = 0x02;  
  90.  SYNCDELAY;  
  91.  FIFORESET = 0x04;  
  92.  SYNCDELAY;  
  93.  FIFORESET = 0x06;  
  94.  SYNCDELAY;  
  95.  FIFORESET = 0x08;  
  96.  SYNCDELAY;  
  97.  FIFORESET = 0x00;  
  98.   // enable dual autopointer feature
  99.   AUTOPTRSETUP |= 0x01;  
  100. }  

二、測試韌體方法

測試就是去讀取FPGA寫入的資料,但怎麼判斷FPAG工程師的程式碼使寫入是有效呢?

為了在與FPGA工程師為為什麼端點時沒資料而爭執時,能讓FPGA工程師心服口服地知道是自己的問題,我們應該知道在Slave FIFO模式下的寫時序圖。

1、FPGA端的設計

在開發技術手冊上有:

翻譯成中文是:

(1)FX2LP接收內部或外部的時鐘(IFCLK最大為48MHz);

(2)SLCS#、SLRD、SLWR、SLOE、PKTENT訊號作為外部的邏輯;

(3)當用外部時鐘時,外部時鐘必須在用IFCLKSRC bit轉化到外部時鐘時表現出來;

(4)每個端點能有byte或word兩種方式可選,可通過內部的配置bit來配置;SLOE訊號使能被選擇的資料;

(5)外部的控制邏輯要保證在寫資料到一個slave FIFO時,output enable 訊號是不可用的。

3、1 Slave FIFO 同步寫

寫時序圖:

包結束觸發時序圖:

PKTEND能把最後的資料值按時鐘輸入到FIFOs.

(1)雖然PKTEND的斷言沒有特殊的要求,但是那裡有一個特殊的拐角的條件要滿足。

(2)當FIFO被配置成自動模式時,有一個增加的時序要求需要被滿足,此時它被要求連續地傳送兩個包:

一個滿包(滿被定義作為滿足AUTOENLEN暫存器中設定的級別的位元數)被自動提交,隨在它後面的是一個short one byte或word包(它們是用PKTEND手動提交的)。

在這種場景中,使用者必須確保在最後byte或word被輸入到之前的自動提交包後的上升沿後斷言PKTEND至少一個時鐘週期。

下圖表示的就是這樣應用場景,其中X表示在IN端點被配置成自動模式時AUTOINLEN暫存器被設定的值。