linux任务响应模型&linux实时化&RTAI 3.2分析&Adeos分析(9)
- UID
- 1029342
- 性别
- 男
|
linux任务响应模型&linux实时化&RTAI 3.2分析&Adeos分析(9)
struct adcpudata {
unsigned long status;
unsigned long irq_pending_hi;
unsigned long irq_pending_lo[IPIPE_IRQ_IWORDS];
unsigned irq_hits[IPIPE_NR_IRQS];
adevinfo_t event_info;
} cpudata[ADEOS_NR_CPUS];
struct {
int (*acknowledge)(unsigned irq);
void (*handler)(unsigned irq);
unsigned long control;
} irqs[IPIPE_NR_IRQS];
在结构变量cpudata[ADEOS_NR_CPUS]中,每个元素包含在某个CPU上的中断信息;其中,字段status表示当前域的状态,它的取值范围如下:
IPIPE_STALL_FLAG:表示域禁止中断,当硬件中断沿着中断管道传递到这个域的时候,Adoes将不会执行域的中断处理程序,也不会将中断沿着中断管道继续向下传播;
IPIPE_SYNC_FLAG:表示Adoes正在为这个域执行中断处理程序(被称为IRQ同步),保护同步代码不被同步执行;
IPIPE_XPEND_FLAG:表示域收到了异常(或者说系统事件,如进入、退出系统调用等)通知消息,而且还没有对其进行处理;
IPIPE_SLEEP_FLAG:表示域已经将自己挂起,也就是说,现在是其它的域在运行;当一个域刚被注册的时候就是处于被挂起的状态;
在cpudata中,字段irq_pending_hi,irq_pending_lo[IPIPE_IRQ_IWORDS]和irq_hits[IPIPE_NR_IRQS]用于保存域接收到的中断信息。IPIPE_NR_IRQS为系统中断个数(包括用于域间通信的软件中断)irq_hits[]的每个元素对应于某一个中断发生的次数;irq_pending_lo[]是一个映射表,每一位对应于一个中断,当某个中断发生时,就将这个映射表中的相应位置1表示相应的中断发生了;irq_pending_hi也是一个映射表,其中的每一位对应于irq_pending_lo数组中的每一个元素;例如,当接收到32号中断后,irqs_hits[32]的值加1,irq_pending_lo[1]的位0被置1(相当于映射表的位32),irq_pending_hi的位1被置1(表示数组irq_pending_lo的第2个元素有位被置1)。
在cpudata中的字段event_info则是用来保存接收到的系统事件通知的信息,它的结构如下:
typedef struct adevinfo {
unsigned domid;
unsigned event;
void *evdata;
volatile int propagate; /* Private */
} adevinfo_t;
其中的字段domid表示系统事件是在哪个域发生的;event表示事件类型;evdata则是传递给事件处理函数的参数;propagate指示执行完事件处理函数后是否将这个事件通知传递给中断管道中后面的域。
irqs[IPIPE_NR_IRQS]保存着中断的中断处理函数、中断应答函数和中断的处理模式;中断处理模式字段control是一个位掩码,目前中断处理共有四种模式:
1.域不处理中断而直接将中断传递给低优先级的域(control = IPIPE_PASS_MASK);
2.域对中断进行处理,但不再将中断传递给低优先级的域(control = IPIPE_HANDLE_MASK);
3.域对中断进行处理并将之传递给低优先级的域(control = IPIPE_HANDLE_MASK | IPIPE_PASS_MASK);
4.域既不对中断进行处理,也不将中断传递给中断管道中优先级的域;
从上面的分析可以看出,Adeos的中断入口函数仅仅只是将中断信息纪录在每个域的中断相关的日志内,每个域的中断处理函数的执行实际上是由中断管道来调度的(根据域的优先级);中断管道对域的中断函数的执行是通过对函数__adeos_walk_pipeline的调用实现的(在函数__adeos_handle_irq的最后被调用)。
在分析__adeos_walk_pipeline之前,先考虑一下一个域在Adeos系统中所处的状态,将会有助于对后面分析的理解。Adeos系统中的每个域,都处于以下3种状态之一:
第一种是域处于运行状态,在这种情况下,中断管道中比当前运行状态的域优先级高的域都处于挂起状态,也就是说,高优先级的域都没有任务、中断或系统事件需要处理,他们都通过调用函数adeos_suspend_domain将本身挂起;而中断管道中比当前运行域优先级的的域则或者处于挂起状态或者处于被中断状态;
第二种是域处于挂起状态,这说明这个域是通过调用adeos_suspend_domain将本身挂起的,在挂起的时候域没有任务或中断或事件需要处理。但经过一段时间后,处于挂起状态的域,可能也有需要处理的中断或事件通知,只不过现在有更高优先级的域在运行而已。
第三种是域处于被中断的状态,当一个域正处于运行态时,如果这个时候产生中断,或是触发了一个系统事件,Adeos就开始进行中断的处理,如有更高优先级的域需要处理这个中断的时候,Adoes就会调度高优先级的域先运行,那么,这个被中断的域就处于被中断状态了。
__adeos_walk_pipeline定义在文件arch/arm/kernel/adeos.c中,它完成的主要功能如下:
1.沿着中断管道从头开始对域进行处理;
2.如果域禁止中断,则不再对之后的域进行中断的处理;
3.如果某个域有需要处理的中断,则调用域切换函数__adeos_switch_to从当前域切换到那个域,那个域在恢复运行的时候会通过调用函数__adeos_sync_stage执行中断处理函数;
4.如果遍历到了当前域,则直接调用__adeos_sync_stage执行当前域的中断处理函数,然后就可以退出函数__adeos_walk_pipeline,紧接着退出Adeos的中断处理函数__adeos_handle_irq,返回被中断的域继续运行。
__adeos_sync_stage的主要功能是执行域的中断处理函数,并更新域结构的中断相关日志。
__adeos_switch_to的功能就是通过调用汇编函数__adeos_switch_domain进行域切换,然后再调用域切换的钩子函数dswitch。 |
|
|
|
|
|