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
*------------------------------------------------------------------------------