我想在ARM Cortex-M3处理器(使用NVIC)中实现某些功能。我对嵌入式系统知之甚少,但我知道,ISR例程应该尽可能简单。
现在我遇到以下问题:我有一个中断例程,当收到CAN消息时会调用它。在一种情况下,我必须使用CAN消息计算一些耗时的任务,该任务不能被另一个CAN消息中断,但在此操作期间可以提供其他中断。我的想法如下:
这是一个好的(或不是完全坏的)想法,还是我应该以另一种方式做到这一点?
答案 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/
中断禁用较长时间可能导致中断丢失(显然有些数据丢失)。设置中断标志后,创建延迟工作并退出中断上下文。