我已经为Linux v4.1.15(非PREEMPT_RT)创建了一个PCIe驱动程序,其中只有一个IRQ,它是从FPGA的MSI生成的。我的ISR是:
static irq_handler int_handler(int irq, void* dev_id, struct pt_regs* regs)
{
spin_lock(&my_lock);
msi_counter++;
spin_unlock(&my_lock);
return (irq_handler_t) IRQ_HANDLED;
}
MSI每隔300 us从FPGA(Cyclone V)发送一次,我的ISR非常快速地被触发并且处理时没有失败(延迟<5 us)。问题是大约每隔3秒(抖动相对较小的3秒),我的ISR的延迟会跳到大约1.5毫秒到2毫秒;这是通过改变我的ISR来测量范围,将值写回FPGA并监控来自FPGA的引脚。 spin_lock
的{{1}}仅用于我的代码中的另一个位置,但仅用于递减计数器,就像我的ISR递增它一样。我正在使用1 GHz的iMX6四核CPU,系统正在使用简单的Yocto映像(核心映像最小),因此CPU上没有真正运行的东西。 CPU连接的唯一其他硬件是以太网,但发送的数据非常少,数据更新频率超过3秒。
我已将传递给msi_counter
的标记更改为request_irq()
以及其他值,似乎没有任何修复
这种周期性延迟增加。
此外,当我查看IRFQ_NO_SUSPEND
| IRFQ_NO_THREAD
时,它显示只有核心0
(四个核心中的第一个)是我的ISR运行的唯一核心。一世
不知道这是否有任何意义,但我认为这是值得的
提。
我创建了一个PREEMPT_RT内核映像,并使用标记cat /proc/interrupts
创建了我的ISR request_irq()
。我还将IRQF_NO_SUSPEND | IRQF_NO_THREAD | IRQF_PERCPU
替换为spin_lock
,改进来自PREEMPT_RT。我现在的平均延迟时间约为12 us。
答案 0 :(得分:0)
您可以在spin_lock之前和之后添加计时器。如果时间差异超过某个阈值,则再增加一次。你可以计算延迟是由spin_lock造成的。如果它与您看到延迟的频率相匹配,那么您可以尝试找出其他锁定持有者不释放它的原因。拿着锁可以抢先一步吗?
另一件需要关注的事情是,spin_lock本身需要很长时间才能获得低但非零的概率吗?