1、menDMA实验基于描述符的存储器DMA实验 本实验利用ADSPBF533-EZ-KIT板的硬件资源,完成Blackfin存储空间中的存储器对存储器的DMA传送。本实验中三种不同的描述符(DMA传送方法)得到的结果不一样,可以通过观察各个输出存储器的窗口看到现象。通过这个实验可以加深对menDMA数据传送方式的理解。1本实验程序简介1) 程序结构:程序包括主函数main.asm、memDMAfunc.asm、memdmainit.asm等3个模块,以及常数和宏定义、全局变量定义部分。其中main.asm 函数完成整个功能程序的控制,memDMAfunc.asm完成各种描述符(DMA数据传送方法
2、)的设定和dma_engine的启动,memdmainit.asm完成基于描述的DMA初始化。2) 程序工作流程:_main先调用memdma_init完成对基于描述的DMA初始化,再调用memdma_move1D、call memdma_move1Dto2D、memdma_move2Dto2D三种不同的描述符(传送方法)进行存储器到存储器的数据传送,最后调用ctivate_dma_engine启动DMA传送数据。 本实验的程序位于 Descriptor Base子目录,打开工程文件memdma_example.dpj,可以看到演示软件包括以下几个程序模块:(1) main.asm#inclu
3、de defBF533.h#define N 0x100 / number of elements to transfer in each DMA example/ Define extern functions.extern memdma_init;.extern activate_dma_engine;.extern memdma_move1D;.extern memdma_move1Dto2D;.extern memdma_move2Dto2D;/ Set up input and output buffers in L1 data bank A.section L1_data_a;.a
4、lign 4;.global input_frame;input_frame:.byte _input_frameN = input_data.dat; / load in 256 values from a test fileinput_frame.end:.global output_frame_1Dto1D; / output buffer after 1D to 1D DMAoutput_frame_1Dto1D:.byte _output_frame_1Dto1DN;output_frame_1Dto1D.end:.global output_frame_1Dto2D; / outp
5、ut buffer after 1D to 2D DMAoutput_frame_1Dto2D:.byte _output_frame_1Dto2DN;output_frame_1Dto2D.end:.global output_frame_2Dto2D; / output buffer after 2D to 2D DMAoutput_frame_2Dto2D:.byte _output_frame_2Dto2DN;output_frame_2Dto2D.end:.section L1_code;.align 4;.global _main;_main: call memdma_init;
6、/ setup descriptor framework / In the this example, 3 descriptor sets are built./ In each case, the data registers are used to store the following DMA info/ prior to making the setup call /r0 - src address/r1 - XCNT/XMOD/r2 - YCNT/YMOD/r3 - Dst Addr r0.h = input_frame; /source address r0.l = input_f
7、rame; r1.l = N 2; /XCNT - 100 bytes r1.h = 4; /XMOD = 4bytes - 32bit xfers / XMOD has to be at least 4 since 32-bit transfers are used r3.h = output_frame_1Dto1D; /Destination Address for first descriptor r3.l = output_frame_1Dto1D; call memdma_move1D; /setup 1D to 1D L1-L1 descriptor r0.h = input_f
8、rame; /source address r0.l = input_frame; r1.l = 0x0002; /D_XCNT -2 columns r1.h = 0x0004; /D_XMOD = 4 bytes ( 32bit transfers) r2.l = 0x0003; /YCNT - 3 rows r2.h = 0x0010; /YMOD - 16 bytes (produces a separation of 12 bytes (16-4) between each block) r3.h = output_frame_1Dto2D; /Destination Address
9、 r3.l = output_frame_1Dto2D; call memdma_move1Dto2D; /setup 1D to 2D L1-L1 descriptor r0.h = input_frame; /source address r0.l = input_frame; r1.l = 0x0002; /S and D_XCNT -2 columns; r1.h = 0x0004; /S and D_XMOD = 4 bytes - 1 32bit element r2.l = 0x0003; /S and D YCNT - 2 rows; r2.h = 0x0010; /S and
10、 D YMOD - 16 bytes r3.h = output_frame_2Dto2D; /Destination Address r3.l = output_frame_2Dto2D; call memdma_move2Dto2D; /setup 2D to 2D L1-L1 descriptor call activate_dma_engine; / start descriptor based DMA / Open a memory window and look at the following labels to see the results of each DMA / out
11、put_frame_1Dto1D / output_frame_1Dto2D / output_frame_2Dto2D: here:jump here; / Example done_main.end:(2)memdmainit.asm#include defBF533.h/*MemDma initialization routine This routine sets up the descriptor list framework for a memDMA transfer up to NUM_DESCR_BLOCKS_IN_QUEUE descriptors A source and
12、destination buffer is set up because memDMA is being used */#include memdma.h.section L1_data_a;.align 4;/DMA Descriptor - Small Model/1 32B Word: LS16BW: Next Descr Pointer, MS16BW: Start Addr Low/2 32B Word: LS16BW:Start Addr High , MS16BW:DMA config/3 32B Word: LS16BW:XCNT, MS16BW:XMOD/4 32B Word
13、: LS16BW:YCNT, MS16BW:YMOD.global MemDMAQueue;MemDMAQueue:.byte4 _MemDMAQueue4 * 2 * NUM_DESCR_BLOCKS_IN_QUEUE; / 8 32 bit words * NUM_DESCR_IN_QUEUEMemDMAQueue.end:.section L1_code;.align 4;/dummy_start:.global memdma_init;memdma_init:/ This routine sets up a descriptor framework/ Each descriptor i
14、s filled in from calls within main.asm p1.h = MemDMAQueue; p1.l = MemDMAQueue; p2 = 16(z); r0 = p1; r1 = p1; r0 += 16; p0 = (NUM_DESCR_BLOCKS_IN_QUEUE - 1) * 2); lsetup (start_memdmaqueueinit, end_memdmaqueueinit) lc0 = p0;start_memdmaqueueinit: r0 += 16;end_memdmaqueueinit: wp1 + p2 = r0.l;/Last De
15、scriptor in the Queue points to the first one wp1 + p2 = r1.l; r1 += 16; p1 = r1; rts;memdma_init.end: (3) memDMAfunc.asm*/#include defBF533.h/* MemDma routines dmaDescrPtr = memdma_move1Dto2D (srcaddr, xcount, ycount, dstaddr, priority) dmaDescrPtr = memdma_move2Dto1D (srcaddr, xcount, ycount, dsta
16、ddr, priority) dmaDescrPtr = memdma_move1D (srcaddr (32b), count (32b), destaddr (32b), priority) memdma_wait (dmaDescrPtr)*/#include memdma.h#define NUM_QUEUE_STRUCT_ELEM 2/ All of these are configured as descriptor list (small model) 0x6 in upper byte/ Descriptor size = 8/ all are set to 32-bit tr
17、ansfers/ all are set to DMA enable#define SRCMEM1DCFG 0x6809 / DMA read#define SRCMEM2DCFG 0x6819 / 2D bit set, DMA read#define DSTMEM1DCFG 0x680B / DMA write#define DSTMEM2DCFG 0x681B / 2D bit set, DMA write/DMA Descriptor (S&D) - Small Model/1 32B Word: LS16BW:Src NDPL, MS16BW:Src SAL +0/2 32B Wor
18、d: LS16BW:Src SAH, MS16BW:Src DMACFG +4/3 32B Word: LS16BW:Src XCNT, MS16BW:Src XMOD +8/4 32B Word: LS16BW:Src YCNT, MS16BW:Src YMOD +12/6 32B Word: LS16BW:Dst NDPL, MS16BW:Dst SAL +16/7 32B Word: LS16BW:Dst SAH, MS16BW:Dst DMACFG +20/8 32B Word: LS16BW:Dst XCNT, MS16BW:Dst XMOD +24/9 32B Word: LS16
19、BW:Dst YCNT, MS16BW:Dst YMOD +28.extern MemDMAQueue;.extern memdma_move1D_buffer; / sets up descriptors for 1D transfer/.section shell_L1_data;.section L1_data_a;.align 4;/.section shell_L1_data;.section L1_data_a;.align 4;MemDMAQueueStruct:.byte4 _MemDMAQueueStructNUM_QUEUE_STRUCT_ELEM = MemDMAQueu
20、e, MemDMAQueue;.section L1_code;.align 4;/dummy_start:.global memdma_move1Dto2D; / sets up 1D to 2D descriptormemdma_move1Dto2D: p1.h = MemDMAQueueStruct; p1.l = MemDMAQueueStruct; r5 = p1+; /tail address i0 = r5; r4 = p1-; /MemDMAQueue start address b0 = r4; l0 = NUM_DESCR_BLOCKS_IN_QUEUE*32 (z); m
21、0 = 8; nop; r4.l = wi0+; /S_NDPL - dummy read wi0+ = r0.l; /S_SAL wi0+ = r0.h; /S_SAH r0.l = SRCMEM1DCFG; wi0+ = r0.l; /S_CFG r0 = r1; /S_XMOD = D_XMOD r0.l = r1.l * r2.l (IU); /S_XCNT = D_XCNT * D_YCNT i0+m0 = r0; /S_XCNT/S_XMOD r4.l = wi0+; /D_NDPL - dummy read wi0+ = r3.l; /D_SAL wi0+ = r3.h; /D_
22、SAH r0.l = DSTMEM2DCFG; wi0+ = r0.l; /D_CFG i0+ = r1; /D_XCNT/D_XMOD i0+ = r2; /D_YCNT/D_YMOD l0 = 0; r0 = i0; p1 = r0; /update tail with NDP value r0 = r5; / r0 - return parameter rts;memdma_move1Dto2D.end: .global memdma_move2Dto2D; / sets up 2D to 2D descriptormemdma_move2Dto2D: p1.h = MemDMAQueu
23、eStruct; p1.l = MemDMAQueueStruct; r5 = p1+; /tail address i0 = r5; r4 = p1-; /MemDMAQueue start address b0 = r4; l0 = NUM_DESCR_BLOCKS_IN_QUEUE*32 (z); m0 = 8; nop; r4.l = wi0+; /S_NDPL - dummy read wi0+ = r0.l; /S_SAL wi0+ = r0.h; /S_SAH r0.l = SRCMEM2DCFG; wi0+ = r0.l; /D_CFG i0+ = r1; /D_XCNT/D_
24、XMOD i0+ = r2; /D_YCNT/D_YMOD #if 0 wi0+ = r0.l; /S_CFG r0 = r1; /S_XMOD = D_XMOD r0.l = r1.l * r2.l (IU); /S_XCNT = D_XCNT * D_YCNT i0+m0 = r0; /S_XCNT/S_XMOD #endif r4.l = wi0+; /D_NDPL - dummy read wi0+ = r3.l; /D_SAL wi0+ = r3.h; /D_SAH r0.l = DSTMEM2DCFG; wi0+ = r0.l; /D_CFG i0+ = r1; /D_XCNT/D
25、_XMOD i0+ = r2; /D_YCNT/D_YMOD l0 = 0; r0 = i0; p1 = r0; /update tail with NDP value r0 = r5; / r0 - return parameter rts; memdma_move2Dto2D.end: /r0 - src address/r1 - XCNT/XMOD/r2 - YCNT/YMOD/r3 - Dst Addr.global memdma_move1D; / sets up 1D to 1D descriptormemdma_move1D: p1.h = MemDMAQueueStruct;
26、p1.l = MemDMAQueueStruct; r5 = p1+; /tail address i0 = r5; r4 = p1-; /MemDMAQueue start address b0 = r4; l0 = NUM_DESCR_BLOCKS_IN_QUEUE*32 (z); m0 = 8; nop; r4.l = wi0+; /dummy read to offset NDPL wi0+ = r0.l; /S_SAL wi0+ = r0.h; /S_SAH r0.l = SRCMEM1DCFG; wi0+ = r0.l; /S_CFG i0+m0 = r1; /S_XCNT/S_X
27、MOD r4.l = wi0+; /dummy read to get over DST NDPL wi0+ = r3.l; /D_SAL wi0+ = r3.h; /D_SAH r3.l = DSTMEM1DCFG; wi0+ = r3.l; /D_CFG i0+m0 = r1; /D_XCNT/D_XMOD l0 = 0; r0 = i0; p1 = r0; /update tail with NDP value r0 = r5; / r0 - return parameter rts;memdma_move1D.end: .global activate_dma_engine;activate_dma_engine: / once descriptor list is set, call this to start DMA p0.h = HI(MDMA_S0_NEXT_DESC_PTR); p0.l = LO(MDMA_S0_NEXT_DESC_PTR); r0.l = MemDMAQueue; /Address of the Source Descriptor r0.h = MemDMAQueue; p0 = r0; ssync; p0.l = LO(MDMA_D0_NEXT_DESC_PTR); r0 +=16;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1