天天看點

【補充】EZ-USB FX2 LP CY7C68013A 開發指南(2)--控制傳輸 端點0,ep0,ep0buf

端點0是用來測試驅動最好的方法,我稍後會把linux下面的驅動心得放上來,這個哥們寫了如何發送資料:http://www.lcsky.org/2.0/node/43

控制傳輸在交換少量控制資訊的時候很有用,例如傳送指令、擷取下位機狀态等,通過Cypress标準固件架構可以很友善的使用控制傳輸,僅需在DR_VendorCmnd中加入自己的處理過程即可。如:

BOOL DR_VendorCmnd(void) {

switch(SETUPDAT[1]) {

case VR_1: //自定義指令1

do_something();

break;

case VR_2: //自定義指令2

do_something_else();

break;

default:

return(TRUE);

}

return(FALSE); // no error; command handled OK

}

控制傳輸分為三個階段。

1、SETUP階段,通過SETUPDAT的8位元組寄存器進行,

SETUPDAT[0] = bmRequestType

SETUPDAT[1] = bmRequest

SETUPDAT[2:3] = wValue

SETUPDAT[4:5] = wIndex

SETUPDAT[6:7] = wLength

傳輸我們自定義的指令時,bmRequestType不用處理;bmRequest為我們自定義的指令,上位機和下位機統一即可;wValue和wIndex我們可以自由使用,共4個位元組;wLength為接下來的“資料階段”的資料長度。

2、資料階段。本階段是可選的,如果我們傳輸的資料wValue和wIndex容納不下,或者需要從裝置讀取資訊,就需要通過資料階段進行,資料階段通過EP0BUF、EP0BCH、EP0BCL寄存器進行,資料階段一次可以傳輸64位元組的資料。

本階段常常被錯誤的使用,特别是從上位機傳輸資料到下位機時,錯誤使用造成一個奇怪的現象:需要連續傳輸兩次才能在緩沖區中得到正确的資料。以下是錯誤使用的例子:

case VR_1:

a = EP0BUF[0];

b = EP0BUF[1];

c = EP0BUF[2];

d = EP0BUF[3];

EP0BCH = 0;

SYNCDELAY;

EP0BCL = 0;

SYNCDELAY;

break;

這本意是從上位機得到一些資料,并且通過最後的EP0BCH = 0;EP0BCL = 0;告訴ez-usb已經讀取完畢,但實際上,這會導緻上述的問題。仔細看TRM,發現如下的一段話:

Some CONTROL transfers do not have a DATA stage. Therefore the 8051 code that processes the SETUP data should check the length field in the SETUP data (in the 8-byte buffer at SETUPDAT) and arm endpoint zero for the DATA phase (by loading IN0BC or OUT0BC) only if the length is non-zero.[1]

至此,傳輸兩次才能得到正确資料的疑惑解開了——下行資料需要通過EP0BCH和EP0BCL告知ez-usb,以啟動資料階段!改為下述代碼:

case VR_1:

//start data phase, see TRM 7.2

if (SETUPDAT[7] != 0 || SETUPDAT[6] != 0) {

EP0BCH = SETUPDAT[7];

SYNCDELAY;

EP0BCL = SETUPDAT[6];

SYNCDELAY;

while(EP0CS & bmEPBUSY);

}

a = EP0BUF[0];

b = EP0BUF[1];

c = EP0BUF[2];

d = EP0BUF[3];

break;

另外,無資料階段的傳輸不需要在最後使用EP0BCH = 0; EP0BCL = 0來“告訴ez-usb已經讀取完畢”。

3、狀态階段。通過EP0CS寄存器,告知上位機指令是否處理等資訊。如果未處理,通過EZUSB_STALL_EP0()告知上位機;通過EP0CS |= bmHSNAK;發送ack進行确認。(此階段不需我們處理,fw.c中已處理)

我補充下如何接收資料:

if(SETUPDAT[1]==0xd2) //自定義接收資料指令

    {

        for(j=0;j<64;j++)

            EP0BUF[j]= 0x11;

        for(j=0;j<10;j++)

            EP0BUF[j]=j<5?0x55:0xAA;

        for(;j<20;j++)

            EP0BUF[j]=0xcc;

        for(;j<30;j++)

            EP0BUF[j]=0x88;

        //

        EP0BCH = 0;

        EP0BCL = 40; //要發送的個數,最大隻有64個

        return FALSE;

    }

return TRUE;

注意:處理完非标準請求指令後要傳回false,否則固件會調用EZUSB_STALL_EP0(); 而電腦認為無效,出現類似:

Vendor Request failed

A device attached to the system is not functioning.

的錯誤提示。

繼續閱讀