Raspberry:通过 DMA 的 PWM 是如何工作的?

Jon*_*nny 2 c hardware dma raspberry-pi pwm

我读到“软件 PWM”的驱动程序以某种方式在 PWM-HW 上运行,并在不使用 CPU 的情况下访问所有 GPIO。有人可以解释它是如何工作的吗?Raspberry Pi 中是否有第二个处理器用于 PWM 和 PCM 模块(是否有块图)?

这个问题与我在我的机器人中经常使用的这个优秀的驱动程序有关。

这是解释,不幸的是我不明白......

驱动程序通过设置 DMA 控制块的链接列表来工作,最后一个链接回第一个,因此一旦初始化,DMA 控制器就会连续循环,除非需要更改脉冲宽度,否则驱动程序不需要参与. 对于给定的周期,有两个 DMA 控制块;第一个将单个字传输到 GPIO“清除输出”寄存器,而第二个将一定数量的字传输到 PWM FIFO 以生成所需的脉冲宽度时间。此外,穿插这些控制块的是每个配置的伺服器,用于设置输出。

虽然驱动程序确实使用了 PWM 外设,但它仅使用它来调整 DMA 传输的速度,从而产生准确的延迟。”

以下理解是否正确:

DMA 控制器就像第二个处理器。您可以在其上运行代码。因此,这里使用它与 PWM 块一起控制所有 Raspberry GPIO 引脚的高/低状态。DMA 控制器会连续执行此操作。Raspberry 中可能有不止一个 DMA 控制器,因此 OS Linux 的速度不会因为缺少一个 DMA 控制器而受到太大影响。

我不明白 DMA 和 PWM 究竟是如何协同工作的。

Pie*_*ica 5

我建议阅读RPIO 源代码ServoBlaster 的,因为它稍微简化了,可以帮助理解。同样非常重要:Broadcom 的 BCM2835 手册,其中包含所有微小的细节。

有没有方块图

该手册包含该芯片提供的所有功能(但就我所见,不在框图中)。

以下理解是否正确:

DMA 控制器是主芯片的一部分(Broadcom,虽然我认为桌面 CPU 上也会发生同样的情况)。它不能完全运行代码,但它可以自己跨外设复制内存,而不会消耗主处理器的时间。DMA 控制器有不同的通道,可以独立复制内存,独立于 CPU 运行。

它可以通过“控制块”(BCM 手册第 40 页,4.2.1.1)进行配置:您可以告诉 DMA 控制器首先将内存从 A 复制到 B,然后从 C 复制到 D,依此类推。

不明白 DMA 和 PWM 究竟是如何协同工作的

DMA用于将数据发送到 PWM 控制器(“脉宽调制器”,BCM 手册第 138 页,第 9 章),后者消耗数据并产生非常精确的延迟。有趣的是,PWM 控制器……不是用来产生任何 PWM 脉冲的,而是用来等待的。

有人可以解释它是如何工作的吗?

最终,您通过在特殊地址设置内存来配置 GPIO 引脚的值(或 PWM 或 PCM 发生器的设置);该区域中的内存代表外设配置(BCM 手册第 89 页,第 6 章)。

所以想法是: 使用DMA控制器将1复制到控制GPIO引脚值的内存上;等待脉宽;将 0 复制到 GPIO 引脚值;等待剩余时间;环形。由于 DMA 控制器执行此操作,因此不会消耗 CPU 周期。

这里的关键点是能够让 DMA 控制器“等待”一个确切的时间量,为此,RPIO 和 ServoBlaster 在 FIFO 模式下使用 PWM 控制器(PCM 发生器也有这样的功能,但让我们坚持使用 PWM) . 这意味着 PWM 控制器将“发送”它从其所谓的 FIFO 队列中读取的数据,然后停止。它是如何“发送”的并不重要(BCM 手册页 139, 9.4 MSENi=0),关键是它需要固定的时间。事实上,发送哪个数据并不重要:DMA 控制器被配置为写入 FIFO 队列,然后等待 PWM 控制器完成发送数据,这会产生非常精确的延迟。

结果脉冲的分辨率由 PWM 传输的持续时间决定,该持续时间取决于 PWM 控制器运行的频率。

例子

我们有 1ms 的最大分辨率(由 PWM 延迟给定),我们希望有一个频率为 125Hz 的占空比为 25% 的脉冲。因此一个脉冲的周期是 8ms。执行的 DMA 操作将是

  1. 将引脚设置为 1(DMA 写入 GPIO 内存)
  2. 等待 1ms(DMA 写入 PWM FIFO)
  3. 等待 1ms(DMA 写入 PWM FIFO)
  4. 将引脚设置为 0(DMA 写入 GPIO 内存)
  5. 等待 1ms(DMA 写入 PWM FIFO)
  6. ...再重复“等待 1 毫秒”4 次。
  7. 等待 1ms(DMA 写入 PWM FIFO)并跳回 1。

因此,这将需要至少 10 个 DMA 控制块(8 个等待指令,由周期/延迟加上 2 个写操作给出)。

注意: 在 ServoBlaster 和 RPIO 中,它将正好消耗 16 个 DMA 控制块,因为(为了更高的精度),它们总是在“等待操作”之前执行“内存复制”操作。“内存复制”操作只是一个虚拟操作,除非它需要更改引脚值。