1. 程式人生 > >FPGA+DSP SRIO通訊(三)——基於LSU的資料傳輸

FPGA+DSP SRIO通訊(三)——基於LSU的資料傳輸

之前的配置中我們知道如何配置通道速率、設定deviceID。
也就是馬路已經鋪設好了,我們應該造車了。
搏一搏,單車變摩托!
SRIO不是單車,而是摩托車,我們需要搏一搏,把這個摩托車造出來,在我們已經鋪設好的高速路上飛馳。

目錄

下面提及的關於LSU暫存器的詳細知識,在我的以下兩篇部落格中都大篇幅詳細講過,如果本文說的不清楚,大家可以看一下我之前的這兩篇部落格:

一、LSU暫存器基本介紹

SRIO用來高速傳輸大量資料,用的就是LSU,LSU的全稱是Load/Store Unit,一共有8個LSU(Load/Store Unit),每個LSU都有自己的7個暫存器,即LSU_REG0-LSU_REG6,REG0-REG4用來儲存控制資訊,REG5、REG6用來儲存命令和狀態資訊。除了REG6,其它暫存器都是可讀可寫的,只有REG6有隻讀和只寫兩種模式。

所有關於SRIO傳輸的重要屬性都在LSU的7個暫存器中,我們所要做的,就是對這7個暫存器賦上不同的值,以實現我們的目的。對於這7個暫存器的說明,都在我之前的部落格裡,說的不清楚的地方,在文末的參考文獻裡有詳細說明。

LSU的這7個暫存器就像摩托車的零件,每一個零件都有不同的功能,但是隻有組裝起來,成為一輛完整的車架,才能有具體功能。

而對於這7個暫存器的賦值,TI官方給出的兩種方式,我都提供出來:
1、對每一個暫存器單獨賦值,這需要知道每個暫存器的每個域的具體功能,才能得心應手地配置。因為我的ti資料夾安裝在c盤,所以我的SRIO文件的路徑為:

C:/ti/pdk_C6678_1_1_2_6/packages/ti/csl/docs/doxygen/html/csl__srio_aux_8h.html

該文件中有以下API是用來對每個暫存器單獨賦值的(截圖):
這裡寫圖片描述

任意點開上面的一個API,就會有其使用方式,這裡我以reg0為例,提供其使用方式:
這裡寫圖片描述
2、對指定的功能進行編輯
這種配置方式只需要知道一些特定名詞,如bytecount,即傳輸的位元組數,dstID,即目的地的deviceID等等。該方式的API也可以在下面的路徑中找到。

C:/ti/pdk_C6678_1_1_2_6/packages/ti/csl/docs/doxygen/html/csl__srio_aux_8h.html

下面是一段示例程式,我的工程中採用的就是這種配置方法,簡明易懂,也比較推薦這種方法:

    CSL_SrioHandle     hSrio;//宣告一個SRIO控制代碼
    SRIO_LSU_TRANSFER  lsuTransfer;//宣告一個LSU傳輸

    // Open the CSL SRIO Module 0
    hSrio = CSL_SRIO_Open (0);//開啟CSL SRIO模組0
    ...
    // 對該LSU傳輸的資訊進行賦值. 
    lsuTransfer.rapidIOMSB    = 0x0;
    lsuTransfer.rapidIOLSB    = (Uint32)&tx_buffer[0];
    lsuTransfer.dspAddress    = (Uint32)&rx_buffer[0];
    lsuTransfer.bytecount     = 256;
    lsuTransfer.doorbellValid = 0;
    lsuTransfer.intrRequest   = 1;
    lsuTransfer.supInt        = 0;
    lsuTransfer.xambs         = 0;
    lsuTransfer.priority      = 2;
    lsuTransfer.outPortID     = 1;
    lsuTransfer.idSize        = 1;
    lsuTransfer.srcIDMap      = 0;
    lsuTransfer.dstID         = 0xDEAD;
    lsuTransfer.ttype         = 4;
    lsuTransfer.ftype         = 5;
    lsuTransfer.hopCount      = 0;
    lsuTransfer.doorbellInfo  = 0;

    // 賦值完成之後,用下面的函式完成對整個傳輸的啟動和配置
    CSL_SRIO_SetLSUTransfer (hSrio, 1, &lsuTransfer);
    ...

二、LSU傳輸流程

知道了如何組裝LSU,我們還需要知道LSU具體是如何運作的。關於LSU的運作,我之前的文章SRIO學習(六)——Direct I/O 操作(一)也詳細說過,具體分3個步驟:

1、查詢REG6來確定LSU是否繁忙,如果繁忙則等待,如果不繁忙,則通過對REG6的寫入來鎖定LSU。
2、對REG0-REG4進行寫入,來確定具體傳輸的目標,地址等資訊。
3、對REG5進行寫入,寫明包型別(Ftype、Ttype),並觸發傳輸。

三、LSU方式_傳送程式碼的實現

綜上所述,我們在最終使用LSU傳輸時,就要融合上面提到的兩方面內容,一是LSU暫存器編輯,二是LSU資料傳輸流程。具體見以下程式碼:

    /*首先包含一些公共的庫,大家用的時候貼上一下就行*/
    #include <stdio.h>
    #include <stdint.h>
    #include <math.h>
    #include <string.h>
    #include <c6x.h>

    /* CSL Chip Functional Layer */
    #include <ti/csl/csl_chipAux.h>
    #include <ti/csl/csl_chip.h>

    /* PSC CSL Include Files */
    #include <ti/csl/csl_psc.h>
    #include <ti/csl/csl_pscAux.h>

    /* CSL SRIO Functional Layer */
    #include <ti/csl/csl_srio.h>
    #include <ti/csl/csl_srioAux.h>
    #include <ti\csl\csl_srioAuxPhyLayer.h>

    #include <ti/csl/tistdtypes.h>
    #include <ti/csl/cslr_device.h>
    #include <ti/csl/csl_tsc.h>
    #include <ti/csl/csl_cacheAux.h>

    SRIO_LSU_TRANSFER  lsuTransfer0;//宣告一個LSU傳輸物件

    /* 函式名:Lsu0_Init
     * 函式作用:對LSU傳輸物件LsuTransfer0進行配置
     * 在配置LSU時本身不需要這麼多引數,一般只設置幾個引數就行,在部落格最後我會給出簡化版配置  */ 

    void Lsu0_Init()
    {
        lsuTransfer0.rapidIOMSB    = 0x0;//傳輸目標地址擴充套件高32bit域,即如果地址位數比32bit多時,會用到它,一般為0
        //lsuTransfer0.rapidIOLSB    = (unsigned int)0x00100000;//傳輸目標地址低32bit,一般情況的目標地址就是這個
        //lsuTransfer0.bytecount     = 32768;//LSU傳輸多少個byte
        //lsuTransfer0.dspaddress    = 0x32c00000;//需要LSU傳送的數的地址
        lsuTransfer0.doorbellValid = 0;//是否需要在傳輸完成後傳送doorbell,0表示不需要
        lsuTransfer0.intrRequest   = 1;//傳輸完成後是否需要產生中斷,1表示需要
        lsuTransfer0.supInt        = 0;//是否需要“壓制”傳輸完成後的中斷,0表示不壓制
        lsuTransfer0.xambs         = 0;//指明擴充套件地址最高位,一般情況下不需要
        lsuTransfer0.priority      = 0;//LSU傳輸的優先順序,該屬性只有在多個LSU傳輸時才有意義
        lsuTransfer0.outPortID     = 0;//LSU要用哪個port傳出,由CPU和nodeID共同決定
        lsuTransfer0.idSize        = 1;//DEVICEID使用8bit還是16bit格式的。1表示使用16bit格式。
        lsuTransfer0.srcIDMap      = 0;//確定在該LSU中使用哪個srcID對映暫存器
        lsuTransfer0.dstID         = 0xABCD;//LSU傳輸目標的DEVICEID,可以看到這裡是16bit格式的
        lsuTransfer0.ttype         = 4;//包的型別由ttype和ftype同時決定,一般主要有寫、讀、帶響應寫、帶響應讀等包型別。具體見參考文獻
        lsuTransfer0.ftype         = 2;
        lsuTransfer0.hopCount      = 0;//Hop Count域是為型別8的維護包準備的。
        lsuTransfer0.doorbellInfo  = 0;//DRbll Info域是為型別10的包(doorbell包)準備的。具體包型別見下文中的Table2-23
        }

    /* 
     * 函式名:SRIO_READ
     * 函式功能:配置好LSU的源地址、目的地址、傳輸總位元組數,並啟動傳輸 
     */

    void SRIO_READ(unsigned int SRC_ADDR,unsigned int BYTES,unsigned int DST_ADDR)
{
        int print = 0;
        unsigned char               context;
        unsigned char               transID;
        unsigned char               count;
        unsigned char               compCode = 1;
        unsigned char               contextBit = 0;
        lsuTransfer0.dspAddress   = SRC_ADDR;
        lsuTransfer0.bytecount    = BYTES;
        lsuTransfer0.rapidIOLSB   = DST_ADDR;
        // 得到LSU背景傳輸資訊
        CSL_SRIO_GetLSUContextTransaction (hSrio, &context, &transID);

        // 在LSU0上啟動傳輸
        CSL_SRIO_SetLSUTransfer (hSrio, 0, &lsuTransfer0);

        // 迴圈直到LSU傳輸完成.
        while (1)
        {
            if (CSL_SRIO_IsLSUBusy (hSrio, 0) == FALSE)
                break;
        }
        //得到完成碼(除錯用)
        CSL_SRIO_GetLSUCompletionCode (hSrio, 1, transID, &compCode, &contextBit);
}

    /*
     * main.c
     */
void main(void) {
    /* 
     * 對於函式enable_srio,SrioDevice_init,都在我在上篇文章中提到的device_srio_loopback.c檔案中,主要就是通道配置和DEVICEID配置,前兩篇部落格也都講述過。文末會附上該檔案的下載地址。
     */

    /* 給SRIO模組供電 */
    if (enable_srio () < 0)
    {
        printf ("Error: SRIO PSC Initialization Failed\n");
        return;
    }

    /* 初始化SRIO */
    if (SrioDevice_init() < 0)
        return;

    /* SRIO已經能夠操作了. */
    printf ("SRIO Driver has been initialized\n");

    Lsu0_Init();

    /* 從地址0x00000001 傳送256bytes資料到 deviceID為0xABCD的裝置上的地址0x00000002去 */
    SRIO_READ(0x00000001, 256, 0x00000002);
    }

這裡寫圖片描述
注意圖中的包型別指的是Ftype的值,而不是最前面的標號。

這樣,我們的摩托也完成了,摩托可以載著貨物在高速上飛奔了,但是有時候來了個電話,你必須停下來,那要怎麼停下來呢?,請看下章——中斷系統。

參考文獻

PS:歡迎大家與我討論文章中的問題,包括反對我的觀點。

本章特別緻謝:感謝北航的王悅人學長在我什麼都不懂的時候耐心回答我的萌新問題。