读代码细学内核中断机制-中断的响应
2012-08-11 18:03
141 查看
在内核中断初始化完成并且设备注册了响应的中断后,内核就可以响应相应的中断了。
首先要确定如果一个外设发出中断请求,它到底做了什么,设备是不能直接发出中断的,而是借助中断控制器,设备向中断控制器请求中断,这就是IRQ的来历。
对于龙芯1B处理器来说,中断控制器有四条输出线接在了处理器上,也就是四条中断线,INT0~INT3,每条中断线对应32个中断源,而中断控制器寄存器的位域也就跟这32个中断源一一对应。
每个设备控制器都有一条IRQ输出线和中断控制器寄存器的相应位相连,这样当相应设备控制器发出中断时,中断控制器寄存器相应位就置1,中断控制器就通过相应的中断输出线向内核发出中断,CP0协处理器寄存器cause寄存器的IP0~IP7相应位就置1。
内核响应中断就是跳转到事先设定好的异常向量入口,前面说过,对于龙芯1B内核是在0x80000180,首先读取cause寄存器中的例外码,确定是哪一种通用异常,然后跳转到exception_handler数组相应的处理函数中。对于中断就是数组的0号成员,处理函数是handler_int,执行handler_int,这个函数中是检查status寄存器的全局中断标志位IE是否置1,然后跳转到plat_irq_dispatch,这个函数就是中断的下发函数了,读取出status寄存器的IM0~IM7,读出cause寄存器的IP0~IP7,相与就得到具体是产生哪一种中断并且该中断也是被使能了。
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
// unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
unsigned int cause_reg = read_c0_cause() ;
unsigned int status_reg = read_c0_status() ;
unsigned volatile int cause = cause_reg & ST0_IM;
unsigned volatile int status = status_reg & ST0_IM;
unsigned int pending = cause & status;
uint64_t volatile counter1, counter2;
if (pending & CAUSEF_IP7) {
ll_timer_interrupt(MIPS_CPU_IRQ_BASE+7);
}
else if (pending & CAUSEF_IP2) {
sb2f_board_hw_irqdispatch(0);
}
else if (pending & CAUSEF_IP3) {
sb2f_board_hw_irqdispatch(1);
}
else if (pending & CAUSEF_IP4) {
sb2f_board_hw_irqdispatch(2);
}
else if (pending & CAUSEF_IP5) {
sb2f_board_hw_irqdispatch(3);
}
else if (pending & CAUSEF_IP6) {
sb2f_board_hw_irqdispatch(4);
} else {
spurious_interrupt();
}
}
从这个函数中可以看出INT0~INT3对应的是IP2~IP5,这个函数调用sb2f_board_hw_irqdispatch,读出相应中断线的ISR中断状态寄存器,计算出是哪一位被置1,然后计算出中断号,再调用do_IRQ函数。
void sb2f_board_hw_irqdispatch(int n)
{
int irq;
int intstatus = 0;
int status;
/* Receive interrupt signal, compute the irq */
status = read_c0_cause();
intstatus = (sb2f_board_hw0_icregs+n)->int_isr;
irq=ffs(intstatus);
// prom_printf("irq=%d,n=%d,realirq=%d\n",irq,n,n*32+irq-1);
if(!irq){
printk("Unknow interrupt status %x intstatus %x \n" , status, intstatus);
return;
}
else do_IRQ(n*32+irq-1);
}
do_IRQ函数
首先要确定如果一个外设发出中断请求,它到底做了什么,设备是不能直接发出中断的,而是借助中断控制器,设备向中断控制器请求中断,这就是IRQ的来历。
对于龙芯1B处理器来说,中断控制器有四条输出线接在了处理器上,也就是四条中断线,INT0~INT3,每条中断线对应32个中断源,而中断控制器寄存器的位域也就跟这32个中断源一一对应。
每个设备控制器都有一条IRQ输出线和中断控制器寄存器的相应位相连,这样当相应设备控制器发出中断时,中断控制器寄存器相应位就置1,中断控制器就通过相应的中断输出线向内核发出中断,CP0协处理器寄存器cause寄存器的IP0~IP7相应位就置1。
内核响应中断就是跳转到事先设定好的异常向量入口,前面说过,对于龙芯1B内核是在0x80000180,首先读取cause寄存器中的例外码,确定是哪一种通用异常,然后跳转到exception_handler数组相应的处理函数中。对于中断就是数组的0号成员,处理函数是handler_int,执行handler_int,这个函数中是检查status寄存器的全局中断标志位IE是否置1,然后跳转到plat_irq_dispatch,这个函数就是中断的下发函数了,读取出status寄存器的IM0~IM7,读出cause寄存器的IP0~IP7,相与就得到具体是产生哪一种中断并且该中断也是被使能了。
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
// unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
unsigned int cause_reg = read_c0_cause() ;
unsigned int status_reg = read_c0_status() ;
unsigned volatile int cause = cause_reg & ST0_IM;
unsigned volatile int status = status_reg & ST0_IM;
unsigned int pending = cause & status;
uint64_t volatile counter1, counter2;
if (pending & CAUSEF_IP7) {
ll_timer_interrupt(MIPS_CPU_IRQ_BASE+7);
}
else if (pending & CAUSEF_IP2) {
sb2f_board_hw_irqdispatch(0);
}
else if (pending & CAUSEF_IP3) {
sb2f_board_hw_irqdispatch(1);
}
else if (pending & CAUSEF_IP4) {
sb2f_board_hw_irqdispatch(2);
}
else if (pending & CAUSEF_IP5) {
sb2f_board_hw_irqdispatch(3);
}
else if (pending & CAUSEF_IP6) {
sb2f_board_hw_irqdispatch(4);
} else {
spurious_interrupt();
}
}
从这个函数中可以看出INT0~INT3对应的是IP2~IP5,这个函数调用sb2f_board_hw_irqdispatch,读出相应中断线的ISR中断状态寄存器,计算出是哪一位被置1,然后计算出中断号,再调用do_IRQ函数。
void sb2f_board_hw_irqdispatch(int n)
{
int irq;
int intstatus = 0;
int status;
/* Receive interrupt signal, compute the irq */
status = read_c0_cause();
intstatus = (sb2f_board_hw0_icregs+n)->int_isr;
irq=ffs(intstatus);
// prom_printf("irq=%d,n=%d,realirq=%d\n",irq,n,n*32+irq-1);
if(!irq){
printk("Unknow interrupt status %x intstatus %x \n" , status, intstatus);
return;
}
else do_IRQ(n*32+irq-1);
}
do_IRQ函数
相关文章推荐
- 读代码细学内核中断机制-中断的响应
- 读代码细学内核中断机制-中断的初始化
- 读代码细学内核中断机制-中断的注册
- QNX驱动开发—中断处理,中断响应机制
- 内核中断机制
- IA32上Linux内核中断机制分析
- Linux内核的时钟中断机制(6)
- 内核总结之中断机制
- 64位多核 MIPS 异常和中断内核代码分析 (4)
- Linux 内核锁机制之进程抢占&中断
- 实例分析Linux0.11内核中断机制
- 线程中断机制及响应
- Linux内核的时钟中断机制(5)
- 把握linux内核设计思想(三):下半部机制之软中断
- 【iOS 开发】iOS 开发 简介 (IOS项目文件 | MVC 模式 | 事件响应机制 | Storyboard 控制界面 | 代码控制界面 | Retina 屏幕图片适配)
- Linux内核的时钟中断机制(7)
- 内核中断机制
- Linux 2.4.x内核软中断机制(转)
- linux内核锁机制实例代码-不可睡眠锁之自旋锁之二
- Linux内核的时钟中断机制(8)