在中断中禁用中断是一种很好的嵌入式编程实践吗?

时间:2016-01-25 11:58:55

标签: c arm interrupt cortex-m

我想在ARM Cortex-M3处理器(使用NVIC)中实现某些功能。我对嵌入式系统知之甚少,但我知道,ISR例程应该尽可能简单。

现在我遇到以下问题:我有一个中断例程,当收到CAN消息时会调用它。在一种情况下,我必须使用CAN消息计算一些耗时的任务,该任务不能被另一个CAN消息中断,但在此操作期间可以提供其他中断。我的想法如下:

  1. 收到CAN消息,启动ISR,执行一些简单的工作(例如设置标志)
  2. 在CAN ISR例程中禁用CAN中断。还要将CAN消息保存到全局变量中,以便可以在主循环中访问它。
  3. 在主循环中,执行耗时的任务。
  4. 完成此任务后,再次启用CAN中断处理。
  5. 这是一个好的(或不是完全坏的)想法,还是我应该以另一种方式做到这一点?

2 个答案:

答案 0 :(得分:2)

禁用所有(CAN)中断通常不是一个好主意。在您完成第一次服务之前,似乎您想要保护自己的信息是第二次到达的相同信息。

在这种情况下,您应该利用ISR本身不可中断的优势。您可以使用bool变量创建一个简单的信号量,并且由于设置它的中断是不可中断的,因此您甚至不必担心对该布尔值的原子访问。 can处理程序的类似C的伪代码:

typedef struct
{
  bool busy;
  can_msg_t msg;
} special_msg_t;

// must be volatile, to prevent optimizer-related bugs:
volatile static special_msg_t special = { false, {0} };

interrupt void can_isr (void)
{
  // non-interruptable ISR, no other interrupt can fire

  if(id==SPECIAL && !special.busy)
  {
    special.busy = true;
    // right here you can open up for more interrupts if you want
    memcpy(&special.msg, &new_msg, size);
  }
}

result_t do_things_with_special (void) // called from main loop
{
  if(!special.busy) 
    return error; // no new message received, no can do

  // do things with the message

  special.busy = false; // flag that processing is done
  return ok;
}

答案 1 :(得分:0)

  

ISR例程应该尽可能简单。

完全。

有一个名为下半部分的Linux内核概念。即尽可能简化ISR。其余的中断处理操作将推迟到以后的时间。

有很多方法可以实现下半部分,比如task-let,work-queues等等。

建议阅读以下链接
http://www.makelinux.net/ldd3/chp-10-sect-4
http://www.ibm.com/developerworks/library/l-tasklets/

中断禁用较长时间可能导致中断丢失(显然有些数据丢失)。设置中断标志后,创建延迟工作并退出中断上下文。