为什么我用dma的方式从mcbsp接收和发送数据,接收中断和发送中断只能进去一次,我用的是5509A,音频芯片是AIC23B。并且奇怪的是先进发送中断,再进的接收中断,我采用的是所谓的ping-pong缓存的方式,dma的中断寄存器CICR是设置的半帧中断。关键代码如下:
void AIC23_Init()
{
I2C_INIT();
// Reset the AIC23 and turn on all power
AIC23_Write(AIC23_RESET_REG,0);
AIC23_Write(AIC23_POWER_DOWN_CTL,0);
AIC23_Write(AIC23_ANALOG_AUDIO_CTL,ANAPCTL_DAC | ANAPCTL_INSEL); // 使用麦克风音源
AIC23_Write(AIC23_DIGITAL_AUDIO_CTL,0);
// Turn on volume for line inputs
AIC23_Write(AIC23_LT_LINE_CTL,0x000);
AIC23_Write(AIC23_RT_LINE_CTL,0x000);
// Configure the AIC23 for master mode, 44.1KHz stereo, 16 bit samples
// Use 12MHz USB clock
AIC23_Write(AIC23_DIGITAL_IF_FORMAT,DIGIF_FMT_MS | DIGIF_FMT_IWL_16 | DIGIF_FMT_FOR_DSP);
AIC23_Write(AIC23_SAMPLE_RATE_CTL,SRC_SR_8 | SRC_BOSR | SRC_MO);
// Turn on headphone volume and digital interface
AIC23_Write(AIC23_LT_HP_CTL, 0x07f); // 0x79 for speakers
AIC23_Write(AIC23_RT_HP_CTL, 0x07f);
AIC23_Write(AIC23_DIG_IF_ACTIVATE, DIGIFACT_ACT);//数字界面激活,激活状态
hMcbsp = MCBSP_open(MCBSP_PORT0, MCBSP_OPEN_RESET);
// xmtEventId = MCBSP_getXmtEventId(hMcbsp); //后续的函数中用到了xmtEventId,应该把该条和下一条语句去掉注释?
// rcvEventId = MCBSP_getRcvEventId(hMcbsp);
/* Open DMA channels 4 & 5 and set regs to power on defaults */
hDmaRcv = DMA_open(DMA_CHA4,DMA_OPEN_RESET);
hDmaXmt = DMA_open(DMA_CHA5,DMA_OPEN_RESET);
/* Get interrupt event associated with DMA receive and transmit */
xmtEventId = DMA_getEventId(hDmaXmt);
rcvEventId = DMA_getEventId(hDmaRcv);
/* Temporarily disable interrupts and clear any pending */
/* interrupts for MCBSP transmit */
old_intm = IRQ_globalDisable();
/* Clear any pending interrupts for DMA channels */
IRQ_clear(xmtEventId);
IRQ_clear(rcvEventId);
/* Enable DMA interrupt in IER register */
IRQ_enable(xmtEventId);
IRQ_enable(rcvEventId);
/* Place DMA interrupt service addresses at associate vector */
IRQ_plug(xmtEventId,&dmaXmtIsr);
IRQ_plug(rcvEventId,&dmaRcvIsr);
/* Write values from configuration structure to MCBSP control regs */
MCBSP_config(hMcbsp, &CodeCMcBSP);
/* Write values from configuration structure to DMA control regs */
DMA_config(hDmaRcv,&dmaRcvConfig);
DMA_config(hDmaXmt,&dmaXmtConfig);
/* Enable all maskable interrupts */
IRQ_globalEnable();
/* Start Sample Rate Generator and Enable Frame Sync */
MCBSP_start(hMcbsp,
MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC,
0x300u);//设置的参数需要核实,是否满足要求?
/* Enable DMA */
DMA_start(hDmaRcv);
DMA_start(hDmaXmt);
/* Take MCBSP transmit and receive out of reset */
MCBSP_start(hMcbsp,
MCBSP_XMIT_START | MCBSP_RCV_START,
0u);
// Set McBSP0 to be transmit slave 设置McBSP0为传送从模式
//McBSP0_InitSlave(); // McBSP0传送从模式初始化
}
void AIC23_Mixer()
{
CSL_init();
IRQ_setVecs((Uint32)(&VECSTART));
taskFxn();
}
void taskFxn(void)
{
Uint16 srcAddrHi, srcAddrLo;
Uint16 dstAddrHi, dstAddrLo;
Uint16 DataTempLeft; // 暂存采样数据
Uint16 DataTempRight;
/* 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. */
srcAddrHi = (Uint16)(((Uint32)(MCBSP_ADDR(DRR10))) >> 15) & 0xFFFFu;
srcAddrLo = (Uint16)(((Uint32)(MCBSP_ADDR(DRR10))) << 1) & 0xFFFFu;
dstAddrHi = (Uint16)(((Uint32)(&rcv)) >> 15) & 0xFFFFu;
dstAddrLo = (Uint16)(((Uint32)(&rcv)) << 1) & 0xFFFFu;
dmaRcvConfig.dmacssal = (DMA_AdrPtr)srcAddrLo;
dmaRcvConfig.dmacssau = srcAddrHi;
dmaRcvConfig.dmacdsal = (DMA_AdrPtr)dstAddrLo;
dmaRcvConfig.dmacdsau = dstAddrHi;
srcAddrHi = (Uint16)(((Uint32)(&xmt[0])) >> 15) & 0xFFFFu;
srcAddrLo = (Uint16)(((Uint32)(&xmt[0])) << 1) & 0xFFFFu;
dstAddrHi = (Uint16)(((Uint32)(MCBSP_ADDR(DXR10))) >> 15) & 0xFFFFu;
dstAddrLo = (Uint16)(((Uint32)(MCBSP_ADDR(DXR10))) << 1) & 0xFFFFu;
dmaXmtConfig.dmacssal = (DMA_AdrPtr)srcAddrLo;
dmaXmtConfig.dmacssau = srcAddrHi;
dmaXmtConfig.dmacdsal = (DMA_AdrPtr)dstAddrLo;
dmaXmtConfig.dmacdsau = dstAddrHi;
AIC23_Init();
while(1)
{
if(RecvComplete==TRUE) //满足该条件表示dsp接收到dma给dsp的接收终端。
{
if(dmaRcvIsr_count==1) //如果满足该条件则处理前半帧的数据
front_rcv_process();
if(dmaRcvIsr_count==0) //如果满足该条件则处理后半帧的数据
rear_rcv_process();
for(i=0,pxmt=xmt;i<N/4;i++) //对左右声道的数据进行合并,以便DMA输出
{
*pxmt++=*pL++;
*pxmt++=*pR++;
}
printf("%d,",k);
}
}
}
void front_rcv_process() //前半帧处理函数
{
prcv=rcv;
for(i = 0;i<N/4;i++)
{
*pL++ = *prcv++;
*pR++ = *prcv++;
}
pL = Left;
pR = Right;
}
void rear_rcv_process() //后半帧处理函数
{
prcv=&rcv[N/2];
for(i = 0;i<N/4;i++)
{
*pL++ = *prcv++;
*pR++ = *prcv++;
}
pL = Left;
pR = Right;
}
//接收中断函数
interrupt void dmaRcvIsr(void) {
RecvComplete = TRUE;
if(++dmaRcvIsr_count>1)
dmaRcvIsr_count=0;
}
//发送中断函数
interrupt void dmaXmtIsr(void) {
RecvComplete = FALSE;
}