SylixOS DMA子系統之一

1. DMA子系統簡介

1.1      DMA簡介。

DMA的英文拼寫是“Direct Memory Access”,是一種數據不經過CPU處理,直接由DMA控制器從一塊物理內存搬運到另一塊物理內存的數據交換模式。在DMA模式下,CPU只須向DMA控制器下達指令,讓DMA控制器來處理數據的傳送,數據傳送完畢再把信息反饋給CPU,這樣就很大程度上減輕了CPU資源佔有率,可以大大節省系統資源。

 

2. DMA設備驅動模型

2.1      DMA驅動模型簡介

SylixOS中的DMA架構位於“libsylixos/SylixOS/system/device/dma/”下,DMA驅動多用於外設驅動或總線驅動中。主要功能是從一塊物理地址向另一塊物理地址搬運數據。本文以mini2440的通用DMA驅動爲例。

DMA設備庫對DMA設備進行了封裝,設備驅動僅需要提供初始化函數和回調函數即可。

在註冊DMA設備驅動之前,需要先安裝DMA設備庫,其原型如程序清單 2‑1:

程序清單 2‑1

#include <SylixOS.h>

INT    API_DmaDrvInstall (UINT               uiChannel,

                         PLW_DMA_FUNCS  pdmafuncs,

                         size_t               stMaxDataBytes)

函數API_DmaDrvInstall原型分析:

l  此函數執行成功返回PLW_DMA_FUNCS的地址。

DMA設備需要調用dmaGetFuncs函數綁定驅動並創建設備,其函數原型如程序清單 2‑2:

 

程序清單 2‑2

#include <SylixOS.h>

PLW_DMA_FUNCS  dmaGetFuncs (UINT        iChannel,

ULONG   *pulMaxBytes)

函數dmaGetFuncs原型分析:

l  此函數成功返回ERROR_NONE,失敗返回PX_ERROR

l  參數iChannel:DMA通道號;

l  參數pulMaxBytes:最大傳輸字節數;

結構體PLW_DMA_FUNCS 詳細描述如程序清單 2‑3:

程序清單 2‑3

typedef struct lw_dma_funcs {

    VOID            (*DMAF_pfuncReset)( UINT     uiChannel,

                                         struct  lw_dma_funcs *pdmafuncs);

    INT              (*DMAF_pfuncTrans)( UINT     uiChannel,

                                         struct  lw_dma_funcs *pdmafuncs,

                                         PLW_DMA_TRANSACTION  pdmatMsg);

    INT              (*DMAF_pfuncStatus)(UINT    uiChannel,

                                         Struct  lw_dma_funcs *pdmafuncs);

} LW_DMA_FUNCS;

typedef  LW_DMA_FUNCS    *PLW_DMA_FUNCS;

結構體中包含三個需要提供給DMA設備庫的操作函數,其功能分別是復位當前DMA操作、啓動一次DMA傳輸、獲得當前DMA工作狀態。這三個函數的第一個傳入參數都是DMA的通道號,第二個參數都是指向DMA驅動結構體的指針。

2.2      DMA回調函數

使用回調函數的目的是將DMA設備庫中的結構體保存到驅動中以供緩衝區數據操作,因此在驅動結構體中需要提供三個變量以保存數據,示例如程序清單 2‑4:

 

程序清單 2‑4

 

typedef struct {

    VOID   (*DMAT_pfuncStart)(UINT     uiChannel,

                              PVOID    pvArg);   /* 啓動本次傳輸之前的回調*/

   

    PVOID  *DMAT_pvArg;                        /* 回調函數參數          */

    VOID   (*DMAT_pfuncCallback)(UINT     uiChannel,

                                  PVOID    pvArg); 

/* 本次傳輸完成後的回調函*/

} LW_DMA_TRANSACTION;

 

2.3      DMA傳輸參數

在LW_DMA_TRANSACTION結構體中除了一些DMA回調函數,還有一些重要的DMA參數,實例如程序清單 2‑5:

程序清單 2‑5

typedef struct {

    UINT8   *DMAT_pucSrcAddress;                   /*  源端緩衝區地址    */

    UINT8   *DMAT_pucDestAddress;                  /*  目的端緩衝區地址  */

    size_t     DMAT_stDataBytes;                     /*  傳輸的字節數       */

    INT      DMAT_iSrcAddrCtl;                      /*  源端地址方向控制  */

    INT      DMAT_iDestAddrCtl;                     /*  目的地址方向控制  */

    INT      DMAT_iHwReqNum;                     /*  外設請求端編號    */

    BOOL    DMAT_bHwReqEn;                      /*  是否爲外設啓動傳輸*/

    BOOL    DMAT_bHwHandshakeEn;                /*  是否使用硬件握手   *

    INT      DMAT_iTransMode;                      /*  傳輸模式, 自定義  */

    PVOID   DMAT_pvTransParam;                    /*  傳輸參數, 自定義   */

    ULONG  DMAT_ulOption;                        /*  體系結構相關參數   */

    PVOID   DMAT_pvArgStart;                      /*  啓動回調參數       */

    …

(回調函數上小節已經單獨說明)

} LW_DMA_TRANSACTION;

typedef LW_DMA_TRANSACTION    *PLW_DMA_TRANSACTION;

DMA 操作的是物理地址, 所以 Src 和 Dest 地址均爲物理地址。有些系統 CPU 體系構架的 CACHE 是使用虛擬地址作爲索引的, 有些是使用物理地址做索引的。所以 DMA 軟件層不處理任何 CACHE 相關的操作, 將這些操作留給驅動程序或應用程序完成。

2.4      DMA API函數簡介

程序清單 2‑6

LW_API  INT     API_DmaDrvInstall(UINT              uiChannel,

                                  PLW_DMA_FUNCS     pdmafuncs,

                                  size_t            stMaxDataBytes);      /*  安裝指定通道的 DMA 驅動程序 */

                                 

LW_API  INT     API_DmaReset(UINT   uiChannel);                       /*  復位指定的 DMA 通道         */

 

LW_API  INT     API_DmaJobNodeNum(UINT   uiChannel,

                                      INT   *piNodeNum);                 /*  獲得當前隊列節點數          */

 

LW_API  INT     API_DmaMaxNodeNumGet(UINT   uiChannel,

                                          INT   *piMaxNodeNum);          /*  獲得最大隊列節點數         */

 

LW_API  INT     API_DmaMaxNodeNumSet(UINT   uiChannel,

                                         INT    iMaxNodeNum);           /*  設置最大隊列節點數          */

 

LW_API  INT     API_DmaJobAdd(UINT                        uiChannel,

                                 PLW_DMA_TRANSACTION    pdmatMsg);  /*  添加一個 DMA 傳輸請求     */

                             

LW_API  INT     API_DmaGetMaxDataBytes(UINT   uiChannel);               /*  獲得一次可以傳輸的最大字節數*/

 

LW_API  INT     API_DmaFlush(UINT   uiChannel);                         /*  刪除所有被延遲處理的傳輸請求*/

 

/*********************************************************************************************************

  API 中斷服務函數

*********************************************************************************************************/

 

LW_API  INT     API_DmaContext(UINT   uiChannel);                     /*  DMA 傳輸完成後的中斷處理函數*/

 

 

#define  dmaDrv                   API_DmaDrvInstall

#define  dmaReset                  API_DmaReset

#define  dmaMaxNodeNumGet        API_DmaMaxNodeNumGet

#define  dmaMaxNodeNumSet        API_DmaMaxNodeNumSet

#define  dmaJobAdd                API_DmaJobAdd

#define  dmaGetMaxDataBytes       API_DmaGetMaxDataBytes

#define  dmaFlush                 API_DmaFlush

 

    如程序清單 2‑6是SylixOS中內核定義的DMA模塊,具體函數使用方法和調用流程在下篇文章中會做詳細介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章