我正在开发一个基于NXP i.MX8M迷你SoC的嵌入式设备。它运行Linux是基于NXP的"hardknott“Yocto食谱:https://source.codeaurora.org/external/imx/imx-manifest/tree/imx-5.10.52-2.1.0.xml?h=imx-linux-hardknott
下面是它正在使用的内核的bitbake脚本:https://source.codeaurora.org/external/imx/meta-imx/tree/meta-bsp/recipes-kernel/linux?h=hardknott-5.10.52-2.1.0
我相信它正在从这里提取内核资源:https://source.codeaurora.org/external/imx/linux-imx/tree/?h=lf-5.10.y
我们的设备有一个数字麦克风,它是由NXP的fsl_micfil.c驱动程序https://source.codeaurora.org/external/imx/linux-imx/tree/sound/soc/fsl/fsl_micfil.c?h=lf-5.10.y驱动的。
我们的修改如下:
在
fsl_micfil_hw_params中,他们的代码确实“启用通道”(第1592行),我们已经将其更改为只启用我们所关心的通道,而不是所有的通道。我们改变了:
ret =regmap_update_bits(REG_MICFIL_CTRL1->regmap,REG_MICFIL_CTRL1,0xFF,(1 <<通道)-1);
至:
ret =regmap_update_bits(REG_MICFIL_CTRL1->regmap,REG_MICFIL_CTRL1,0xFF,1 << 6);
fsl_micfil_probe的开头(在第2202行附近),我们添加代码以将GPIO行(麦克风的启用行)拉低。如果GPIO当时不可用,则返回-EPROBE_DEFER以便稍后再试fsl_micfil_probe (第2334行)下,我们将DMA通道从0更改为6(以便与启用更改保持一致)。我们改变了:
消旋->dma_params_rx.addr= res->start + REG_MICFIL_DATACH0;
至:
->dma_params_rx.addr= res->start + REG_MICFIL_DATACH6;
在被描述之后,这就是问题所在。
我们的应用程序正在尝试从这个麦克风读取音频(我们可以使用arecord命令来测试它)。
我们发现,如果我们在Linux启动后立即启动应用程序,设备就会挂起。我们得给它供电才能恢复。
但是,如果在启动后等待大约60秒,控制台上会出现以下消息:
[ 60.386133] imx-sdma 302c0000.dma-controller: firmware found.
[ 60.392010] imx-sdma 302c0000.dma-controller: loaded firmware 4.6如果我们在这些消息出现后启动我们的应用程序,那么一切都正常。
我查看了imx-sdma驱动程序:https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/dma/imx-sdma.c?h=lf-5.10.y的实现。
驱动程序在启动时加载某种固件。第一条消息(“固件发现”)由探测函数呈现。第二种(“加载固件”)由两个电源管理恢复函数(sdma_resume或sdma_runtime_resume)之一提供。
因此,问题似乎是,这个DMA驱动程序直到系统运行了大约60秒后才开始加载。我认为这是由于某种延迟的初始化,直到某些内核驱动程序需要访问时才进行初始化。我的问题正在发生,因为我的驱动程序需要访问,并且在DMA驱动程序加载之前正在初始化。
那么,什么是好的解决办法呢?我假设我需要在fsl_micfil驱动程序中添加一些东西来请求启动DMA驱动程序。但我不知道该怎么做,我也不知道这是否是解决这个问题的正确方法。
你有什么建议来解决这个错误呢?
(FWIW,我们对内核的旧版本做了非常类似的修改-基于Yocto的"sumo“分支,运行内核4.14,没有问题。)很明显,内核4.14和5.10之间发生了一些变化,我们的代码需要处理,但我不知道这可能是什么。)
发布于 2022-10-14 05:07:21
我最终找到了解决这个问题的原因(但不是最好的解决方案)。
正如我在原始消息中所写的,micfil驱动程序使用imx-sdma,它试图从文件系统加载固件。
"Sumo“(内核4.14)分支对此没有问题。在驱动程序启动时,根文件系统已经被挂载(只读),所以加载它的固件没有问题。
但是,在使用"Hardknott“(内核5.10)和"Kirkstone”(内核5.15)分支时,SDMA驱动程序试图在启动序列中非常早地加载--在任何文件系统挂载之前。所以直接装载失败了。然后通过udev发布一个事件,请求用户空间代码通过sysfs提供固件。但是,驱动程序似乎启动得太早了(根据dmesg的说法,在10-15毫秒内),以至于udev无法排队等待事件。我不知道为什么,但调试表明事件从未传递到用户空间。
udev请求的内核端在60秒后超时,此时驱动程序将重新尝试请求,这是成功的,因为所有文件系统都在此之前完全挂载。
一个理想的解决方法是修改imx-sdma驱动程序,这样直到文件系统挂载之后它才会启动,因此它可以直接加载其固件。或者至少在udev准备好并能够将固件加载事件传递到用户空间之后。我让NXP知道了这个问题,所以也许他们会在他们的驱动程序的未来版本中解决这个问题。
在此之前,我的解决办法是更改内核配置,以便将imx-sdma驱动程序编译为可加载模块。这意味着它在根文件系统可用之后才能加载和启动,此时它就可以找到它的固件了。dmesg显示,这种情况在引导过程中大约发生了6s --比我希望的要晚,但早到没有应用程序软件开始运行,所以没有什么挂起或崩溃。
https://stackoverflow.com/questions/72692338
复制相似问题