ARM PL330 DMA控制器開發(二)

2021-06-27 07:43:40 字數 4063 閱讀 1876

四、s5pc100 pl330測試例子

下面的**目標要實現記憶體間的資料拷貝。對於s5pc100,有3個dma控制器。要實現記憶體間的dma訪問,需要使用dma_mem。

如下圖所示為dmac控制流程。

圖dmac控制流程

配合上面的流程圖,可以編寫**如下。

(1)相關的巨集定義。

#define max 100

#define inp(addr)            (*(volatileunsigned int *)(addr))

#define outp(addr, data)     (*(volatileunsigned int *)(addr) = (data))

extern void printf(const char *fmt, ...);

void int_dma();

volatile char sour[32] = "012345678901234567890123456789\n";

volatile char dest[32] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"; 

//最終實現將32個位元組從sour的資料傳輸到dest

(2)設定sar、ccr、dar暫存器。

//main函式開始

uart0_init();

volatile char instr_seq[max];

int size = 0, x;

int loopstart, loopnum = 2;  //每個迴圈傳輸16個位元組,傳輸2次

unsigned int source, destination,start, temp;

source = (unsigned int)sour;

destination = (unsigned int)dest;

start = (unsigned int)instr_seq;   //記錄dma指令的首位址

/*dmamov sar0*/

instr_seq[size + 0] =(char)(0xbc);

instr_seq[size + 1] = (char)(0x0);

instr_seq[size + 2] =(char)((source>>0) & 0xff);  //設定資料源位址

instr_seq[size + 3] =(char)((source>>8) & 0xff);

instr_seq[size + 4] =(char)((source>>16) & 0xff);

instr_seq[size + 5] =(char)((source>>24) & 0xff);

size = 6;

/*dmamov dar0*/

instr_seq[size + 0] = (char)(0xbc);

instr_seq[size + 1] = (char)(0x2);

instr_seq[size + 2] =(char)((destination>>0) & 0xff); //設定資料目標位址

instr_seq[size + 3] =(char)((destination>>8) & 0xff);

instr_seq[size + 4] =(char)((destination>>16) & 0xff);

instr_seq[size + 5] = (char)((destination>>24)& 0xff);

size += 6;

/*dmamov cc0. burst_size 8byte,burst_len 2*/ 

instr_seq[size + 0] =(char)(0xbc);

instr_seq[size + 1] = (char)(0x1);

//設定資料傳輸規則,每個迴圈傳輸burst_size* burst_len、原和目標位址變化規則、burst操作等

instr_seq[size + 2] = (char)(0x17);

instr_seq[size + 3] =(char)(0xc0);

instr_seq[size + 4] = (char)(0x5);

instr_seq[size + 5] = (char)(0x0);

size += 6;

(3)設定指令段的起始位址及執行第一次資料裝載並輸出fifo。

/*dmalp lc0*/

instr_seq[size + 0] =(char)(0x20);

instr_seq[size + 1] =(char)(loopnum - 1);// 記錄迴圈的次數

size += 2;

loopstart = size;

/*dmald*/

instr_seq[size + 0] =(char)(0x04);   //從源讀資料

size += 1;

/*dmarmb*/

instr_seq[size + 0] =(char)(0x12);

size += 1;

/*dmast*/

instr_seq[size + 0] =(char)(0x08);  //寫資料到目標位址

size += 1;

/*dmawmb*/

instr_seq[size + 0] =(char)(0x13);

size += 1;

(4)產生中斷,並延時一段時間。

/*可以在dma指令執行過程中做延時。此處可以利用延時保證dma傳輸完成後再停止dma*/

/*dmalp lc0*/

instr_seq[size + 0] = (char)(0x20);

instr_seq[size + 1] = (char)(250);   //迴圈次數

size += 2;

loopstart = size;

/*dmanop*/

instr_seq[size + 0] = (char)(0x18);   //dma的nop空指令,可以實現延時

size += 1;

/*dmalpend 0*/

instr_seq[size + 0] = (char)(0x38);

instr_seq[size + 1] = (char)(size - loopstart);

size += 2;

/*dmasev*/

instr_seq[size + 0] = (char)(0x34);

instr_seq[size + 1] = (char)(1<<3);  //通過dma通道1發出中斷申請,也可以選擇其它的通道

size += 2;

#endif

(5)結束dmac控制。

/*dmaend*/

instr_seq[size + 0] = (char)(0x0);

size += 1;

(6)開始dmac控制,設定相應的中斷處理,並進行測試結果。

vic0vecaddr18 = (unsigned int)int_dma;//dma_mem的處理函式

interrupt.vic0intenable |= 1<<18;        //使能中斷控制器對應的中斷位

outp(0xe8100000+0x20, 0x2); //使能控制器的1中斷通道,此處可以選擇其它的通道,要和dmasev對應

/*dmago*/

do while ((x&0x1)==0x1);

outp(0xe8100d00+0x8,(0<<24)|(0xa0<<16)|(0<<8)|(0<<0));//dbginst0  通道1

outp(0xe8100d00+0xc, start);//dbginst1

outp(0xe8100d00+0x4, 0);//dbgcmd  執行dbginst0、1中的dmago指令,start為開始位址

while(1);

//main函式結束

(7)isr函式的實現如下。

void do_irq()

/*isr*/

void int_dma()

實驗除錯過程與結果:

(2)可以看到下圖所示的測試結果,如圖所示。

五、小節

實驗四 8237DMA控制器實驗

實驗內容 編寫程式,使用dma通道進行ram ram的通道傳送。將6264中0000 8000h 0000 80ff單元的資料傳送至0000 8200h 0000 82ffh單元中。本實驗中8237實驗位址從x20h x2fh 實驗 code segment assume 在 0000 8000h ...

嵌入式實驗 之 DMA控制器實驗

實驗環境 實驗步驟 思考題 附錄 dma 庫函式 dma direct memory access 直接儲存器訪問,是一種可以大大減輕cpu 工作量的資料訪問方式,因而被廣泛地使用。外設工作的時候,除了轉移資料,實質上是不需要核心進行干預的,而如果資料轉移的工作現在也交給了另乙個外設,那麼在該外設進...

STM32使用DMA控制器試驗總結

在使用串列埠dma試驗過程中,遇到了一些問題,通過試驗找到了問題所在,也對dma的應用有了新的認識,僅以此分享給大家,不足之處請多多指教。dma初始化 串列埠對應的dma請求通道 define usart tx dma channel dma1 channel4 define usart tx dm...