困扰很久的DMA中断问题
采用5509A 和AIC23实现音频采集,I2C通信配置AIC23,然后通过McBSP0接受数据。并通过DMA传输到内存处理。现在的问题是DMA中断有时可以进去,有时进不去。大多时候是进不去。可以确定AIC23和McBSP0在正常工作,因为DRR寄存器的值在不断更新。但是DMA传完一帧后,进不去中断。查看寄存器,IFR相应位已经置1了,怎么就是进不去ISR呢?下面是我的程序,由CSL例程修改而来,ISR里修改DMA配置,实现pingpong切换。
#include <csl.h>
#include <csl_irq.h>
#include <csl_dma.h>
#include <csl_mcbsp.h>
#include \"5509.h\"
//---------Global constants---------
/* Constant defines transfer length */
#define N 128
//---------Global data definition---------
#pragma DATA_SECTION(dst1, \"dmaMem\"
Uint16 dst1[N];
#pragma DATA_SECTION(dst2, \"dmaMem\"
#pragma CODE_SECTION (main, \"saram1Section\"
#pragma CODE_SECTION (taskFxn, \"saram1Section\")
int dst2[N];
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_PERIPH,
DMA_DMACSDP_DATATYPE_16BIT
), /* DMACSDP */
DMA_DMACCR_RMK(
DMA_DMACCR_DSTAMODE_POSTINC,
DMA_DMACCR_SRCAMODE_CONST,
DMA_DMACCR_ENDPROG_ON,
DMA_DMACCR_REPEAT_OFF,
DMA_DMACCR_AUTOINIT_ON,
DMA_DMACCR_EN_STOP,
DMA_DMACCR_PRIO_LOW,
DMA_DMACCR_FS_DISABLE,
//DMA_DMACCR_FS_ENABLE,
DMA_DMACCR_SYNC_REVT0
//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 */
/* DMACSSAL */
(DMA_AdrPtr)(MCBSP_ADDR(DRR10)),
0, /* DMACSSAU */
(DMA_AdrPtr)&dst1, /* DMACDSAL */
0, /* DMACDSAU */
N, /* DMACEN */
1, /* DMACFN */
0, /* DMACFI */
0 /* DMACEI */
};
DMA_Handle myhDma;
int i, j;
volatile Uint16 transferComplete = FALSE;
static int pingpong=0;
Uint16 src1AddrHi, src1AddrLo;
Uint16 src2AddrHi, src2AddrLo;
Uint16 dst1AddrHi, dst1AddrLo;
Uint16 dst2AddrHi, dst2AddrLo;
Uint32 eventId;
Uint16 old_intm;
//---------Function prototypes---------
/* Declare Reference for Start of Interrupt Vector Table */
/* This symbol is defined in the vectors.s55 file */
extern VECSTART(void);
/* Define a DMA_Handle object */
interrupt void dmaIsr(void);
void DMA_init(void);
//---------main routine---------
void main(void)
{
/* Initializa CSL library - This is REQUIRED !!! */
CSL_init();
EMIF_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 = 0;
dst2 = 0;
}
/* Call function to effect transfer */
AIC23_Init();
DMA_init();
while(1);
}
void DMA_init(void)
{
/* 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);
src1AddrHi = (Uint16)(((Uint32)(MCBSP_ADDR(DRR10))) >> 15) & 0xFFFFu;
src1AddrLo = (Uint16)(((Uint32)(MCBSP_ADDR(DRR10))) << 1) & 0xFFFFu;
dst1AddrHi = (Uint16)(((Uint32)(&dst1)) >> 15) & 0xFFFFu;
dst1AddrLo = (Uint16)(((Uint32)(&dst1)) << 1) & 0xFFFFu;
src2AddrHi = (Uint16)(((Uint32)(MCBSP_ADDR(DRR10))) >> 15) & 0xFFFFu;
src2AddrLo = (Uint16)(((Uint32)(MCBSP_ADDR(DRR10))) << 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);
//DMA_getConfig(myhDma,&config1);
/* 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((Uint32)(0x10000));
/* Place ISR address in associated vector location */
IRQ_plug(eventId, &dmaIsr);
/* Enable all maskable interrupts */
IRQ_globalEnable();
IRQ_globalRestore(old_intm);
/* 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);
/* Restore GLobal Interrupt Enable to Previous Setting */
//IRQ_globalRestore(old_intm);
}
/* DMA Interrupt Service Routine */
interrupt void dmaIsr(void) {
IRQ_clear(eventId);
old_intm = IRQ_globalDisable();
DMA_FSETH(myhDma,DMACSR,FRAME,0);
if(pingpong)
{
while (DMA_FGETH(myhDma,DMACCR,ENDPROG));
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);
DMA_FSETH(myhDma,DMACCR,ENDPROG,1);
}
else
{
while (DMA_FGETH(myhDma,DMACCR,ENDPROG));
DMA_RSETH(myhDma,DMACSSAU,src1AddrHi);
DMA_RSETH(myhDma,DMACSSAL,src1AddrLo);
DMA_RSETH(myhDma,DMACDSAU,dst1AddrHi);
DMA_RSETH(myhDma,DMACDSAL,dst1AddrLo);
DMA_RSETH(myhDma,DMACEN, N);
DMA_RSETH(myhDma,DMACFN, 1);
DMA_FSETH(myhDma,DMACCR,ENDPROG,1);
}
pingpong=!pingpong;
IRQ_globalRestore(old_intm);
IRQ_enable(eventId);
}
我的中断向量表文件:vectors_dma2.s55
*
* 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,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
*------------------------------------------------------------------------------
* This is a dummy interrupt service routine used to initialize the IST.
*------------------------------------------------------------------------------
.text
.def no_isr
no_isr:
b #no_isr
*------------------------------------------------------------------------------
没有人遇到类似问题啊?
我将配置里的控制寄存器CCR的repeat值改为1,也就是采用自动重复加载配置的模式,那么数据传输没有任何问题。
现在想在传输一帧后发送DMA中断给CPU,CPU进行处理。同时要在ISR里修改配置的目的地址。就是进不去中断。
哈哈,已经调试通了。
求人不如求己
over