我正在 FRDM-MCXN947 上构建一个实时 ANC 系统,音频硬件如下:
该系统要求每 16 ms 帧同时捕获所有 4 个麦克风。
由于 MCXN947 只为 提供了 一条 用于 SAI1 RX 的 DMA 请求线
(kDma0RequestMuxSai1Rx = 101U),因此 FIFO 组合模式 (RCR4.FCOMB) 是
SDK 支持的唯一路径,可通过单个 DMA 通道同时接收 RXD0 和 RXD1。
SDK 版本: MCUXpresso SDK (mcuxsdk-core, commit 0455af2)
驱动程序版本: fsl_sai v2.4.11 / fsl_sai_edma v2.7.4
文件: drivers/sai/fsl_sai.c
SAI_RxSetConfig() 无条件清除 RCR4.FCOMB channelNums> 1,
,即使调用者明确设置 fifoCombine = kSAI_RXFifoCombineModeEnabledOnRead。
呼叫链是
SAI_RxSetFifoConfig() (fsl_sai.c)第 1103-1105
行)- 从 config->fifoCombine 正确设置 RCR4.FCOMB :
rcr4 &= ~I2S_RCR4_FCOMB_MASK; rcr4 |= I2S_RCR4_FCOMB(config->fifoCombine); // ← set correctly base->RCR4 = rcr4;
SAI_RxSetConfig() (fsl_sai.c)第 1439-1444 行) -在 第 1 步之后运行 ,
无条件清除:
/* make sure combine mode disabled while multipe channel is used */
if (config->channelNums > 1U)
{
base->RCR4 &= ~I2S_RCR4_FCOMB_MASK; // ← always clears, ignores fifoCombine
}SAI_TransferRxSetConfigEDMA() (fsl_sai_edma.c)第 362-368 行)--有一个 assert()
,正确地 要求 fifoCombine 在 channelNums> 1 时非零,但
验证的是配置结构,而不是硬件寄存器。当
RCR4.FCOMB 在硬件中已经为 0 时,断言通过。
第 2 步的注释说 "确保在使用多通道时禁用组合模式"
- 这似乎是将 TX 端逻辑错误地应用到了 RX 端。对于 RX,如 fsl_sai_edma.c 中的示例代码
所述,多通道 DMA需要使用 的 FIFO
组合模式。 第 340-350 行。
调用 SAI_TransferRxSetConfigEDMA() 后, channelMask = kSAI_Channel0Mask | kSAI_Channel1Mask
和 fifoCombine = kSAI_RXFifoCombineModeEnabledOnRead:
恢复到单通道(仅 kSAI_Channel0Mask , channelNums=1)可立即恢复
完整系统运行。
fsl_sai.h 中的 _sai_fifo_combine 枚举 (第 272-277 行)使用对换的数值
表示 TX 和 RX 方向:
kSAI_FifoCombineModeEnabledOnRead = 1U, // TX only kSAI_RXFifoCombineModeEnabledOnRead = 2U, // RX only
fsl_sai_edma.c 中的示例代码 第 348 行使用 kSAI_FifoCombineModeEnabledOnRead
(TX 枚举,值=1)进行 RX 配置。在
FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE=1 的设备上,它会静默配置 RX 的写入组合而不是读取组合。
目前,我通过在 SAI_TransferRxSetConfigEDMA() 返回后手动恢复 RCR4.FCOMB
来解决这个问题:
SAI_TransferRxSetConfigEDMA(SAI1, &s_saiRxHandle, &rxConfig); /* Workaround: fsl_sai.c:1443 clears RCR4.FCOMB unconditionally when channelNums>1 */ SAI1->RCR4 = (SAI1->RCR4 & ~I2S_RCR4_FCOMB_MASK) | I2S_RCR4_FCOMB(2U);
这很脆弱,需要绕过 SDK API 直接访问寄存器。
完整的错误报告及完整的调用链分析附后。
感谢您的时间和支持。
致以最崇高的敬意,
Huynh Mao
[email protected]
你好@maohuynh、
感谢您的耐心等待。
你好@maohuynh、
谢谢您的帖子。 我目前正在调查您提出的问题,并将尽快给您回复。
BR
西莱斯特
您好@Celeste_Liu,
谢谢您的说明。
重新阅读源代码后,
,我同意 SAI_RxSetFifoConfig() 在清除后确实恢复了 RCR4.FCOMB - 您对执行顺序的解释是正确的。
然而,硬件故障的根本原因是另一个问题:枚举 _sai_fifo_combine 在 TX 和 RX 之间共享数值,但对于相同的数值,TCR4.FCOMB 和 RCR4.FCOMB 的硬件编码是相反的(在 PERI_I2S.h 中得到证实):
fsl_sai_edma.c 中的示例代码第 348 行指示 fifoCombine = kSAI_FifoCombineModeEnabledOnRead(= 1),这是TX枚举。对于 RX DMA 读取来说,它的名称听起来没错,但其数值(1)映射的是 RCR4 上的写合并,而不是读合并。第 366 行的断言验证了同样的错误值,并默默通过,因此在硬件配置错误时没有报错。
我采用的变通方法是在 SAI_TransferRxSetConfigEDMA() 之后直接写入 I2S_RCR4_FCOMB(2U)。恩智浦能否确认第 348 行的示例是否应使用 kSAI_RXFifoCombineModeEnabledOnRead (= 2),以及是否应相应更新第 366 行的断言?
您能帮我检查一下吗?
BRs、
毛慧
你好@maohuynh、
我已经审查了代码,你的观点很有道理。我会将此问题报告给我们的内部 SDK 团队,以便进一步修复。
BR
西莱斯特