DSP

DSP 之直接内存访问(DMA)介绍

2019-07-13 09:37发布

DSP之直接内存访问(DMA)介绍:
C5509A提供的支持: 1.四个标准端口,每个都能够访问外部或者内部数据元。 2.六个通道,能够独立控制DMA通道的有四个。 3.每个通道都是可编程,高优先级的。 4.每个DMA都可以使用中断。 5.支持时间同步,DMA转让能够依赖发生选择事件。 6.可编程地址源,可用于源/目标地址。 7.DMA使用通道可以使用HPI去访问内部存储器(DARAM) 5509ADMA能够同步选择事件,最多支持21个同步事件。。
DMA寄存器: DMA_CCR:   /* * Copyright (C) 2003 Texas Instruments Incorporated * All Rights Reserved */ /* *---------main_dma2.c--------- * This example effects a two single-frame transfers of 128 * elements from DARAM to DARAM, via DMA, using DMA auto-initialization * mode to effect the second transfer */ #include #include #include #include //---------Global constants--------- /* Constant defines transfer length */ #define N 128 //---------Global data definition--------- /* Place src and dst of DMA transfer in seperate memory section */ /* to better control placement in user specified memory range */ /* 将变量放入“dmaMem”数据段中 */ #pragma DATA_SECTION(src1,"dmaMem") Uint16 src1[N]; #pragma DATA_SECTION(src2,"dmaMem") Uint16 src2[N]; #pragma DATA_SECTION(dst1, "dmaMem") Uint16 dst1[N]; #pragma DATA_SECTION(dst2, "dmaMem") /* 将函数地址放入saram1Section代码段 */ #pragma CODE_SECTION (main, "saram1Section") #pragma CODE_SECTION (taskFxn, "saram1Section") Uint16 dst2[N]; /* DMA 配置 */ DMA_Config myconfig = { DMA_DMACSDP_RMK( DMA_DMACSDP_DSTBEN_NOBURST, DMA_DMACSDP_DSTPACK_OFF, DMA_DMACSDP_DST_DARAM, DMA_DMACSDP_SRCBEN_NOBURST, DMA_DMACSDP_SRCPACK_OFF, DMA_DMACSDP_SRC_DARAM, DMA_DMACSDP_DATATYPE_16BIT ), /* DMACSDP */ DMA_DMACCR_RMK( DMA_DMACCR_DSTAMODE_POSTINC, DMA_DMACCR_SRCAMODE_POSTINC, DMA_DMACCR_ENDPROG_ON, DMA_DMACCR_REPEAT_OFF, DMA_DMACCR_AUTOINIT_ON, DMA_DMACCR_EN_STOP, DMA_DMACCR_PRIO_HI, DMA_DMACCR_FS_DISABLE, DMA_DMACCR_SYNC_NONE ), /* DMACCR */ DMA_DMACICR_RMK( DMA_DMACICR_BLOCKIE_OFF, DMA_DMACICR_LASTIE_OFF, DMA_DMACICR_FRAMEIE_ON, DMA_DMACICR_FIRSTHALFIE_OFF, DMA_DMACICR_DROPIE_OFF, DMA_DMACICR_TIMEOUTIE_OFF ), /* DMACICR */ (DMA_AdrPtr)&src1, /* DMACSSAL */ 0, /* DMACSSAU */ (DMA_AdrPtr)&dst1, /* DMACDSAL */ 0, /* DMACDSAU */ N, /* DMACEN */ 1, /* DMACFN */ 0, /* DMACFI */ 0 /* DMACEI */ }; DMA_Handle myhDma; int i, j; Uint16 err = 0; Uint16 numTransfers = 0; volatile Uint16 transferComplete = FALSE; /* Declare Reference for Start of Interrupt Vector Table */ /* This symbol is defined in the vectors.s55 file */ extern VECSTART(void); /* Define DMA interrupt handle function */ interrupt void dmaIsr(void); /* User's function */ void taskFxn(void); void main(void) { /* Initializa CSL library - This is REQUIRED !!! */ CSL_init(); /* Set IVPD/IPVH to start of interrupt vector table */ /* 设置中断向量表的位置 */ IRQ_setVecs((Uint32)(&VECSTART)); /* Initialize source and destination buffers */ for (i = 0; i <= (N - 1); i++) { dst1[i] = 0; dst2[i] = 0; src1[i] = i + 1; src2[i] = (i + 1) * 2; } /* Call function to effect transfer */ taskFxn(); } void taskFxn(void) { Uint16 src1AddrHi, src1AddrLo; Uint16 src2AddrHi, src2AddrLo; Uint16 dst1AddrHi, dst1AddrLo; Uint16 dst2AddrHi, dst2AddrLo; Uint32 eventId; Uint16 old_intm; /* Open DMA Channel 1 setting registers to their power on defualts */ myhDma = DMA_open(DMA_CHA1, DMA_OPEN_RESET); /* Get Interrupt Event Id associated with this DMA */ eventId = DMA_getEventId(myhDma); /* By default, the TMS320C55xx compiler assigns all data symbols word */ /* addresses. The DMA however, expects all addresses to be byte */ /* addresses. Therefore, we must shift the address by 2 in order to */ /* change the word address to a byte address for the DMA transfer. */ src1AddrHi = (Uint16)(((Uint32)(&src1)) >> 15) & 0xFFFFu; src1AddrLo = (Uint16)(((Uint32)(&src1)) << 1) & 0xFFFFu; dst1AddrHi = (Uint16)(((Uint32)(&dst1)) >> 15) & 0xFFFFu; dst1AddrLo = (Uint16)(((Uint32)(&dst1)) << 1) & 0xFFFFu; src2AddrHi = (Uint16)(((Uint32)(&src2)) >> 15) & 0xFFFFu; src2AddrLo = (Uint16)(((Uint32)(&src2)) << 1) & 0xFFFFu; dst2AddrHi = (Uint16)(((Uint32)(&dst2)) >> 15) & 0xFFFFu; dst2AddrLo = (Uint16)(((Uint32)(&dst2)) << 1) & 0xFFFFu; /* 配置DMA源/目标地址 */ myconfig.dmacssal = (DMA_AdrPtr)src1AddrLo; myconfig.dmacssau = src1AddrHi; myconfig.dmacdsal = (DMA_AdrPtr)dst1AddrLo; myconfig.dmacdsau = dst1AddrHi; /* Write configuration structure values to DMA control registers */ DMA_config(myhDma, &myconfig); /* Temporarily Disable All Interrupts */ old_intm = IRQ_globalDisable(); /* Clear any pending interrupts for DMA in IFR */ IRQ_clear(eventId); /* Enable the DMA interrupt in IER register */ IRQ_enable(eventId); /* Set Interrupt Vector Start Location in 0x10000 */ IRQ_setVecs(0x10000); /* Place ISR address in associated vector location * Write the necessary code in the interrupt vector location to * branch to the interrupt service routine for the speified event * */ IRQ_plug(eventId, &dmaIsr); /* Enable all maskable interrupts */ IRQ_globalEnable(); /* Enable DMA channel to begin transfer */ DMA_start(myhDma); /* Wait for programmation bit, ENDPROG == 0, to make sure that device's */ /* configuration register set has already been copied to working set */ while (DMA_FGETH(myhDma,DMACCR,ENDPROG)) { ; } /* Write next set of configuration values to the DMA control regs */ /* for next transfer */ /* Set value of DMA register */ DMA_RSETH(myhDma,DMACSSAU,src2AddrHi); DMA_RSETH(myhDma,DMACSSAL,src2AddrLo); DMA_RSETH(myhDma,DMACDSAU,dst2AddrHi); DMA_RSETH(myhDma,DMACDSAL,dst2AddrLo); DMA_RSETH(myhDma,DMACEN, N); DMA_RSETH(myhDma,DMACFN, 1); /* Set programmation bit to 1, ENDPROG = 1) */ DMA_FSETH(myhDma,DMACCR,ENDPROG,1); /* Wait for transfers to complete * twice the “transferComplete” will be true * */ while (!transferComplete) { ; } /* Check data values to make sure transfer happened correctly */ for (i = 0; i <= (N - 1); i++) { if ((dst1[i] != src1[i]) && (dst2[i] != src2[i])) { ++err; } } printf ("%s ",err?"TEST FAILED" : "TEST PASSED"); /* Restore GLobal Interrupt Enable to Previous Setting */ IRQ_globalRestore(old_intm); /* We are through with DMA, so close it */ DMA_close(myhDma); } /* DMA Interrupt Service Routine */ interrupt void dmaIsr(void) { ++numTransfers; DMA_FSETH(myhDma,DMACSR,FRAME,0); if (numTransfers == 2) { transferComplete = TRUE; DMA_stop(myhDma); } }
/* * Copyright (C) 2003 Texas Instruments Incorporated * All Rights Reserved */ /* *---------dma2.cmd--------- * */ MEMORY { PAGE 0: MMR : origin = 0000000h, length = 00000c0h SPRAM : origin = 00000c0h, length = 0000040 VECS : origin = 0000100h, length = 0000100h DARAM0 : origin = 0000200h, length = 0003E00h DARAM1 : origin = 0004000h, length = 0004000h DARAM2 : origin = 0008000h, length = 0004000h DARAM3 : origin = 000c000h, length = 0004000h SARAM0 : origin = 0010000h, length = 0004000h SARAM1 : origin = 0014000h, length = 0005000h SARAM2 : origin = 0019000h, length = 0003000h SARAM3 : origin = 001c000h, length = 0004000h SARAM4 : origin = 0020000h, length = 0004000h SARAM5 : origin = 0024000h, length = 0004000h SARAM6 : origin = 0028000h, length = 0004000h SARAM7 : origin = 002c000h, length = 0004000h SARAM8 : origin = 0030000h, length = 0004000h SARAM9 : origin = 0034000h, length = 0004000h SARAM10 : origin = 0038000h, length = 0004000h SARAM11 : origin = 003c000h, length = 0004000h SARAM12 : origin = 0040000h, length = 0004000h SARAM13 : origin = 0044000h, length = 0004000h SARAM14 : origin = 0048000h, length = 0004000h SARAM15 : origin = 004c000h, length = 0004000h CE0 : origin = 0050000h, length = 03b0000h CE1 : origin = 0400000h, length = 0400000h CE2 : origin = 0800000h, length = 0400000h CE3 : origin = 0c00000h, length = 03f8000h PDROM : origin = 0ff8000h, length = 07f00h /* VECS : origin = 0ffff00h, length = 00100h */ /* reset vector */ } SECTIONS { .vectors : {} > VECS PAGE 0 /* interrupt vector table */ .cinit : {} > SARAM0 PAGE 0 .text : {} > SARAM1 PAGE 0 .stack : {} > DARAM0 PAGE 0 .sysstack: {} > DARAM0 PAGE 0 .sysmem : {} > DARAM1 PAGE 0 .cio : {} > DARAM1 PAGE 0 .data : {} > DARAM1 PAGE 0 .bss : {} > DARAM1 PAGE 0 .const : {} > DARAM1 PAGE 0 saram1Section : {} > SARAM2 PAGE 0 .csldata: {} > DARAM0 PAGE 0 dmaMem: {} > DARAM0 PAGE 0 }
* * Copyright (C) 2003 Texas Instruments Incorporated * All Rights Reserved * * *---------vectors_dma2.s55--------- * * Assembly file to set up interrupt vector table * .sect ".vectors" *------------------------------------------------------------------------------ * Global symbols defined here and exported out of this file *------------------------------------------------------------------------------ .global _VECSTART *------------------------------------------------------------------------------ * Global symbols referenced in this file but defined somewhere else. * Remember that your interrupt service routines need to be referenced here. *------------------------------------------------------------------------------ .ref _c_int00 .def nmi, int0, int1, int2, int3, int4, int5, int6 .def int7, int8, int9, int10, int11, int12, int13 .def int14, int15, int16, int17, int18, int19, int20 .def int21, int22, int23, int24, int25, int26, int27 .def int28, int29 _VECSTART: .ivec _c_int00,use_reta nmi .ivec no_isr nop_16 int0 .ivec no_isr nop_16 int1 .ivec no_isr nop_16 int2 .ivec no_isr nop_16 int3 .ivec no_isr nop_16 int4 .ivec no_isr nop_16 int5 .ivec no_isr nop_16 int6 .ivec no_isr nop_16 int7 .ivec no_isr nop_16 int8 .ivec no_isr nop_16 int9 .ivec no_isr nop_16 int10 .ivec no_isr nop_16 int11 .ivec no_isr nop_16 int12 .ivec no_isr nop_16 int13 .ivec no_isr nop_16 int14 .ivec no_isr nop_16 int15 .ivec no_isr nop_16 int16 .ivec no_isr nop_16 int17 .ivec no_isr nop_16 int18 .ivec no_isr nop_16 int19 .ivec no_isr nop_16 int20 .ivec no_isr nop_16 int21 .ivec no_isr nop_16 int22 .ivec no_isr nop_16 int23 .ivec no_isr nop_16 int24 .ivec no_isr nop_16 int25 .ivec no_isr nop_16 int26 .ivec no_isr nop_16 int27 .ivec no_isr nop_16 int28 .ivec no_isr nop_16 int29 .ivec no_isr nop_16 *------------------------------------------------------------------------------ * This is a dummy interrupt service routine used to initialize the IST. *------------------------------------------------------------------------------ .text .def no_isr no_isr: b #no_isr *------------------------------------------------------------------------------