我如何有效地为每个(相同的)外设端口使用相同的中断处理程序?

How do I efficiently use the same interrupt handler for every (identical) peripheral port?

(希望)我的问题的简化版本:

假设我正在使用我的 cortex M-4 mcu 的每个 GPIO 端口来做完全相同的事情,比如在引脚电平变化时读取端口。我已经简化了我的代码,因此它与端口无关,但是我在重新使用相同的中断处理函数的一个很好的解决方案方面遇到了问题。

  1. 有没有办法让我可以使用相同的中断处理函数同时 有找到哪个端口触发中断的方法吗?理想情况下,一些 O(1)/ 不会根据电路板的端口数量进行扩展。
  2. 我是否应该为每个端口设置不同的处理程序来调用接收“端口”参数的相同函数? (到目前为止我能想到的最好的)

很喜欢:

void worker (uint32_t gpio_id) {
    *work goes here*
}

void GPIOA_IRQ_Handler(void) { worker(GPIOA_id); }
void GPIOB_IRQ_Handler(void) { worker(GPIOB_id); }
void GPIOC_IRQ_Handler(void) { worker(GPIOC_id); }
...

我的实际问题:

我正在学习和摆弄 FreeRTOS,并为 debug/stdio UART 创建简单的驱动程序,我的开发人员有一些按钮。板等。到目前为止,我一直在为特定的 peripheral/port.

制作驱动程序

现在我想在不知道要使用哪个接口的情况下制作 I2C 驱动程序(我的 mcu 中有 10 个 I2C 端口),并可能允许驱动程序代码在多个端口上使用同一时间。不过,我会知道编译时使用的所有端口。

关于如何使驱动程序与端口无关,我有一个很好的主意,除了我正在想办法找到一个很好的方法来使用单个处理程序函数来查找哪个端口触发了中断。 (除了循环遍历每个端口的中断状态寄存器,因为那是 O(n))。

就像我说的那样,我想出的最好办法是不使用单个处理程序,而是在向量 table 上使用不同的处理程序,它们都在其中调用相同的“worker”函数并传递一个“端口” “ 范围。此方法使驱动程序代码混乱,但它是 O(1)(除非您考虑代码复杂性)。

  1. 我这样做是不是全错了,应该“保持简单愚蠢”并根据我实际需要的端口/用例以最简单的方式实现驱动程序? (甚至没有计划使用多个 I2C 总线,尽管实现起来会很有趣)

先谢谢了,希望post不要太含糊或太长(我觉得挺长sry)。

  1. Is there a way I can use the same interrupt handler function while having a method of finding which port triggered the interrupt?

仅当不同的中断以相同的方式清除并且您的应用程序不关心哪个引脚触发了中断。不太可能的用例。

  1. Should I just have different handlers for each port that call the same function that takes in a "port" parameter?

是的,我通常就是这样做的。您应该将参数从 ISR 传递给函数,这些参数对于特定中断是唯一的。重要提示:注意函数应该是inline static!快速的 ISR 比通过重复使用相同的功能来节省一点点闪存要重要得多。因此,在机器代码中,您将拥有 4 个不同的 ISR,其中内联了 worker 函数。 (虽然可能想在调试版本中禁用内联。)

Am I going about this all wrong and should just "keep it simple stupid"

听起来你做得对。正确编写的驱动程序应该能够使用相同的代码处理多个硬件外设实例。也就是说,C 程序员倾向于避免代码重复。 “KISS”通常比避免代码重复更合理。避免重复当然很好,但这不是您的首要任务。

在这种情况下,优先级应该是最重要的:

  1. 尽可能快、精简的中断。
  2. 可读代码。
  3. 使用的闪存大小。
  4. 避免代码重复。