主控:imx8mp
内核:linux5.4.70
声卡:sgtl5000
应用程序:基于mmap方式,向dma buffer中搬移数据。
故障现象:当应用程序播音一段时间,内核出现 fsl-sai 30C3000.sai:isr:Transmit underrun detected的刷屏打印,对应具体的内核文件:./kernel/kernel-5.4.70/sound/soc/fsl/fsl_sai.c文件。
...........
if(flags & FSL_SAI_CSR_FEF) {
dev_dbg(dev,"isr:Transmit underrun detected\n");
/* FIFO reset for safety*/
xcsr |= FSL_SAI_CSR_FR;
}
...........
同时使用指令cat /proc/interrupts | grep sdma 查看声卡对那个的dma中断计数,停止增加。
在目前代码的设置里面,是不是当FIFO出现underrun的情形之后,FIF状态异常,进而导致dma工作异常呢?
查看imx8mp的规格书,有这样一个描述FCONT:IMX8MPPRM文档 14.4.2.7.3章节。When FIFO Continue on Error is enbaled,the FIFO continues transmitting data following an underrun without software intervention. To ensure that data transmits in the correct order,the transmitter continues from the same word number in the frame that caused the FIFO to inderrun,but only after new data writes to transmit FIFO ............................................
按照规格书的这段配置,针对这样的情况 是不是出现underrun之后,dma还可以正常工作,只要dma将数据搬移至fifo,就可以继续之前的声音播放,而不是像之前的dma异常工作,而FIFO处于underrun状态呢?
Hi @zhuliushun
1.对FCONT 的理解方向基本正确,但是FCONT不是根本上的解决办法。
2.根本原因还是TX FIFO 投喂速度 < 消耗速度,这个你可以调试看看,是不是这样。
3.可以考虑打入下面的两个补丁:
LKML: Shengjiu Wang: [PATCH] ASoC: fsl_sai: Enable 'FIFO continue on error' FCONT bit
ASoC: fsl_sai: Remove unnecessary FIFO reset in ISR - Patchwork
Best Regards,
Zhiming
Hello @Zhiming_Liu
是的,这个问题的原因是FIFO填充慢的速度小于fifo的数据消耗速度。而FIFO填充是基于DMA来实现的。
1. 目前调试发现:当FIFO消耗完之后,FIFO发生underrun,同时dma也不工作,这样也不会填充fifo。
2. 将帖子中的2个patch打入之后,调试发现fifo依然后发生underrun,同时dma不工作。
在fsl_sai.c的中断回调函数中fsl_sai_isr()中,打印出xcsr的值与tcr4的值。具体如下所示:
fsl-sai 30c30000.sai scsr :status:0xd0170c01
fsl-sai 30c30000.sai isr: transmit inderrun detected,tcr4: 0x18010f3a
当故障发生的时候,上述的打印一直在刷屏打印
3. 依据2的发现.tcr4中bit[28] =1,FCONT是使能的。
4. 针对我的问题:播放音频文件卡死问题(fifo underrun,dma不工作,一直卡死)。我的一个期望的解决方案:当fifo发生underrun的时候,保留硬件数据搬移现场,不复位,dma工作正常。等到buffer有数据的时候(应用程序以mmap方式填充buffer),dma(依据fifo发过来的dma request)将数据搬移至fifo,这样音频文件可以继续接着播放,不知道这样可以实现吗?