Embedded 基于轮询或中断的方法
什么时候应该使用轮询方法,什么时候应该使用基于中断的方法?Embedded 基于轮询或中断的方法,embedded,operating-system,interrupt,processor,rtos,Embedded,Operating System,Interrupt,Processor,Rtos,什么时候应该使用轮询方法,什么时候应该使用基于中断的方法? 有两种情况都可以使用吗?简单的回答是在轮询速度太慢时使用中断方法。(我所说的太慢,是指如果轮询丢失数据,则必须使用中断方法)应尽可能避免轮询,因为它通常会不必要地占用大量CPU周期(除非(a)您只打算轮询一小段时间,或者(b)您可以在轮询循环中睡上一段合理的时间)。浪费CPU周期不仅从性能角度看是不好的,而且还会导致功耗增加,这对于电池供电的嵌入式应用程序来说可能是一个问题。基本上,如果由于某些硬件或软件原因中断模式不可用,则使用轮询模
有两种情况都可以使用吗?简单的回答是在轮询速度太慢时使用中断方法。(我所说的太慢,是指如果轮询丢失数据,则必须使用中断方法)应尽可能避免轮询,因为它通常会不必要地占用大量CPU周期(除非(a)您只打算轮询一小段时间,或者(b)您可以在轮询循环中睡上一段合理的时间)。浪费CPU周期不仅从性能角度看是不好的,而且还会导致功耗增加,这对于电池供电的嵌入式应用程序来说可能是一个问题。基本上,如果由于某些硬件或软件原因中断模式不可用,则使用轮询模式。因此,从功耗、性能等角度来看,中断模式更可取(同意Paul R)。轮询模式也可用于原型制作、无需外围设备的内核以及某些测试目的 如果感兴趣的事件是:
如果感兴趣的事件是:
其他注意事项包括您是为操作系统编写设备驱动程序,还是只编写没有线程支持的裸机代码。在裸机情况下,CPU通常只是在不忙的情况下循环,因此它也可以轮询某些内容。有时您实际上需要同时使用这两种方式。例如,如果事件是零星的,但以高速突发方式出现;您可能需要首先响应中断,然后再重新启用中断轮询,以查看是否已发生另一个事件,从而避免中断上下文切换的一些开销。我相信Linux网络接口在这种模式下工作。当需要低延迟时,中断是首选。如果你每秒轮询某个条件N次,那么平均而言,你会在实际发生后的1/N的一半时间内发现该条件
当需要绝对确定性定时时,轮询有时是首选的。就其本质而言,中断可能发生在不可预测的时间,并使时序分析变得非常复杂,而对于轮询系统,就截止日期满足情况做出可证明的陈述相对容易。始终使用中断。这样你就不会丢失数据。在事件驱动或线程化应用程序中,即使最慢的信号也应该是中断驱动的
唯一应该使用轮询的时间是在使用调度器时,并且硬件上的缓冲区足够深,以确保不会丢失数据。轮询模式在具有高频事件的系统中非常有用,在这些系统中,与进入和退出中断处理程序相关的开销比简单轮询使用更多的CPU周期。例如,在IP路由器中可以使用轮询来最大化数据包处理可用的CPU带宽。在决定轮询或中断时,您必须完全了解您试图跟踪的事件的性质以及您对它的响应 当什么都没有发生时,中断不需要处理,但当有事情发生时,需要全神贯注。如果事件是外部事件,并且具有嘈杂的边缘或快速脉冲,那么这可能会导致中断的严重问题,在设置中断时必须小心 在本例中,中断程序对已清除的激光束作出响应,并为其被阻止的事件进行设置:
BEAM_INTR_EN = TRUE; /*re-enable the beam interrupts*/
/*Set the beam interrupt for the next clear to blocked event*/
BEAM_INTR_EDGE = CLEAR_TO_BLOCKED;
BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/
该规范有两个弱点:
1) 如果激光束在中断标志清除之前再次被阻挡(beam_INTR_flag=FALSE;)。中断将丢失,代码将与激光束状态不同步
2) 在后台例程中设置中断或设置优先级高于此代码所处优先级的中断时,启用中断时必须小心。如果中断标志在启用之前已经设置(不正确),则一旦启用,中断例程将被错误调用,可能是因为错误的边缘
修复1)的最简单方法是在设置中断后再次检查,如果中断发生,则强制中断。修复2)将中断的启用移至双重检查后:
/*Set the beam interrupt for the next clear to blocked event*/
BEAM_INTR_EDGE = CLEAR_TO_BLOCKED;
BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/
/*Double check beam state to see if it has already gone blocked*/
if (BEAM_STATE == BEAM_BLOCKED)
{
BEAM_INTR_FLAG = TRUE; /*Force the interrupt to re-enter the ISR after exiting*/
}
BEAM_INTR_EN = TRUE; /*re-enable the beam interrupts*/
强制中断使系统使用相同的状态机工作,只需手动强制中断以覆盖盲点
基本上:
Set the edge to detect the next interrupt event
Clear the interrupt flag
if (the event has already occurred)
{
Set the interrupt flag to force the interrupt
}
Enable the interrupt
如果对事件的响应时间必须一致(例如,输入线变高后1ms+/-10us,传输事件信号),则中断通常是最好的
如果对事件的响应时间必须在特定时间内(例如,在输入线变高的1ms内,传输事件信号),则最好使用中断
中断的问题是,您必须开始考虑线程,两段代码可以同时访问相同的数据
中断也有利于允许处理器在等待某些事情发生时进入低功耗模式(睡眠/空闲等)
话虽如此,如果处理器只有一件事要做,轮询可以给事件提供非常紧凑的时间响应,中断硬件通常需要几个周期来响应事件,而紧凑的轮询循环就可以了
如果事件不具有时间关键性和潜在噪音(例如有人按下开关),则轮询允许简单过滤,而不会错过长期转换。常见的mi
void fnInitialiseSystem(void)
{
if (MODE_INPUT == MODE_A) /*First polling of the MODE_INPUT*/
{
PR2 = PR2_MODE_A;
}
else
{
PR2 = PR2_MODE_B;
}
OpenTimer2( TIMER_INT_ON &
T2_PS_1_1 &
T2_POST_1_8 );
if (MODE_INPUT == MODE_A) /*Second polling of the MODE_INPUT*/
{
CurrentMode = MODE_A;
PROBE_INT_EDGE = CLEAR_TO_BLOCKED;
}
else
{
CurrentMode = MODE_B;
PROBE_INT_EDGE = BLOCKED_TO_CLEAR;
}
}
-INTERRUPT- -LOOP-
Speed fast slow
Eficiency good poor
CPU waste low high
multitasking yes no
complexity high low
debugging +/- easy easy
critical in time excellent poor
code bloat low impact high impact