DSP

【DSP】直接存储器访问(DMA)控制器——TMS320VC5509A(下篇)

2019-07-13 12:47发布

之前的上篇和中篇是对直接存储器访问(DMA)的一个大体上的讲解,下篇中主要是对一个DMA具体的实例进行讲解。 实例主要是两个文件:dma.c和vectors.s55。

dma.c文件

/* * Copyright 2002 by Texas Instruments Incorporated. * All rights reserved. Property of Texas Instruments Incorporated. * Restricted rights to use, duplicate or disclose this code are * granted through contract. * */ /* "@(#) DSP/BIOS 4.80.208 12-06-02 (barracuda-l19)" */ /****************************************************************************** * Copyright (C) 2000 Texas Instruments Incorporated. * All Rights Reserved *------------------------------------------------------------------------------ * FILENAME...... dma.c * DATE CREATED.. 08/27/2001 * MODIFIED. 08/28/2001 * MODIFIED. 03/05/2002 Removed reference to PG2.0 DMA regs ******************************************************************************/ #include #include #include #include /* Constant defines transfer length */ //#define N 128 #define N 128 /* Place src and dst of DMA transfer in seperate memory section */ /* to better control placement in user specified memory range */ #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") #pragma CODE_SECTION (main, "saram1Section") #pragma CODE_SECTION (taskFxn, "saram1Section") Uint16 dst2[N]; /* Declare Reference for Start of Interrupt Vector Table */ /* This symbol is defined in the vectors.s55 file */ extern VECSTART(void); /* 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 */ /* The macro invocation reflect the settings required in */ /* DMA control registers to make this happen. */ /* DMACSDP dstben == 0 */ /* dstpack == 0 */ /* dst == 0 */ /* srcben == 0 */ /* srcpack == 0 */ /* src == 0 */ /* datatype == 1 */ /* */ /* DMACCR dstamode == 1 */ /* srcamode == 1 */ /* endprog == 0 */ /* repeat == 0 */ /* autoinit == 0 */ /* en == 0 */ /* prio == 0 */ /* fs == 0 */ /* sync == 0 */ /* */ /* DMACICR blockie == 1 */ /* lastie == 1 */ /* frameie == 1 */ /* firsthalfie == 1 */ /* dropie == 1 */ /* timeoutie == 1 */ 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 */ }; /* Define a DMA_Handle object */ interrupt void dmaIsr(void); void taskFxn(void); DMA_Handle myhDma; int i, j; Uint16 err = 0; Uint16 numTransfers = 0; volatile Uint16 transferComplete = FALSE; 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)(myconfig.dmacssal)) >> 15) & 0xFFFFu; src1AddrLo = (Uint16)(((Uint32)(myconfig.dmacssal)) << 1) & 0xFFFFu; dst1AddrHi = (Uint16)(((Uint32)(myconfig.dmacdsal)) >> 15) & 0xFFFFu; dst1AddrLo = (Uint16)(((Uint32)(myconfig.dmacdsal)) << 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; 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 */ IRQ_setVecs(0x10000); /* Place ISR address in associated vector location */ 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 */ 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 */ 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; } } if (err) { printf(">>> Warning, DMA Example 2 Failed "); } else { printf("...DMA Example 2 Complete "); } /* 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); } } 需要注意的几点:
  1. 这个例子当中使用的DMRAM到DARAM之间的相互之间的DMA数据搬迁。故选择的是DMA_DMACCR_SYNC_NONE,如果是何McBSP联合使用的话,这边需要改成对应的同步事件。
  2. DMA_FSETH(myhDma,DMACSR,FRAME,0),应当在每次中断发生后读DMACSR寄存器,清除即将发生的状态位。这一步不能忘记。

vectors.s55文件

; ; Copyright 2002 by Texas Instruments Incorporated. ; All rights reserved. Property of Texas Instruments Incorporated. ; Restricted rights to use, duplicate or disclose this code are ; granted through contract. ; ; ; "@(#) DSP/BIOS 4.80.208 12-06-02 (barracuda-l19)" .sect ".vectors" .global _VECSTART .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,c54x_stk 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 .text .def no_isr no_isr: b #no_isr vectors.s55文件没有任何的变动,也不需要任何的变动,直接拷贝就行了。