STM32 - 隔行扫描 SAI 同步接收器

问题描述 投票:0回答:1

我正在进行一个项目,该项目涉及使用两条数据线接收 I2S 信号,每条数据线承载一个音频通道,共享相同的字和位时钟。为此,我在 STM32F7 MCU 上使用 SAI(串行音频接口)。它是为此而设计的,因为每个 SAI 实例都有两个“子块”A 和 B(如参考手册中所述),它们可以同步在一起以共享相同的位和字选择时钟。

为了接收我的 I2S 信号,我将 A 和 B 子块配置为接收 16 位 I2S 字并共享相同的时钟(A 异步,B 与 A 同步)。这工作正常并且使用 DMA 同步捕获样本,但问题是它们最终在内存中的两个单独缓冲区中:(每个单元格是一个字节,每个样本两个字节;蓝色是 SAI A,绿色是 SAI B)

但是,我希望每个 SAI 子块中的每个 2 字节样本在内存中交错排列,因此一个样本来自 A,下一个样本来自 B,依此类推,就像通常存储的音频一样:

编写一个 for 循环将两个缓冲区交织在一起对我来说很简单,但这会消耗大量 CPU 时间,而这些时间本可以用来做其他事情。我想知道是否有一些我忽略的硬件技巧或功能可以帮助我实现这一目标。 老实说,我很惊讶 SAI 功能没有任何一种本地方法来执行此操作,但我已经看过通过 reference manual 的整个部分,没有看到任何对我有帮助的东西。

想法,以及我尝试过的

如果 STM32 的 DMA 功能允许输出内存指针增加与传输数据不同的大小(例如,只传输两个字节但输出指针增加四个)这会很容易,但事实并非如此除非我使用 DMA 的 FIFO 功能,否则似乎不会。使用 FIFO 模式,我可以让它将一个 16 位样本缓冲到一个 32 位缓冲区中,并在缓冲区半满时将该缓冲区写入输出,通过将每个 16 位样本与另一个 16 位分开来有效地“腾出空间” , 如下所示。但是,这仅适用于一个通道,因为它似乎覆盖了所有 32 位,即使它们并未全部使用。 CPU 仍然必须工作以将另一个通道转移到那个未使用的空间。

此外,我使用 2D DMA 功能提出了一个有点笨拙的解决方案,该功能旨在用于渲染图像。对一个通道使用上述方法,同时对另一个通道使用普通 DMA,我可以使用 2D DMA 功能将第二个通道复制到第一个通道缓冲区中为其创建的未使用空间。为此,我有效地配置了 2D DMA 以将大小为

1x<buffer size>
的 16bpp“图像”(就其而言)传输到画布“图像”中,即
2x<buffer size>
,使其跳过所有其他输出“像素”(这实际上是一个样本)。它很简陋,但它在我的原型板上工作。然而,不幸的是,我实际要用于该项目的 STM32 不支持此功能,因此它没有用。

tl;博士;

我可以使用任何硬件技巧将两个 16 位样本缓冲区交织到另一个缓冲区中,以便两个缓冲区中的每个样本都一个接一个,就像通常存储音频一样?理想情况下,这将在 CPU 不需要做太多工作的情况下完成。如果没有,也许有一些特定的汇编指令可以比简单的 C for 循环更快地完成这项工作?

谢谢,我真的很感激。

audio embedded stm32 dma
1个回答
0
投票

我有一个类似的问题,它确实来自错误的 DMA 传输设置,32 位(CubeMX 中的默认设置)而不是 16.

© www.soinside.com 2019 - 2024. All rights reserved.