微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux中断机制之中断处理

ARM Linux中断机制之中断处理

时间:11-09 来源:互联网 点击:

@@ we have the value
1001:
adds\irqnr, \irqnr, #IRQ_EINT0
1002:
@@ exit here, Z flag unset if IRQ

.endm

(4)

宏ret_to_user在文件arch/arm/kernel/entry-common.S下定义:

ENTRY(ret_to_user)
ret_slow_syscall:
disable_irq//禁止中断
ldrr1, [tsk, #TI_FLAGS]//获取线程结构体thread_union的flags成员
tstr1, #_TIF_WORK_MASK//判断task是否被阻塞
bnework_pending //根据需要进行进程的切换,该段代码在下面讲述。
no_work_pending://不需要进程切换
/* perform architecture specific actions before user return */
arch_ret_to_user r1, lr

@ slow_restore_user_regs
ldrr1, [sp, #S_PSR]@ get calling cpsr
ldrlr, [sp, #S_PC]!@ get pc
msrspsr_cxsf, r1@ save in spsr_svc //// spsr里保存好被中断代码处的状态(cpsp)
ldmdbsp, {r0 - lr}^//恢复中断前寄存器的值恢复到各个寄存器。
movr0, r0
addsp, sp, #S_FRAME_SIZE - S_PC
movspc, lr//返回用户态
ENDPROC(ret_to_user)

在arch/arm/kernel/entry-common.S中

work_pending:
tstr1, #_TIF_NEED_RESCHED//判断是否需要调度进程
bnework_resched//进程调度
tstr1, #_TIF_SIGPENDING
beqno_work_pending//无需调度,返回
movr0, sp@ regs
movr2, why@ syscall
bldo_notify_resume
bret_slow_syscall@ Check work again

work_resched:
blschedule//调用进程切换函数。

这里只讲了在用户模式下的中断处理,在内核模式下的处理方式也大抵相仿,就不再赘言了。

中断处理函数的C语言入口

asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);

irq_enter();//进入中断上下文

if (irq >= NR_IRQS)
handle_bad_irq(irq, &bad_irq_desc);
else
generic_handle_irq(irq);//根据中断号获取中断描述结构体,并调用其中断处理函数。

irq_finish(irq);//退出中断上下文

irq_exit();
set_irq_regs(old_regs);
}

//函数generic_handle_irq()是函数generic_handle_irq_desc()的包装。

static inline void generic_handle_irq(unsigned int irq)
{
generic_handle_irq_desc(irq, irq_to_desc(irq));
}

/*

如果实现了上层中断处理函数desc->handle_irq就调用它,实际上在中断处理函数s3c24xx_init_irq()中已为每一个

中断线分配了一个上层中断处理函数。

如果desc->handle_irq为空就调用通用中断处理函数__do_IRQ(irq);,在干函数中调用了函数handle_IRQ_event(),

在函数handle_IRQ_event()中执行了该条中断线上的每一个中断例程。

*/

static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
{
#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
desc->handle_irq(irq, desc);
#else
if (likely(desc->handle_irq))
desc->handle_irq(irq, desc);
else
__do_IRQ(irq);
#endif
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top