i.MX8M Mini fsl_micfil驱动因DMA未就绪启动挂死问题咨询
i.MX8M Mini MICFIL驱动早期启动采集挂死问题修复
问题环境
- 硬件:基于NXP i.MX8M Mini SoC的定制嵌入式设备
- 系统:NXP Yocto Hardknott版本构建的Linux发行版,内核采用NXP官方lf-5.10.y分支
linux-imx,对应BSP版本为5.10.52-2.1.0 - 音频外设:板载数字麦克风,使用定制修改的NXP官方
fsl_micfil.c驱动,源码路径为sound/soc/fsl/fsl_micfil.c
驱动定制修改点
共对官方驱动做了三处适配调整:
- 通道使能逻辑修改(位于
fsl_micfil_hw_params函数约1592行)
原逻辑为按传入的通道数使能对应数量的低位通道:
修改为固定仅使能第6采集通道:ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1, 0xFF, ((1 << channels) - 1));ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL1, 0xFF, 1 << 6); - 硬件使能GPIO控制逻辑添加(位于
fsl_micfil_probe函数起始位置约2202行)
探测阶段执行拉低麦克风硬件使能GPIO的操作,若探测时GPIO子系统未完成初始化,直接返回-EPROBE_DEFER延后驱动探测流程。 - DMA接收地址匹配修改(位于
fsl_micfil_probe函数约2334行)
原逻辑默认配置DMA接收地址为0通道数据寄存器:
修改为匹配第6通道的数据寄存器地址:micfil->dma_params_rx.addr = res->start + REG_MICFIL_DATACH0;micfil->dma_params_rx.addr = res->start + REG_MICFIL_DATACH6;
故障现象
- 系统启动完成后立刻启动音频采集(可直接通过
arecord命令复现)读取麦克风数据时,设备会直接硬挂死,仅能通过断电重启恢复 - 等待系统启动约60秒,待控制台打印如下SDMA固件加载完成日志后,再启动音频采集,麦克风功能可完全正常工作:
[ 60.386133] imx-sdma 302c0000.dma-controller: firmware found. [ 60.392010] imx-sdma 302c0000.dma-controller: loaded firmware 4.6
根因定位
查阅imx-sdma驱动源码(路径drivers/dma/imx-sdma.c)可确认:
- SDMA驱动启动时需要加载专属固件,其中
firmware found日志在驱动probe流程打印,loaded firmware日志在sdma_resume/sdma_runtime_resume电源管理恢复流程中打印 - 5.10版本内核的imx-sdma驱动默认启用运行时PM懒初始化机制,系统启动后不会立刻加载固件,直到首次有设备请求SDMA服务时才会触发恢复流程加载固件,实际测试该触发延迟约为60秒
- 现有fsl_micfil驱动未正确关联SDMA的运行时PM依赖,启动采集时没有主动等待SDMA完成固件加载就绪,直接配置DMA寄存器启动传输,触发SDMA硬件异常导致系统挂死
- 4.14版本内核的imx-sdma驱动未启用该懒加载机制,驱动probe阶段就会完成固件加载,因此相同定制修改不会触发该故障。
标准修复方案
不需要在fsl_micfil驱动中编写自定义的主动唤醒、轮询SDMA状态的逻辑,直接使用内核通用的运行时PM依赖框架即可解决,具体修改如下:
- 建立设备PM依赖:在
fsl_micfil_probe函数完成DMA通道配置、调用devm_snd_dmaengine_pcm_register注册PCM设备前,添加如下代码,主动建立MICFIL设备与SDMA控制器的PM依赖,探测阶段就触发一次SDMA的恢复流程提前加载固件:struct device *sdma_dev = micfil->dma_params_rx.dev; if (sdma_dev) { pm_runtime_enable(&pdev->dev); /* 触发SDMA上电恢复,完成固件加载 */ pm_runtime_get_sync(sdma_dev); pm_runtime_put_sync(sdma_dev); /* 建立父子设备PM依赖,后续runtime PM操作自动联动 */ pm_runtime_link_init(&pdev->dev, sdma_dev); } - 采集流程加PM引用保护:在
fsl_micfil_trigger函数的SNDRV_PCM_TRIGGER_START分支中,启动MICFIL硬件采集前先调用pm_runtime_get_sync(sdma_dev)持有SDMA的运行时引用,确保SDMA处于工作状态;在SNDRV_PCM_TRIGGER_STOP分支中,停止采集后调用pm_runtime_put_sync(sdma_dev)释放引用,允许SDMA进入低功耗状态。 - 注意:不要修改imx-sdma驱动关闭懒加载逻辑,该机制是内核为降低系统待机功耗设计的标准特性,通过PM依赖链路触发设备就绪是框架约定的标准实现,不会引入跨版本兼容性问题。
内容的提问来源于stack exchange,提问作者David C.
相关产品推荐
相关产品推荐

