我们小组正在使用嵌入式处理器(Phytec LPC3180、ARM9)。我们设计了一个电路板,它在 LPC3180 的一个 I2C 总线上包含四个 MAX3107 UART 芯片。以防万一,我们正在运行内核 2.6.10,这是该处理器可用的最新版本(对该产品的支持不是很好;我们必须开发或修复 Phytec 提供的许多驱动程序,并且 Phytec似乎对升级该产品的 linux 代码(尤其是内核版本)没有兴趣。这太糟糕了,因为 LPC3180 是一个不错的设备,尤其是在不需要以太网且实际上不需要以太网的低功耗嵌入式产品的情况下'不想要以太网(由于以太网控制器芯片的相关功耗)。
当 I2C 总线上的四个设备(MAX3107 UART 芯片)之一接收到一个字符时,它会产生一个中断。所有四个 MAX3107 芯片的中断线是共享的(开漏下拉),并且该线连接到配置为电平中断的 3180 的 GPIO 引脚。当 3017 中的一个产生中断时,将运行一个处理程序,该处理程序执行以下处理(大致):
spin_lock_irqsave();
disable_irq_nosync(irqno);
irq_enabled = 0;
irq_received = 1;
spin_unlock_irqrestore()
set_queued_work(); // Queue up work for all four devices for every interrupt
// because at this point we don't know which of the four
// 3107's generated the interrupt
return IRQ_HANDLED;
请注意,这是我觉得有些麻烦的地方,即在离开上述代码之前没有重新启用中断。相反,驱动程序的编写使得中断由下半部分工作队列任务重新启用(使用“enable_irq(LPC_IRQ_LINE)函数调用”。由于工作队列任务不在中断上下文中运行,我相信它们可能会休眠,我认为对于中断处理程序来说是个坏主意。
上述方法的基本原理如下: 1. 如果四个 MAX3107 uart 芯片中的一个接收到一个字符并产生一个中断(例如),中断处理程序需要确定四个 I2C 设备中的哪个实际引起了中断。然而,显然,由于 I2C 读取可以休眠,因此无法从上半部中断处理程序的上下文中读取 I2C 设备,这被认为不适合中断处理程序上半部。2.解决上述问题(即哪个设备导致中断)的方法是让中断禁用并退出上半部分处理程序,之后非中断上下文代码可以查询I2C总线上的四个设备中的每一个找出哪个接收到了字符(并因此产生了中断)。3. 一旦下半部分处理程序确定哪个设备产生了中断,下半部分代码就会禁用该芯片上的中断,这样它就不会重新触发到 LPC3180 的中断线。这样做之后,它会读取串行数据并退出。
这里的主要问题似乎是没有办法从中断处理程序上半部分中查询四个 MAX3107 uart 芯片。如果上半部分在返回之前简单地重新启用中断,这将导致同一芯片再次产生中断,我认为导致上半部分禁用中断,安排下半部分工作队列并禁用中断只是发现自己回到了同一个地方,因为在下半部分代码到达导致中断的芯片之前,另一个中断已经发生,等等,......
任何与此驱动程序打交道的建议将不胜感激。我真的不喜欢允许在驱动程序的上半部分禁用中断但在存在上半部分驱动代码之前不重新启用中断的想法。这似乎并不安全。
谢谢,
吉姆
PS:在我的阅读中,我发现线程中断是处理上述要求的一种手段(至少这是我对http://lwn.net/Articles/302043/等网站文章的解释)。我不确定 Phytec 提供的 2.6.10 内核是否包含线程中断函数。我打算在接下来的几天内对此进行调查。