程序中对DMA配置如下:
dmaConfig.pingPongMode = CSL_DMA_PING_PONG_DISABLE; dmaConfig.autoMode = CSL_DMA_AUTORELOAD_ENABLE; //自动加载 dmaConfig.burstLen = CSL_DMA_TXBURST_1WORD; dmaConfig.trigger = CSL_DMA_SOFTWARE_TRIGGER;//软件触发DMA传输 dmaConfig.dmaEvt = CSL_DMA_EVT_NONE; dmaConfig.dmaInt = CSL_DMA_INTERRUPT_ENABLE; // 使能DMA中断 dmaConfig.chanDir = CSL_DMA_WRITE; // 方向为写,即发送 dmaConfig.trfType = CSL_DMA_TRANSFER_MEMORY; // 在内存之间传输 dmaConfig.dataLen = I2S_DMA_BUF_LEN*2; // 传输长度 dmaConfig.destAddr = (Uint32)dmaDstBuf; dmaConfig.srcAddr = (Uint32)dmaSrcBuf;
在调用一次DMA_start(dmaHandle)之后,产生了一次中断,完成I2S_DMA_BUF_LEN*2字节的数据dmaSrcBuf到dmaDstBuf的传输。
由于设置了dmaConfig.autoMode = CSL_DMA_AUTORELOAD_ENABLE,DMA会继续自动完成传输。
所以,当更新dmaSrcBuf中的数据时,dmaDstBuf也会被更新。
但是,传输完成后,并没有再次产生中断,为什么?
中断函数中,已经对DMAIFR寄存器的标志位进行了清零:
ifrValue = CSL_SYSCTRL_REGS->DMAIFR;
CSL_SYSCTRL_REGS->DMAIFR |= ifrValue;
Shine:
请问SYNCMODE=1吗?
The auto-initialization feature can only be used when event synchronization is used (SYNCMODE = 1 in DMACHmTCR2).
Shide Lu:
回复 Shine:
查看资料后,终于知道了,自动加载只能用在事件触发模式(dmaConfig.trigger = CSL_DMA_EVENT_TRIGGER)。软件触发模式(CSL_DMA_SOFTWARE_TRIGGER)下不支持自动加载。
现在遇到了新问题,我用I2S的TX事件触发,为什么仍然只能进入一次中断?
关键代码:
CSL_Status I2sDmaInit(void) {I2S_Config hwConfig;CSL_DMA_Config dmaConfig;CSL_Status status;/* DMA engine initialization *//* Open the device with instance 2 (AIC3204 is connected to I2S2 on C5515 EVM) */hI2s = I2S_open(I2S_INSTANCE, DMA_INTERRUPT, I2S_CHAN_STEREO);if(NULL == hI2s){status = CSL_ESYS_FAIL;return (status);}else{LOG_printf(&trace,"I2S Module Instance opened successfully\n");}/* Set the value for the configure structure */hwConfig.dataFormat= I2S_DATAFORMAT_LJUST;hwConfig.dataType= I2S_STEREO_ENABLE;hwConfig.loopBackMode= I2S_LOOPBACK_DISABLE;hwConfig.fsPol= I2S_FSPOL_LOW;hwConfig.clkPol= I2S_FALLING_EDGE;hwConfig.datadelay= I2S_DATADELAY_ONEBIT;hwConfig.datapack= I2S_DATAPACK_DISABLE;hwConfig.signext= I2S_SIGNEXT_DISABLE;hwConfig.wordLen= I2S_WORDLEN_16;hwConfig.i2sMode= I2S_SLAVE;hwConfig.clkDiv= I2S_CLKDIV2; // don't care for slave modehwConfig.fsDiv= I2S_FSDIV32; // don't care for slave modehwConfig.FError= I2S_FSERROR_DISABLE;hwConfig.OuError= I2S_OUERROR_DISABLE;/* Configure hardware registers */status = I2S_setup(hI2s, &hwConfig);if(status != CSL_SOK){return (status);}else{LOG_printf(&trace,"I2S Module Configured successfully\n");}/* Configure DMA channel 0 for I2S left channel read */dmaConfig.pingPongMode= CSL_DMA_PING_PONG_DISABLE;dmaConfig.autoMode= CSL_DMA_AUTORELOAD_ENABLE;dmaConfig.burstLen= CSL_DMA_TXBURST_1WORD;dmaConfig.trigger= CSL_DMA_EVENT_TRIGGER;dmaConfig.dmaEvt= CSL_DMA_EVT_I2S2_TX;dmaConfig.dmaInt= CSL_DMA_INTERRUPT_ENABLE;dmaConfig.chanDir= CSL_DMA_WRITE;dmaConfig.trfType= CSL_DMA_TRANSFER_IO_MEMORY;dmaConfig.dataLen= NUM_SAMP_PER_MS*NUM_MS_PER_FRAME*2; // two framesdmaConfig.destAddr= (Uint32)&CSL_I2S2_REGS->I2STXLT0;dmaConfig.srcAddr= (Uint32)i2sDmaReadBufLeft;/* Open DMA ch0 for I2S left channel read */dmaLeftRxHandle = DMA_open(DMA_CHAN_L, &dmaObj0,&status);//DMA_CHAN_L = 4if (dmaLeftRxHandle == NULL){LOG_printf(&trace,"DMA_open CH4 Failed \n");dmaLeftRxHandle = NULL;}/* Configure DMA channel */status = DMA_config(dmaLeftRxHandle, &dmaConfig);if (status != CSL_SOK){LOG_printf(&trace,"DMA_config CH4 Failed \n");dmaLeftRxHandle = NULL;}// I2S_transEnable(hI2s, TRUE);/* Configure DMA ch1 for I2S right channel read */dmaConfig.pingPongMode = CSL_DMA_PING_PONG_DISABLE;dmaConfig.autoMode= CSL_DMA_AUTORELOAD_ENABLE;dmaConfig.burstLen= CSL_DMA_TXBURST_1WORD;dmaConfig.trigger= CSL_DMA_EVENT_TRIGGER;dmaConfig.dmaEvt= CSL_DMA_EVT_I2S2_TX;dmaConfig.dmaInt= CSL_DMA_INTERRUPT_ENABLE;dmaConfig.chanDir= CSL_DMA_WRITE;dmaConfig.trfType= CSL_DMA_TRANSFER_IO_MEMORY;dmaConfig.dataLen= NUM_SAMP_PER_MS*NUM_MS_PER_FRAME*2;// two framesdmaConfig.destAddr= (Uint32)&CSL_I2S2_REGS->I2STXRT0;dmaConfig.srcAddr= (Uint32)i2sDmaReadBufRight;/* Open DMA ch0 for I2S right channel read */dmaRightRxHandle = DMA_open(DMA_CHAN_R, &dmaObj1,&status);//DMA_CHAN_R = 5if (dmaRightRxHandle == NULL){LOG_printf(&trace,"DMA_open CH1 Failed \n");dmaRightRxHandle = NULL;}/* Configure DMA channel */status = DMA_config(dmaRightRxHandle, &dmaConfig);if (status != CSL_SOK){LOG_printf(&trace,"DMA_config CH1 Failed \n");dmaRightRxHandle = NULL;}// I2S_transEnable(hI2s, TRUE);/* Start left Rx DMA */status = DMA_start(dmaLeftRxHandle);if (status != CSL_SOK){LOG_printf(&trace,"I2S Dma Left Failed!!\n");return (status);}/* Start right Rx DMA */status = DMA_start(dmaRightRxHandle);if (status != CSL_SOK){LOG_printf(&trace,"I2S Dma Right Failed!!\n");return (status);}// Enable DMA interruptIRQ_enable(DMA_EVENT); // 必须,否则无法进入DMA中断/* Enable I2S */I2S_transEnable(hI2s, TRUE);return CSL_SOK; }
Shide Lu:
回复 Shine:
我要实现的功能是I2S+DMA播放音频文件。思路是通过I2S触发DMA传输RAM数据到I2S数据寄存器,DMA使用Ping-Pong模式。
下面是Ping-Pong模式下的ISR,还没有完成。
// DMA ISR void DmaIsr(void) {int ifrValue;Uint32 i;CSL_Statusstatus;ifrValue = CSL_SYSCTRL_REGS->DMAIFR;CSL_SYSCTRL_REGS->DMAIFR |= ifrValue;if ((DMA_getLastTransferType (dmaLeftRxHandle, &status)) == 1){// Pong传输完成,标志位1for (i=0; i<I2S_DMA_BUF_LEN; i++){ //dmaPongSrcBuf_L[i]= dmaPongDstBuf_L[i]; //dmaPongSrcBuf_R[i]= dmaPongDstBuf_R[i];}}else{// Ping传输完成,标志位0for (i=0; i<I2S_DMA_BUF_LEN; i++){ //dmaPingSrcBuf_L[i]= dmaPingDstBuf_L[i]; //dmaPingSrcBuf_R[i]= dmaPingDstBuf_R[i];}} }https://e2echina.ti.com/question_answer/dsp_arm/c5000/f/48/p/73804/245753?tisearch=e2e-quicksearch&keymatch=DMA#245753
这个帖子的答案说,“#2. 在中断ISR里要读一下DMACSR清除状态。”,是否指的是8~9行的操作?
Shide Lu:
回复 Shine:
另外,我是在DSP/BIOS下使用的上述代码,是否有什么冲突?
DmaIsr函数已经通过.tcf文件配置为HWI_INT8的ISR。主文件完整内容见附件。
5153.tsk.c
TI中文支持网



