在中断中禁用中断是一种很好的嵌入式编程实践吗?
Is it a good embedded programming practice to disable an interrupt in an interrupt?
我想在 ARM Cortex-M3 处理器(带有 NVIC)中实现一些东西。我对嵌入式系统的了解有限,但我知道,ISR 例程应该尽可能简单。
现在我遇到了以下问题:我有一个中断例程,它在收到 CAN 消息时调用。在一种情况下,我必须使用 CAN 消息计算一些耗时的任务,该任务不能被另一个 CAN 消息中断,但在此操作期间可以处理其他中断。我的想法如下:
- 收到CAN消息,ISR开始,做一些简单的工作(例如设置标志)
- 在 CAN ISR 例程中禁用 CAN 中断。还将 CAN 消息保存到全局变量中,以便在主循环中可以访问它。
- 在主循环中,执行耗时任务。
- 完成此任务后,再次启用 CAN 中断处理。
这是一个好(或不完全坏)的主意还是我应该换一种方式来做?
an ISR routine should be as simple as possible.
完全正确。
有一个 Linux 内核概念称为 下半部分 。即尽可能保持 ISR 简单。其余的中断处理操作推迟到以后。
有很多方法可以实现下半部分,例如 task-let、work-queues 等
建议阅读以下链接
http://www.makelinux.net/ldd3/chp-10-sect-4
http://www.ibm.com/developerworks/library/l-tasklets/
长时间禁用中断可能会导致中断丢失(显然会丢失一些数据)。设置中断标志后,创建一个延迟工作并从中断上下文中出来。
禁用所有 (CAN) 中断通常不是一个好主意。似乎您想要保护自己免受第二次到达的相同消息的影响,在您完成第一次服务之前。
在那种情况下,您应该利用 ISR 本身 non-interruptable。您可以使用 bool 变量创建一个简单的信号量,并且由于设置它的中断是 non-interruptable,您甚至不必担心对该布尔值的原子访问。 C-like pseudo-code 罐头处理程序:
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;
}
我想在 ARM Cortex-M3 处理器(带有 NVIC)中实现一些东西。我对嵌入式系统的了解有限,但我知道,ISR 例程应该尽可能简单。
现在我遇到了以下问题:我有一个中断例程,它在收到 CAN 消息时调用。在一种情况下,我必须使用 CAN 消息计算一些耗时的任务,该任务不能被另一个 CAN 消息中断,但在此操作期间可以处理其他中断。我的想法如下:
- 收到CAN消息,ISR开始,做一些简单的工作(例如设置标志)
- 在 CAN ISR 例程中禁用 CAN 中断。还将 CAN 消息保存到全局变量中,以便在主循环中可以访问它。
- 在主循环中,执行耗时任务。
- 完成此任务后,再次启用 CAN 中断处理。
这是一个好(或不完全坏)的主意还是我应该换一种方式来做?
an ISR routine should be as simple as possible.
完全正确。
有一个 Linux 内核概念称为 下半部分 。即尽可能保持 ISR 简单。其余的中断处理操作推迟到以后。
有很多方法可以实现下半部分,例如 task-let、work-queues 等
建议阅读以下链接
http://www.makelinux.net/ldd3/chp-10-sect-4
http://www.ibm.com/developerworks/library/l-tasklets/
长时间禁用中断可能会导致中断丢失(显然会丢失一些数据)。设置中断标志后,创建一个延迟工作并从中断上下文中出来。
禁用所有 (CAN) 中断通常不是一个好主意。似乎您想要保护自己免受第二次到达的相同消息的影响,在您完成第一次服务之前。
在那种情况下,您应该利用 ISR 本身 non-interruptable。您可以使用 bool 变量创建一个简单的信号量,并且由于设置它的中断是 non-interruptable,您甚至不必担心对该布尔值的原子访问。 C-like pseudo-code 罐头处理程序:
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;
}