【问题标题】:How does software recognize an interrupt has occured?软件如何识别中断发生?
【发布时间】:2012-06-12 12:11:23
【问题描述】:

据我们所知,我们编写 Embedded C 编程,用于 task management, memory management, ISR, File system 等等。
我想知道是否有一些task or process is runninginterrupt occurred,然后是how SW or process or system comes to know that, the interrupt has occurred?pauses 当前的task executionstarts serving ISR

假设我会写下面的代码:

// Dummy Code
void main()
{
    for(;;)
        printf("\n forever");
}

// Dummy code for ISR for understanding
void ISR()
{
    printf("\n Interrupt occurred"); 
}

在上面的代码中,如果一个external interrupt(ISR) occurs,那么main()如何知道中断发生了?所以它会首先开始服务于 ISR?

【问题讨论】:

  • Main() 应该返回 int。从信号处理程序或中断处理程序调用 printf() 是不安全的。
  • 阅读您的系统文档,这些文档很可能不在 stackoverflow.com 上
  • @wildplasser No main 不应该返回 int,这不是 PC。该帖子被明确标记为嵌入式系统。阅读this
  • @Lundin:我刚刚写了一个虚拟代码。这不是真的

标签: c embedded scheduled-tasks interrupt


【解决方案1】:

主要不知道。您必须在设置代码(可能在主代码中)中执行一些与系统相关的函数,该函数将中断处理程序注册到硬件中断例程/向量等。

中断代码是否可以直接执行 C 函数变化很大;中断过程的运行时约定并不总是遵循应用程序代码的运行时约定。通常,在从中断例程获取信号到 C 代码时会涉及一些间接。

【讨论】:

    【解决方案2】:

    您的问题:我理解您的回答。但我想知道何时发生中断,当前任务执行如何停止/暂停以及 ISR 开始执行?

    Rashmi 回答您的问题,请阅读下文,

    当微控制器检测到中断时,它会在执行当前指令后停止程序的执行。然后它将PC(程序计数器)压入堆栈并用该中断的向量位置加载PC,因此程序流被引导到中断服务程序。在 ISR 完成后,微控制器再次从堆栈中弹出存储的程序计数器并将其加载到 PC 上,因此,程序执行再次从下一个停止位置恢复。 这是否回复了您的查询?

    【讨论】:

    • 我认为上面的解释确实消除了我的疑问。谢谢 Kinjal Patel。
    • @kinjalpatel 你应该编辑你的答案,而不是发布多个答案。
    【解决方案3】:

    这取决于你的目标。

    例如,ATMEL mega 系列使用预处理器指令向中断向量注册 ISR。当发生中断时,相应的中断标志会在相关状态寄存器中产生。如果产生全局中断标志,则程序计数器在调用 ISR 之前存储在堆栈中。这一切都发生在硬件中,主要功能对此一无所知。

    为了让 main 知道是否发生了中断,您需要在中断例程和 main 函数之间实现共享数据资源,并且 RTOS 编程中的所有规则都适用于此。这意味着,由于 ISR 可以随时执行,因此在不先禁用中断的情况下从 main 读取共享资源是不安全的。

    在 ATMEL 目标上,这可能如下所示:

    volatile int shared;
    
    int main() {
      char status_register;
      int buffer;
      while(1) {
        status_register = SREG;
        CLI();
        buffer = shared;
        SREG = status_register;
        // perform some action on the shared resource here.
      }
      return 0;
    }
    
    void ISR(void) {
      // update shared resource here.
    }
    

    请注意,此处未将 ISR 添加到向量表中。检查您的编译器文档以获取有关如何执行此操作的说明。

    另外,要记住的重要一点是 ISR 应该非常短且执行速度非常快。

    【讨论】:

    • 所有共享资源必须是易失性的,以防止危险的编译器优化。
    【解决方案4】:

    在大多数嵌入式系统上,硬件都有一些特定的内存地址,当硬件条件指示需要中断时,指令指针将移动到该地址。

    当指令指针位于这个特定位置时,它将开始执行那里的代码。

    在很多系统上,程序员只会在这个位置放置一个 ISR 的地址,这样当中断发生并且指令指针移动到特定位置时,它就会跳转到 ISR

    尝试在 Google 上搜索“中断向量”

    【讨论】:

      【解决方案5】:

      中断处理对于正在运行的程序是透明的。处理器会根据事件自动跳转到先前配置的地址,该地址是相应的 ISR 功能。从中断返回时,有一条特殊指令恢复被中断的程序。

      实际上,大多数时候您都不希望程序被中断知道它已被中断。如果你需要知道这些信息,程序应该调用一个驱动函数来代替。

      【讨论】:

        【解决方案6】:

        中断是硬件而不是软件。当中断信号到达处理器时,处理器(通常)完成当前指令。以某种方式 shape 或 form 保留了状态(因此它可以回到原来的位置),并且以某种方式 shape 或 form 开始执行中断服务程序。 isr 通常不是 C 代码,至少入口点通常是特殊的,因为处理器不符合编译器的调用约定。 ISR 可能会调用 C 代码,但您最终会犯下您所犯的错误,调用 printf 之类的调用不应该在 ISR 中。在 C 中很难避免尝试在 isr 中编写通用 C 代码,而不是典型的进出类型的东西。

        理想情况下,您的应用层代码不应该知道中断发生,不应该有(基于硬件的)残差影响您的程序。您可以选择为应用程序留下一些东西,例如计数器或其他需要标记为易失性的共享数据,以便应用程序和 isr 可以共享它。让 isr 简单地标记发生中断并且应用程序轮询该标记/计数器/变量并且处理主要发生在应用程序而不是 isr 中,这种情况并不少见。这样,应用程序可以进行任何它想要的系统调用。只要满足整体带宽或性能,这可以并且确实可以作为一种解决方案。

        【讨论】:

        • github.com/dwelch67/raspberrypi 前几天我刚刚放了一个例子,blinker05。有一个保存寄存器然后调用 C 函数的 asm,C 函数增加一个共享/全局计数器并更改 LED 的状态。没有,但可以很容易地让应用程序监控共享变量 (icount),并且可以很容易地让应用程序根据共享计数器而不是 isr 来更改 LED 的状态。
        【解决方案7】:

        软件无法识别具体的中断,它是微处理器 (INTC) 或微控制器 JOB。

        中断例程调用就像对 Main() 的正常函数调用一样,唯一的区别是 main 不知道该例程何时会被调用。

        每个中断都有特定的优先级和向量地址。一旦接收到中断(软件或硬件),根据中断优先级、掩码值和程序流被转移到与该中断相关的特定向量位置。

        希望对您有所帮助。

        【讨论】:

        • 我明白你的回答。但我想知道何时发生中断,当前任务执行如何停止/暂停以及 ISR 开始执行?
        猜你喜欢
        • 1970-01-01
        • 2017-03-22
        • 1970-01-01
        • 2011-01-17
        • 2011-02-22
        • 2011-01-23
        • 1970-01-01
        • 1970-01-01
        • 2019-06-22
        相关资源
        最近更新 更多