【问题标题】:Critical Timing in an ARM Linux Kernel DriverARM Linux 内核驱动程序中的关键时序
【发布时间】:2013-06-15 08:28:17
【问题描述】:

我在 MX28 (ARMv5) 上运行 linux,并使用 GPIO 线与设备通信。不幸的是,该设备有一些特殊的时序要求。 GPIO 线上的低电平不能持续超过 7us,高电平没有特殊的时序要求。该代码作为内核设备驱动程序实现,并通过直接寄存器写入而不是通过内核 GPIO api 来切换 GPIO。为了测试,我只产生 3 个脉冲。流程如下,全在一个函数中,所以它应该适合指令缓存:

  • 将 gpio 设置为高
  • 保存标志并禁用中断
  • gpio 低
  • 暂停
  • gpio 高
  • 再重复 2 次​​li>
  • 恢复标志/重新启用中断

这是连接到 GPIO 的逻辑分析仪的输出。

大多数情况下,它的效果都很好,脉冲持续时间不到 1us。然而,大约 10% 的低点会持续很多很多微秒。即使中断被禁用,某些东西也会导致代码流被中断。

我很茫然。 RT Linux 在这里可能无济于事,因为问题不在于延迟,它似乎是在低电平期间发生的事情,即使在禁用 IRQ 时没有任何东西可以中断它。任何建议将不胜感激。

【问题讨论】:

  • 是否有一些额外的核心或功能单元(DMA 等)可以占用总线?如果系统运行诸如 uboot 之类的东西,您是否可以尝试将代码构建到其中作为比较测试,或者在内核启动的早期在初始化之前在纯汇编中执行它?
  • 我不这么认为。 GPIO 是专用的。这看起来像 cpu 停止执行代码一段时间。我怀疑正在发生的是页面错误或类似的事情。我尝试在它的开头添加一个障碍,以防万一出现乱序执行的问题,但它没有改变任何东西。 U-Boot 充当引导加载程序,而我现在执行的大部分代码已经是汇编程序,所以我可能可以在 u-boot 中添加一个命令来执行此操作。
  • @Arcane:如果您在禁用中断的情况下出现页面错误,那么事情不会暂停——它们会中断。太可怕了。 Chris 正在讨论的内容(主内存总线上的多个总线主控器)将导致内核暂停执行(在 fetch-decode-execute 的“fetch”阶段),直到其他总线事务完成。例如,显示控制器通常具有优先权,因为从帧缓冲区中延迟读取会导致显示损坏。
  • 智能使用指令缓存可能会避免通过主内存总线加载代码。
  • 它甚至可能不是与另一个总线主机的竞争,它可能只是缓存未命中。您的 DRAM 使用什么时钟速度和 CAS 延迟?

标签: linux linux-kernel kernel arm driver


【解决方案1】:

IMX25 (ARM926) 上的 ARM 缓存 是 16K 代码、16K 数据 L1,长度为 32 字节或 8 条指令。 DDR-SDRAM 控制器以 133Mhz 和 16 位总线运行,传输速率约为 300MB/s。一次缓存填充应该只需要大约 100nS,而不是 9uS;这大约长了 100 倍。

但是,Linux 还存在其他四个问题。

  1. TLB 未命中和页表遍历。
  2. 数据中止。
  3. DMA 主机窃取。
  4. FIQ 中断。

除非您的显示器很大,否则 LCD 主机不太可能窃取足够的带宽。您的显示器是否大于 1/4VGA?如果没有,这只是内存带宽的 10%,这将与处理器一起流水线化。您是否有以太网或 USB 处于活动状态?这些外设具有更高的数据速率,可能会导致与 SDRAM 的此类争用。

所有这些问题都可以通过编写您的切换器 PC 相关文件并将其复制到 IRAM 来避免。见:iram_alloc.c;这个文件应该可以移植到旧版本的 Linux。 XBAR 开关允许同时从 SDRAM 和 IRAM 取数据。 IRAM 仍然可以成为其他 DMA 主设备的目标。如果你真的很紧张,请将代码移动到系统中其他主机无法访问的 ETB 缓冲区。

TLB 未命中实际上可能非常陡峭,因为它可能需要运行几个单拍 SDRAM 周期;仍然应该低于 1uS。您尚未发布代码,因此可能是某个变量和/或其他变量导致了一个不可屏蔽的数据错误

如果您有任何使用 FIQ 的驱动程序,即使您屏蔽了正常的 IRQ 中断,它们也可能仍在运行。例如,该系统的 ALSA 驱动程序通常使用 FIQ

ETBIRAM 都是 32 位数据路径和低等待状态。任何一个都可能比 DDR-SDRAM 提供更好的响应。

我们已经通过使用 FIQIRAM 来实现亚微秒级的响应,通过使用 bit banging 的另一种协议来切换 IMX258 上的 GPIO。

【讨论】:

  • 向您FAE询问内部总线PDF。它将有助于显示哪些内存/外围设备会导致系统配置争用。即,它是一个DMA主从连接图。
  • 此硬件上没有显示,但它的以太网和 USB 都在正常工作。
【解决方案2】:

解决 Chris 提到的问题(除了内核模块代码的分页问题)的一种可能解决方法是使用 PWM 外设,其中脉冲的持续时间是预先编程的,并且计时是在硬件中实现的。

带有缓存的高级处理器不适合硬实时工作。如果缓存未命中是不确定的,则执行时间会有所不同(并且缓存未命中完全确定的设计还不够复杂,不足以证明一个花哨的处理器是合理的)。

您可以通过对齐关键部分来避免内存控制器在关键部分出现延迟,使其不会跨越高速缓存行。或者预取您需要的代码。但这将是非常不便携的,并为未来的维护创造了一场噩梦。而且仍然不能保护对内存映射 GPIO 的访问免受总线争用。

【讨论】:

  • 我有一个使用 PWM 的后备方案。然而,这个协议(spy-bi-wire)还有其他因素需要我在 gpio 拉低时从一行读取,所以我仍然有时间关键问题。
  • @Arcane:为此,您可以添加一个外部 D 触发器来注册您正在读取的线路,并从我们正在讨论的 GPIO 为其计时。控制线上升沿之前数据线上的任何值都将被锁存。
猜你喜欢
  • 2014-02-05
  • 2015-12-31
  • 2015-01-23
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 2017-03-02
  • 2023-03-18
  • 2012-03-12
相关资源
最近更新 更多