四、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...