【问题标题】:Why does not WiringPiISR block the main routine when it is fired?为什么 WiringPiISR 在被触发时不阻塞主程序?
【发布时间】:2019-08-01 19:22:51
【问题描述】:

我正在用 C 语言开发一个在树莓板上运行的程序。在程序中,我想使用 WiringPiISR 来处理引脚触发的中断。然而,我发现,wiringPiISR 并没有阻塞主程序,而是创建了一个并发线程。我错过了什么吗?

最小代码示例:

#include <WiringPi.h>
#include <unistd.h>
int Check=0;
void Isr()
{
    while (1)
    {
       sleep(1);
       Check++;
    }
}

int main()
{
     wiringPiSetup () ;
     pinMode(7, INPUT) ;
     wiringPiISR (7, INT_EDGE_BOTH ,&Isr);
     while (1)
      {
         sleep(2);
         printf("check : %d", Check );
      }
   return 0;
}

我希望这个最小程序在中断触发后永远不会恢复,但在我的情况下,它会不断增加变量检查并将其打印在屏幕上(两个线程同时工作)。

【问题讨论】:

  • 不要在 ISR 中调用 sleep()!

标签: c raspberry-pi embedded wiringpi


【解决方案1】:

我发现的documentation 相当具体(强调我的):

int 接线PiISR (int pin, int edgeType, void (*function)(void)) ;

此函数以高优先级运行(如果程序使用 sudo 或作为 root 运行)并与主程序同时执行。它拥有对所有全局变量、打开文件句柄等的完全访问权限。

sources 没有任何想象空间。它只是创建了一个新线程:

pthread_create (&threadId, NULL, interruptHandler, &pin) ;

等待中断并执行你的处理程序:

static void *interruptHandler (void *arg)
{
  int pin = *(int *)arg ;

  (void)piHiPri (55) ;

  for (;;)
  {
    if (waitForInterrupt (pin, -1) > 0)
      isrFunctions [pin] () ;
  }

  return NULL ;
}

所以你的处理程序作为一个单独的线程运行并且你的行为是预期的。

【讨论】:

    【解决方案2】:

    ISR 代表中断服务程序,也就是中断处理程序。

    您的代码设置了一个中断处理程序。如果触发中断,则常规代码(在您的情况下为main())被中断并执行中断处理程序。这不是第二个线程,但结果是相似的。

    中断处理程序应该只做最少的工作,并迅速将控制权返回给被中断的程序。不允许在中断处理程序中使用sleep(),这会导致未定义的行为。

    【讨论】:

    • 我会说 IRQ 中的 while(1){} 更糟糕。
    【解决方案3】:

    假设你故意进行了无限循环和sleep()的调用:

    sleep() 可能允许在线程之间切换。

    【讨论】:

    • 这只是一个强调这一点的最小例子,但我想 sleep() 的使用很好,因为它揭示了其他部分信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2021-10-19
    • 2022-01-02
    • 1970-01-01
    • 2021-11-12
    • 2020-01-02
    相关资源
    最近更新 更多