CYPEESS USB3.0程式解讀之—同步FIFO(slaveFifoSync)

來源:互聯網
上載者:User

上一篇文章解讀了CYPRESS FX3的GPIO的操作過程,下面解讀同步FIFO的一個例子(slaveFifoSync)。

*生產者,消費者。

1、首先看DMA的回呼函數(cyu3dma.h):

typedef void (*CyU3PDmaCallback_t) (

 CyU3PDmaChannel *handle,     /* Handle to the DMA channel. */

 CyU3PDmaCbType_t type, /* The type ofcallback notification being generated. */

 CyU3PDmaCBInput_t *input /* Union that contains data related to the notification.

                      The input parameter willbe a pointer to a CyU3PDmaBuffer_t

variable in the cases where the callback type is CY_U3P_DMA_CB_RECV_CPLTor CY_U3P_DMA_CB_PROD_EVENT. */

       );

根據其說明,解讀如下:

1. 對每一個DMA通道,回呼函數必須被註冊。如果沒有註冊或者相應的通知事件沒有被註冊,則回呼函數不會被執行。

2. 回呼函數不能被阻塞。即不能用SLEEP()之類的函數。如果資料需要處理,必須在回呼函數之外。

3. 在生產者事件中,應用希望儘可能快地處理輸入的資料。如果緩衝的處理不能在規定的時間內完成,則輸入的可能是陳舊的資料。在自動訊號通道中,輸入參量指向最新的資料。如果處理延時,生產者socket可能覆蓋部分資料。

4. 在手動或手動IN通道模式時,輸入參量指向第一個緩衝(用於去消費者socket).如果在第二次調用時,這個緩衝仍沒有被處理,輸入參量中將是被陳舊的資料。如果資料處理必須在通道中做, CyU3PDmaChannelGetBuffer函數必須被應用,而回呼函數必須作為一個通知。

2、而輸入指標input的定義如下:

typedef struct CyU3PDmaBuffer_t

{

    uint8_t *buffer;   /* Pointer to the buffer                */

    uint16_t count;     /* Byte count of valid data in buffer   */

    uint16_t size;      /* Buffer size                          */

    uint16_t status;    /* Buffer status. This is a four bit data field…

} CyU3PDmaBuffer_t;

 

CyU3PDmaChannel這個結構中包含20個左右的參數,其中含回呼函數。

 

1> .定義了一個全域變數:CyBool_t glIsApplnActive=CyFalse; 這個變數是一個BOOL型先設為FALSE.

 

2> .程式然後定義了一個錯誤處理,CyFxAppErrorHandler()我們不處理錯誤,故是一個死迴圈語句。

 

 

3>. 然後,定義一個CyFxSlFifoApplnDebugInit()用串口來顯示一些資訊。初始化串口,設傳輸速率—只允許發不允許收,另外,採用DMA模式來處理UART。

*注意到這個函數:CyU3PDebugInit(CY_U3P_LPP_SOCKET_UART_CONS,8)表示只處理8以下的顯示,大於8將不顯示。

3、 接下來就是兩個回調處理函數

1>. DMA回呼函數 ,生產者----->消費者

CyFxSlFifoUtoPDmaCallback(

CyU3PDmaChannel *chHandle,

CyU3PDmaCbType_t type,

CyU3PDmaCBInput_t *input)

{

CyU3PReturnStatus_t status =CYU3P_SUCESS;

    If(type== CY_U3P_DMA_CB_PROD_EVENT){

    Status=  

CyU3PDmaChannelCommitBuffer(chHandler,input->buff_p.count,0);

glDMARxCount++;}

}

其中,CommitBuffer這個函數通常在手動DMA方式下被調用,它3個參數的含義分別為:DMA的控制代碼號,處理的位元組數及當前的狀態。其中地址由通道描述符隱含著。這個函數發送一個buffer向消費者socket.

 2>.DMA 回呼函數 ,消費者----->生產者

CyFxSlFifoPtoUDmaCallback (

       CyU3PDmaChannel   *chHandle,

       CyU3PDmaCbType_t  type,

       CyU3PDmaCBInput_t *input

       )

{

   CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    if(type == CY_U3P_DMA_CB_PROD_EVENT)

    {

       status = CyU3PDmaChannelCommitBuffer (chHandle, input->buffer_p.count,0);

       if (status != CY_U3P_SUCCESS)

       {

           CyU3PDebugPrint (4, "CyU3PDmaChannelCommitBuffer failed, Error code= %d\n", status);

       }

       glDMATxCount++;

    }

}

    1>.這個回調跟上一個功能類似,只是這個是 PtoU( 消費者----->生產者)。

4、 接下來,是一個比較複雜的程式

VoidCyFxSlFifoApplnStart(void)

這個函數啟動一個slave fifo應用。當從USB介面收到一個SET_CONF事件時,即設定配置事件時,它被調用。在這個函數中,端點被配置,DMA管道被建立。我們稍後將看到它就是在USB配置時被調用的。

首先,根據USB的介面速度,決定這個DMA緩衝區的大小為多少位元組。對於3.0是1024 Byte。

然後,端點配置。而得到速度是一個庫函數,如何得到速度不得而知。

不過,由於配置是在裝置描述符得到後,並且是設定地址後調用的。故此時估計PC機已經與下位機協商好速度了。例如PC為2.0則速度只能設為2.0

連接埠設為BULK方式,且被允許。突髮長度為1。尺寸也被設為1024。

 

先配置生產者:

允許端點1的收,尺寸按速度設定好,其它沒什麼。

不過IN端點1定義成0x81  OUT定義成0x01

接下來,要產生一個DMA_MANUAL通道 為U TO P

看dmaCfg的一些參數填充:

尺寸,即1024。

緩衝區個數,2個。

生產者ID號 從0X401開始的。

消費者socket連接埠,從0X103開始的。

DMA模式:為0表示按位元組計數。

DMA事件:CY_U3P_DMA_CB_PROD_EVENT表示收到一個生產者發來的緩衝

DMA的回呼函數 UtoP

頭 0

尾 0

消費socket的頭的編移 0

最少要多少個空的緩衝才會在生產者啟用前。0 表示任何時候都要啟用它。

在接收PtoU的DMA通道中,修改了這些:

產生者socketID被定義為0x100

消費者socketID被定義為0x301

回呼函數改變了。

然後是產生DMA通道。

再就是重新整理生產者端點 EP。

再就是重新整理消費者端點 EP

設定DMA傳輸尺寸。設為0表示無限。

最後將glIsApplnActive = CyTrue;  將這個全域變數設為TRUE。

 

下面是一個停止FIFO迴圈的程式。斷開時或複位時會被調用。此處暫不管它。

再下面是一個當USB在SETUP時的回調處理

由於SETUP時交由DRIVER預設處理,故直接返回一個FALSE.

 

USB事件處理回呼函數

當設定配置時,調用AppStart() 但是如果已啟用又來這麼一下,則直接調用ApplnStop()

複位和斷開時,調用ApplnStop()

 

5、下面又定義一個比較重要的函數:用於初始化GPIF和USB介面。

CyFxSlFifoApplnInit(void)   ///下面將這個函數寫於此

{

CyU3PPibClock_tpitClock;

CyU3PReturnStatus_tapiRetStatus =CY_U3P_SUCCESS;

//以下初始化p-port塊

pibClock.clkDiv =2;

pibClock.clkSrc =CY_U3P_SYS_CLK;

pibClock.isHanfDiv= CyFalse;

pibClock.isDllEnable= CyFalse;

apiRetStatus =CyU3PPibInit(CyTrue,&pibClock);   //這裡是設定好時鐘

///以下裝載GPIF   Slave_Fifo----未明白它是如何配置的。

apiRetStatus =CyU3PGpifLoad(&Sync_Slave_Fifo_2Bit_CyFxGpifConfig);

///接下來是啟動狀態機器(略),啟動USB函數:

apiRetStatus =CyU3PUsbStart(0;---開始USB功能

接下來

註冊回呼函數用於USB的SETUP過程。但它是一個返回FALSE的函數。

CyU3PUsbRegisterSetupCallback(CyFxSlFifoApplnUSBSetupCB,CyTrue);

CyU3PUsbRegisterEventCallback(CyFxSlFifoApplnUSBEventCB);交易處理不是預設的,而是我們上面定義過的。例如ApplnStart()就是在配置過程中啟動的。

 

接下來,要開始配置裝置描述符了,因為描述符中含有PID和VID的值。所以必須配置。

apiRetStatus=CyU3PUsbSetDesc(CY_U3P_USB_SET_SS_DEVICE_DESCR,NULL,(uint8*)CyFxUSB30DeviceDscr);

接下來是二進Object Storage Service描述符的設定。

接下來是裝置量化描述符。

接下來是超速配置描述符,高速裝置配置描述符,

重點看一下超速配置描述符,它含配置描述符 主要指明了介面數,配置數,配置字串(無)

特性-自供電,遠端喚醒功能

電流消耗400mA

介面描述符有:

連接埠數量,2個。

介面類 FF,子類00 介面協議0 介面協議字串0

生產者端點描述符如下:

端點地址 0x01 生產者。最大包的長度1024,資料間隔傳輸類型 0表示BULK。

超速端點公司描述符,基本上全是0。

消費者端點,與生產者基本類似。只是連接埠地址不一樣,其它一樣的。

接下來是高速,全速描述符。

接下來是語言描述符。

接下來是製造廠名描述符。 為CYPRESS

接下來是產品描述符  FX3

最後串連USB物理層。至此枚舉將開始。

}

然後定義了一個線程進入點,如下:

SlFifoAppThread_Entry(uint32input)

{

         CyFxSlFifoApplnDegugInit();  ///這裡是UART串口初始化

         CyFxSlFifoApplnInit();     ///初始化FIFO 應用在這中間是GPIF和USB的初始化程式。

          for(;;)

{ CyU3PThreadSleep(1000);   //sleep

  If(glIsApplnActive)       ///如果還是啟用狀態

         CyU3PDebugPring(6,”Datatracker:…%d,buffer send:%d\n”,glDMARxCount,glDMATxCount);

}

}

}

/////

下面是應用定義函數,估計這個函數名是不能改的。在這個函數中,我們先分配一個堆棧空間

 Ptr=CyU3PMemAlloc(CY_FX_SLFIFO_THREAD_STACK);

//然後產生一個線程

retThrdCreate =CyU3PThreadCreate(*slFifoAppThread,

“ 21:Slave_FIFO_syne”,

slFifoAppThread_Entry,

0,ptr,

CY_FX_SLFIFO_THREAD_STACK,

CY_FX_SLFIFO_THREAD_PRIOITY,

CY_FX_SLFIFO_THREAD_PRIORITY,

CYU3P_NO_THIME_SLICE,

CYU3P_AUTO_START

);

 

 

6、最後是主程式main()

首先初始化裝置,裝置指的是CPU,主要是時鐘和堆棧等。

然後cachecontrol 不用DATA CACHE。

在開發板上,由於53:56腳被串連到UART,這意味著我們要麼選擇DQ32模式,要麼選擇LppMode.

不然UART就沒辦法用了。Lpp模式好象是GPIO+UART模式,見datasheet33頁。

幾個參數 用UART,不用IIC ,不用IIS,不用SPI。沒有GPIO使用到(簡單複雜都沒有)。

然後就是設定配置了。

最後進入到核心。不返回。結束主程式。

核心於是調用某一個函數(具體實現核心已經封裝好了),也就是CyFxApplicationDefine(void)。程式就從此開始了。

*問:

1程式是如何下載到USB中去的。要怎麼做。例如將這個編譯好的代碼放到什麼目錄裡還是怎麼辦,還是啟動時,安裝driver時,自動下載,這個下載的東西是個什麼檔案格式?該放在哪裡?不明白

2.難道GPIF口上沒接任何東西, 如何將PC機發下來的資料發回到PC機上去?

生產者:USB的OUT介面1,向GPIF發送一批資料

消費者:GPIF向IN介面81,由它消費掉一批資料。然後通過IN發回PC機。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.