gpt4 book ai didi

linux - 需要帮助处理共享 ARM9 GPIO 中断(linux)上的多个共享 I2C MAX3107 芯片

转载 作者:太空狗 更新时间:2023-10-29 11:15:28 25 4
gpt4 key购买 nike

我们的小组正在使用嵌入式处理器(Phytec LPC3180、ARM9)。我们设计了一个电路板,在 LPC3180 的一个 I2C 总线上包含四个 MAX3107 uart 芯片。以防万一,我们正在运行内核 2.6.10,这是该处理器可用的最新版本(对该产品的支持不是很好;我们不得不开发或修复 Phytec 提供的许多驱动程序,以及 Phytec似乎对升级这个产品的 linux 代码(尤其是内核版本)没有兴趣。这太糟糕了,因为 LPC3180 是一个不错的设备,尤其是在不需要以太网的低功耗嵌入式产品的背景下,实际上不需要不想要以太网(由于以太网 Controller 芯片的相关功耗)。现在安装的处理程序(由其他人开发)基于上半部分处理程序和下半部分工作队列方法。

当 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 内核是否包含线程中断函数。我打算在接下来的几天里研究这个。

最佳答案

如果您的代码编写正确,那么在处理先前的中断之前设备是否发出中断应该无关紧要,并且您不想在上半部分进行阻塞操作是正确的,但是阻塞操作在一个下半部分,事实上这也是它们存在的部分原因!

在这种情况下,我会建议一种方法,其中上半部分只安排下半部分,然后下半部分在所有 4 个设备上循环并处理任何挂起的请求。可能是多个设备需要处理,也可能没有。

更新:
确实,您可能会通过负载测试使系统过载,并且可能需要优化软件以处理重负载。此外,我没有自己的 3180 和四个 3107(或类似的)来测试这一点,所以我是从理论上讲,但我不清楚为什么你需要禁用中断。

一般来说,当硬件设备断言中断时,它不会断言另一个中断,直到当前中断被清除。所以你有 4 个设备共享一条 int 线:

  • 您的上半部分触发并向工作队列添加一些内容(即触发下半部分)
  • 您的下半部分扫描该 int 行上的所有设备(即所有四个 3107)
  • 如果其中之一导致中断,您将读取完全处理数据所需的所有数据(可能将其放入队列以供更高级别的处理?)
  • 您“清除”当前设备上的中断。

  • 当您清除中断时,设备将被允许触发另一个中断,但之前不能。

    有关此特定设备的更多详细信息:

    似乎这个设备 (MAX3107) 有一个 128 个字的缓冲区,默认情况下你会在每个字后被中断。但似乎您应该能够通过设置 FIFO 级别寄存器来更好地利用缓冲区。然后,只有在接收到该字数后才会被中断(或者如果您将 tx FIFO 填满超过阈值,在这种情况下您应该减慢传输速度(即在软件中缓冲更多))。

    似乎这个想法基本上是定期从设备中提取数据(可能每 100 毫秒或 10 毫秒或任何似乎对您有用的东西),然后只让中断作为您已经超过阈值的警告,这可能会安排周期函数立即执行,或增加调用的速率。

    关于linux - 需要帮助处理共享 ARM9 GPIO 中断(linux)上的多个共享 I2C MAX3107 芯片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13554144/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com