linux2.4下DMA的使用

這兩天看了如下linux下DMA的使用方法,這裏與你們分享。

      本文以linux2.4,硬件s2410爲平臺。關於DMA具體操做編程在內核源碼目錄下 /kernel/arch/arm/mach-s2410/dma.c.linux

這裏並不打算講解dma具體的實現方法,主要想告訴你們如何學會在本身的程序中使用DMA這個功能。編程

     使用DMA功能主要涉及如下幾個步驟:數組

     1,申請DMA資源數據結構

        int s2410_request_dma(const char *device_id, dmach_t channel,dma_callback_t write_cb, dma_callback_t read_cb)函數

       功能:這個函數的主要就是申請一個空閒的DMA通道,指針

參數:device_id 哪一個硬件須要使用DMA功能,這是一個字符串,具體定義在/kernel/arch/arm/mach-s3c2410/dma.h中,裏面有個數組包含了全部的可使用DMA的硬件模塊,此處參數,只須要填充下面數組的紅色字符串便可,這麼沒有所有列出,若是用到本身去查。隊列

static dma_type_t dma_types[4][5] = {內存

{資源

       { "XDREQ0", XDREQ0_WR_SRC, XDREQ0_WR_DST, XDREQ0_WR_CTL, \字符串

                  XDREQ0_WR_SRC_CTL, XDREQ0_WR_DST_CTL, \

                  XDREQ0_RD_SRC, XDREQ0_RD_DST, XDREQ0_RD_CTL, \

                  XDREQ0_RD_SRC_CTL, XDREQ0_RD_DST_CTL },

       { "UART0", UART0_WR_SRC, UART0_WR_DST, UART0_WR_CTL, \

                  UART0_WR_SRC_CTL, UART0_WR_DST_CTL, \

                  UART0_RD_SRC, UART0_RD_DST, UART0_RD_CTL, \

                  UART0_RD_SRC_CTL, UART0_RD_DST_CTL },

     。。。。。。。。。。。

}

channel:要申請的DMA的通道

write_cb:通常在DMA一次操做完成後須要調用一個函數完成一些善後工做,這個參數是個回調參數指針,當DMA完成一次寫操做後後調用這個函數。這個函數的定義形式爲

static void dmaout_done_callback(void *buf_id, int size)   

read_cb:與上一個參數相似,只是這個函數在DMA完成一次讀操做後調用。函數定義形式爲static void dmain_done_callback(void *buf_id, int size)

2,DMA隊列填充,linux對DMA使用一個隊列進行管理,咱們在申請了DMA通道之後接下來的工做就是向DMA緩衝區中填充數據,DMA傳輸數據問題交由linux來處理,使用函數:

int s2410_dma_queue_buffer(dmach_t channel, void *buf_id, dma_addr_t data, int size, int write)

功能:將須要由DMA傳輸的緩衝區添加到DMA隊列中

參數:channel : 剛剛申請到的DMA通道

      buf_id: 私有數據結構,能夠存聽任何數據,dmain_done_callback(void *buf_id, int size)中的參數buf_id,二者是同一個東西。(這是真滴J)

     data:緩衝區首地址

       size:   緩衝區的大小

write:0 控制DMA是讀取操做

      1 控制DMA是寫入操做

3, DMA緩衝區的申請。若是你們使用上面的函數必定不會操做成功的o(∩_∩)o。那是由於最重要的俺還沒告訴你呢! 原來DMA的傳輸須要物理地址才行,而咱們用一般方法獲得的緩衝區都是虛擬地址,爲了獲得物理地址的緩衝區,咱們須要使用下面這個函數;

void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)

功能:申請一塊內存空間

參數:gpf:內存分配參數,

      size:須要分配的大小

      dma_handle:若是分配成功存放,分配空間的物理地址的首地址,沒錯這個地址才能放到DMA隊列中

返回值:返回申請到空間的邏輯地址的首地址

4,使用上面的幾個函數就能夠完成DMA的傳輸了(*^__^*) 。天下沒有不散的宴席,有合必有分,因此老是要有離別的時候的,當你使用完了DMA簡單的說聲byebye就能夠了,比起什麼什麼來夠簡單吧

void s2410_free_dma(dmach_t channel)

功能:釋放DMA通道

參數:要釋放的DMA通道

void consistent_free(void *vaddr, size_t size, dma_addr_t handle)

功能:釋放申請的DMA緩衝區

參數:vaddr 虛擬地址

      size 緩衝區大小

      handle 物理地址

這樣就就能夠完美操做DMA了,下面使用一個從IIS驅動中拿出來的例子,實際演示一下

1, s2410_request_dma("I2SSDO", 2, audio_dmaout_done_callback, NULL);

2, dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA, dmasize, &dmaphys);                                                                                       // 申請DMA緩衝區

3, s2410_dma_queue_buffer(s->dma_ch, (void *) b, dmaphys , b->size, DMA_BUF_WR);

4, s2410_free_dma(2);

5, consistent_free(dmabuf, dmasize, dmaphys);}

基本上使用DMA就是這個過程了,byebye嘍

相關文章
相關標籤/搜索