有关C5510DSK应用中的DMA设置问题
今天研究C5510DSK所带的例子dsk_app(examples\dsk5510\bsl\dsk_app)的DMA设置,结果发现两个问题,这两个问题将在程序运行瞬间产生噪声。
先简要介绍一下dsk_app设置DMA的方法。
在DSP/BIOS Config中为DMA0设置handle名为hDmaXmt,DMA1的handle名为hDmaRcv,这两个DMA分别传输数据到McBSP和从McBSP接收数据。
这两个DMA对应的配置分别为dmaCfgTransmit和dmaCfgReceive,可在dsk_app2.cdb中的Chip Support Library -> DMA -> DMA Configuration Manager中找到。
DMA 配置为Auto init。这里稍微解释一下Auto Init的工作原理。DMA的寄存器分为配置寄存器和工作寄存器,用户设置配置寄存器,在启动DMA的时候DMA控制器将配置寄存器的内容复制到工作寄存 器中,然后按照工作寄存器的设置工作。若设置了Auto Init则当DMA传输完毕的时候,自动载入当时的配置寄存器的内容到工作寄存器,并按照其设置工作。因此Auto Init可以方便的让DMA不间断地工作,这在语音输入输出时非常有用。
声音的输入输出缓存都采用PingPong缓存,当DMA写 Ping缓存的时候,系统处理Pong缓存的数据,写Pong缓存的时候,处理Ping缓存的数据。输入DMA(hDmaRcv)一开始设置为写输入 Ping缓存(gBufferRcvPingL,gBufferRcvPingR),而输出DMA则读输出Ping缓存。由于此时输出缓存中没有实际数 据,因此在启动DMA之前应先将输出PingPong缓存清零,但是例子程序中并没有这么做,这是造成程序运行瞬间产生噪声的第一个原因。
程 序初始设置存取输入输出的Ping缓存,当DMA开始时,DMA控制器将设置读入工作寄存器,此时应该继续设置配置寄存器为存取Pong缓存,这样当输入 Ping缓存满(而输出Ping缓存空)的时候,Auto Init将自动载入存取Pong缓存的设置,从而继续存取Pong缓存。但是程序中并没有这么做,这样,程序启动时首先存取Ping缓存,Ping缓存满 了之后,载入的设置仍然是存取Ping缓存。下一次载入的仍然是Ping缓存的设置,直到第3次载入设置的时候,才会切换到Pong缓存,因此程序存取 PingPong缓存的顺序是 Ping Ping Ping Pong Ping Pong …,而正确的顺序应该是:Ping Pong Ping Pong …,即第二个Ping应当为Pong。由于第二次传输的时候仍然使用Ping缓存,而声音处理程序处理已传输完毕的缓存也是Ping,这样就造成了数据的 冲突,以至产生噪声。
具体的修改办法也很简单,把processBuffer函数中设置DMA存取Pong缓存的程序复制到main函数中启动DMA的语句之后即可:
void main(){
…
// Start the DMA
DMA_start(hDmaRcv);
DMA_start(hDmaXmt);
// 添加下面的设置,DMA传输完毕,自动载入配置寄存器时,将开始存取Pong缓存。
// Configure the receive channel for pong input data
addr = ((Uint32)gBufferRcvPongL) << 1;
DMA_RSETH(hDmaRcv, DMACDSAL, addr & 0xffff);
DMA_RSETH(hDmaRcv, DMACDSAU, (addr >> 16) & 0xffff);
// Configure the transmit channel for pong output data
addr = ((Uint32)gBufferXmtPongL) << 1;
DMA_RSETH(hDmaXmt, DMACSSAL, addr & 0xffff);
DMA_RSETH(hDmaXmt, DMACSSAU, (addr >> 16) & 0xffff);
}
虽然这两个问题只会在程序启动瞬间产生噪声,作为一般的演示程序并无大碍,但是如果把它写进产品了的话,就有些麻烦了。
|
|
|
|