eCos中断模型(1)ISR和DSR
中断处理是实时操作系统一个重要部分。及时地处理中断源是很重要的,但一些必须被视为原子操作(不能被中断)的动作对保证及时性带来了十分严重的影响。因为执行这些动作时,都要disable中断。为了最大限度地减少这种动作,确保最可能少的中断延迟,eCos使用了一种分割式中断处理机制,在这种机制中,中断处理被分为两部分。第一部分是大家都知道的中断服务例程(ISR),第一部分是延迟服务例程(DSR)。明显地,这种分割允许中断被enabled的情形下运行DSRs,因此在处理较低优先级的中断时,允许别的潜在的更高优先级的中断发生和处理。
为了使这种中断模型能够工作起来,ISR应当快速运行。如果中断引起的服务量少,ISR可以单独处理这个中断而不需要DSR。当然,如果中断服务比较复杂,DSR就派上了用场。将会在稍后合适的时间执行这个DSR,在这个时候允许进行线程调度。推迟到这个时候运行DSRs使得kernel可以使用简单的同步方式。
此外,这种受控的调用方式—当允许进行线程调度的时侯--意味着DSR可以和内核打交道,比如向内核发出信号:一个异步操作结束了。
为了可以在中断被enabled的情形下运行DSRs,对应于特定中断源(或硬件)的ISR必须作出安排保证这个中断不会再次发生,直到DSR结束。在有的情况下,硬件完成这个动作:一旦一个中断被递送出去,别的中断将不会发生,除非中断被重新enabled。但是,一般情况下,是ISR来强迫这个行为的发生。ISR将会屏蔽掉这个中断源,防止了再次产生中断。只有当DSR执行结束时,这个DSR将会unmask这个中断,这样如果新的中断再次发生了,允许递送这个中断。
另外,如果每次中断时ISR要做的动作很少,比如传递内存上的一个字节到一个IO设备上,每一次“传递”结束时,它可能只需要与系统的其它部分打交道。在这种情况下,多次执行了ISR后,等到处理完这个缓冲区,这个ISR才真的需要请求执行它的DSR。
如果中断源是爆发性的,在执行一个被请求的DSR之前,可能产生了多个中断并且多次调用了这个ISR,这是正常的;内核记录下被posted的DSR的个数。在这种情况下,这个DSR将会最终被调用,其中一个参数告诉它有多少个ISR请求执行这个DSR。编码时必须小心处理这种情形,因为一次对DSR的调用需要完成好几次DSR的任务。
正如上面所说,这个DSR将会在稍后的时间得到执行。与系统的状态有关,它可能会在更迟的时间得到执行。执行一定的内核操作时,在某些时期内线程调度被禁止,这使得不能执行DSR。eCos内核有意识地尽可能地限制了这些时期,尽管它们依然存在。另外,同时用户线程有能力挂起调度,因此影响了可能的DSR执行延迟。如果不能足够快地执行一个DSR,这个中断源可能overrun。这应当视为系统失败。
eCos中断模型(2)用户栈和中断栈
系统设计者面临的一个问题是为每个线程应当分配多大的堆栈空间。eCos并没有指定线程堆栈的大小,它留给用户在创建线程的时候决定。堆栈的大小不但与线程需求有关,也与一些固定的系统开销有关。这个系统开销是能够存放全部线程状态的足够的堆栈空间(它的实际数量与CPU结构有关)。抽象硬件层的CYGNUM_HAL_STACK_SIZE_MINIMUM给出了所需的最小堆栈空间。
嵌套中断是这种机制潜在的一个问题。既然处理一个中断时它的DSR部分重新enable了中断,这样在处理DSR时,有可能来了一个新的中断(hopefully来自别的中断源)。当处理这个新的中断时,被中断的状态信息将会存放在堆栈上。被中断的状态信息的数量依赖于具体的CPU结构,有时候数量很多。这意味着堆栈空间应当足够大能够存放“N”个中断框架(被中断的状态信息)。对于有很多线程的实时系统来说,这是一个不能容忍的局面。为了解决这个问题,在处理中断时,eCos应用了一个独立的中断栈。这个栈需要足够大能够存放“N”个中断框架(被中断的状态信息),而每个线程堆栈只需单个中断状态的开销。这是因为线程状态被保存在自己的堆栈上,包括导致这个线程被调度的中断的状态信息。这是一个好得多的结局,既然只有这个中断栈需要足够大以处理潜在的中断服务需求。
eCos允许中断栈完全地可配置。用户可以选择不使用这个独立的中断栈。这需要所有的线程堆栈足够大,但是在中断处理时,这省去了切换栈的开销。如果内存很紧张,每次处理中断时以几个机器周期(cycle)为代价,选择一个独立的中断栈应当是warranted。
eCos中断模型(3)overrun问题
在mn10300模拟器上,观察到如下与中断有关的问题:当DSR重新enabled了中断,马上就来了下一个中断。既然一个中断被处理完到下一个中断出现之前,不可能有任何(有意义的)处理,这种现象应当被视为一种中断overrun,系统完全饱和了。产生了问题是因为栈溢出。这是用户栈溢出,因为DSR是在用户栈上执行的。对这个问题的分析导致重新修改了中断处理方式,尤其是进行中断处理时(ISR和DSR),对独立中断栈的使用。栈溢出依然会发生,但这回它只限制在中断栈上。如果系统设计者事先知道overrun是有限的,例如以串口设备为例,它可能是一些FIFO的depth,他可以为此做出相应调整给出适当大的中断栈。任何情况下,overrun必须避免,但使用中断栈使得这种failure可以很简单地检测出来。
文章评论(0条评论)
登录后参与讨论