IRQ中断处理流程
基于Linux2.6.30.4分析IRQ中断的处理流程。
1.中断入口
/* arch/arm/kenel/entry-armv.S*/
b vector_irq + stubs_offset
2.vector_irq
vector_stub 宏展开即为vector_irq, 参考Linux异常体系之vector_stub宏解析。
/*
* Interrupt dispatcher
*/
vector_stub irq, IRQ_MODE, .long __irq_usr @ (USR_26 / USR_32)
.long __irq_invalid @ (FIQ_26 / FIQ_32)
.long __irq_invalid @ (IRQ_26 / IRQ_32)
.long __irq_svc @ (SVC_26 / SVC_32)
3.__irq_user
__irq_usr:
usr_entry /*3.1*/
kuser_cmpxchg_check #ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
get_thread_info tsk /*3.2*/ #ifdef CONFIG_PREEMPT
/*
*r8<--old preempt_count
*r7<--preempt_count+1
*preempt_count<--r7
*/
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
add r7, r8, # @ increment it
str r7, [tsk, #TI_PREEMPT]
#endif irq_handler /*3.3*/
#ifdef CONFIG_PREEMPT
/*
*r0<--new preempt_count
*preempt<--old preempt_count
*/
ldr r0, [tsk, #TI_PREEMPT]
str r8, [tsk, #TI_PREEMPT]
teq r0, r7
strne r0, [r0, -r0]
#endif #ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_on
#endif mov why, #
b ret_to_user /*3.4*/
UNWIND(.fnend )
ENDPROC(__irq_usr)
3.1__user_entry
.macro usr_entry
UNWIND(.fnstart )
UNWIND(.cantunwind ) @ don't unwind the user space
/* DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));*/
sub sp, sp, #S_FRAME_SIZE /**/
stmib sp, {r1 - r12} ldmia r0, {r1 - r3}
add r0, sp, #S_PC @ here for interlock avoidance
mov r4, #- @ "" "" "" "" str r1, [sp] @ save the "real" r0 copied
@ from the exception stack @
@ We are now ready to fill in the remaining blanks on the stack:
@
@ r2 - lr_<exception>, already fixed up for correct return/restart
@ r3 - spsr_<exception>
@ r4 - orig_r0 (see pt_regs definition in ptrace.h)
@
@ Also, separately save sp_usr and lr_usr
@
stmia r0, {r2 - r4}
/*“^”符号表示访问user mode的寄存器*/
stmdb r0, {sp, lr}^ @
@ Enable the alignment trap while in kernel mode
@
alignment_trap r0 @
@ Clear FP to mark the first stack frame
@
zero_fp
.endm
这里面用到pt_regs结构保存栈上的数据,8字节对齐
/*
* This struct defines the way the registers are stored on the
* stack during a system call. Note that sizeof(struct pt_regs)
* has to be a multiple of 8.
*/
struct pt_regs {
long uregs[];
};
与之相关的宏定义如下
DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
DEFINE(S_R2, offsetof(struct pt_regs, ARM_r2));
DEFINE(S_R3, offsetof(struct pt_regs, ARM_r3));
DEFINE(S_R4, offsetof(struct pt_regs, ARM_r4));
DEFINE(S_R5, offsetof(struct pt_regs, ARM_r5));
DEFINE(S_R6, offsetof(struct pt_regs, ARM_r6));
DEFINE(S_R7, offsetof(struct pt_regs, ARM_r7));
DEFINE(S_R8, offsetof(struct pt_regs, ARM_r8));
DEFINE(S_R9, offsetof(struct pt_regs, ARM_r9));
DEFINE(S_R10, offsetof(struct pt_regs, ARM_r10));
DEFINE(S_FP, offsetof(struct pt_regs, ARM_fp));
DEFINE(S_IP, offsetof(struct pt_regs, ARM_ip));
DEFINE(S_SP, offsetof(struct pt_regs, ARM_sp));
DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr));
DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc));
DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr));
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); #define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
#define ARM_sp uregs[13]
#define ARM_ip uregs[12]
#define ARM_fp uregs[11]
#define ARM_r10 uregs[10]
#define ARM_r9 uregs[9]
#define ARM_r8 uregs[8]
#define ARM_r7 uregs[7]
#define ARM_r6 uregs[6]
#define ARM_r5 uregs[5]
#define ARM_r4 uregs[4]
#define ARM_r3 uregs[3]
#define ARM_r2 uregs[2]
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
macos
3.2 get_thread_info tsk
tsk即r9寄存器的别名,内核中为寄存器声明的别名如下
/*
* These are the registers used in the syscall handler, and allow us to
* have in theory up to 7 arguments to a function - r0 to r6.
*
* r7 is reserved for the system call number for thumb mode.
*
* Note that tbl == why is intentional.
*
* We must set at least "tsk" and "why" when calling ret_with_reschedule.
*/
scno .req r7 @ syscall number
tbl .req r8 @ syscall table pointer
why .req r8 @ Linux syscall (!= )
tsk .req r9 @ current thread_info
get_thread_info tsk的作用是获取sp地址保存在tsk(r9)中,即r9中保存当前任务的thread_info结构的地址。
.macro get_thread_info, rd
mov \rd, sp, lsr # /*获取sp地址*/
mov \rd, \rd, lsl # /*8KBytes对齐*/
.endm
3.3 irq_handler
irq_handler函数调用分析以后再写。
/*
* Interrupt handling. Preserves r7, r8, r9
*/
.macro irq_handler
get_irqnr_preamble r5, lr
: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrne lr, 1b
bne asm_do_IRQ #ifdef CONFIG_SMP
/*
* XXX
*
* this macro assumes that irqstat (r6) and base (r5) are
* preserved from get_irqnr_and_base above
*/
test_for_ipi r0, r6, r5, lr
movne r0, sp
adrne lr, 1b
bne do_IPI #ifdef CONFIG_LOCAL_TIMERS
test_for_ltirq r0, r6, r5, lr
movne r0, sp
adrne lr, 1b
bne do_local_timer
#endif
#endif .endm
3.4 ret_to_user
ret_to_user函数调用分析以后再写。
/*
* "slow" syscall return path. "why" tells us if this was a real syscall.
*/
ENTRY(ret_to_user)
ret_slow_syscall:
disable_irq @ disable interrupts
ldr r1, [tsk, #TI_FLAGS]
tst r1, #_TIF_WORK_MASK
bne work_pending
no_work_pending:
/* perform architecture specific actions before user return */
arch_ret_to_user r1, lr @ slow_restore_user_regs
ldr r1, [sp, #S_PSR] @ get calling cpsr
ldr lr, [sp, #S_PC]! @ get pc
msr spsr_cxsf, r1 @ save in spsr_svc
ldmdb sp, {r0 - lr}^ @ get calling r0 - lr
mov r0, r0
add sp, sp, #S_FRAME_SIZE - S_PC
movs pc, lr @ return & move spsr_svc into cpsr
ENDPROC(ret_to_user)
IRQ中断处理流程的更多相关文章
- bootloader启动代码init.s解析----IRQ中断处理函数
bootloader启动代码init.s解析----IRQ中断处理函数 init.s源代码如下: ;///////////////////////////////////////////// ;opt ...
- 【原创】中断子系统-ARM GPIO中断处理流程
目录 第一部分 GIC中断控制器的注册 1. GIC驱动分析 2.GIC驱动流程分析 第二部分 device node转化为platform_device 第三部分:platform_device注册 ...
- Exynos4412 中断处理流程详解
Linux 中,当外设触发中断后,大体处理流程如下: a -- 具体CPU architecture相关的模块会进行现场保护,然后调用machine driver对应的中断处理handler; b - ...
- 中断处理流程,ok6410
中断处理流程 CPU在工作的过程中,经常需要与外设进行交互,交互的方式包括”轮询方式”,”中断方式”. 1.轮询方式: CPU不断地查询设备的状态.该方式实现比较简单,但CPU利用率很低,不适合多任务 ...
- Linux 简单按键中断处理流程
中断处理程序中不能延时.休眠之类的,一定要最快速.高效的执行完. // 功能:申请中断 // 参数1:中断号码,通过宏 IRA_EINT(x) 获取 // 参数2:中断的处理函数,填函数名 // 参数 ...
- ATMEL精妙的IRQ中断处理过程
A: 从栈地址开始,栈顶为AT91SAM7S64的16K片内RAM尽头0x00204000IRQ_STACK_SIZE = 3*8*4FIQ_STACK_SIZE = 0x004ABT_STACK_S ...
- 专题2-通过按键玩中断\第1课-中断处理流程深度剖析-lesson1
中断概念 1.中断生命周期 串口先产生一个事件,该事件传送到中断控制器里面,中断控制器会进行相应过滤,能通过过滤,那么就交给CPU去处理. 2.中断源 2440芯片手册 6410芯片手册 3.中断过滤 ...
- Linux中断处理流程
http://blog.csdn.net/dianhuiren/article/details/7468956
- Linux中断处理体系结构分析
Linux中断处理体系结构分析(一) 异常,就是可以打断CPU正常运行流程的一些事情,比如外部中断.未定义指令.试图修改只读的数据.执行swi指令(Software Interrupt Instruc ...
随机推荐
- Codeforces 1142E(图、交互)
题目传送 官方题解说的很好了,剩下的就是读大佬代码了,前面是tarjan求SCC缩点图.我图论没学过,接下来删点是怎么操作看得有点头秃,直到我看到了%%%安德鲁何神仙的代码. 按照题面连通紫线以后,我 ...
- [已读]用Angularjs开发下一代web应用
屯了很久了,貌似是国内出现的第一本讲angularjs的书...上上周看完的时候,angular2都要出来了...angular的双向绑定很赞,因为之前公司后台系统我都用tmodjs做,模板语法什么的 ...
- WPF中获取指定坐标依赖对象数据项
上图中红色框区域是一个自定义的ListBox控件,需要实现的功能是,点击红框区域中某项时,获取当前选中项的数据项 控件的MouseDown事件部分代码为: var x = TreeHelper.Fin ...
- sql server 日期 查询技巧
CONVERT(varchar(100), SendTime, 23) –-sql里的字段SendTime参数 selectdateName(weekday,getDate());--返回当前星期 s ...
- input type=file 选择图片并且实现预览效果
通过<input />标签,给它指定type类型为file,可提供文件上传: accept:可选择上传类型,如:只要传图片,且不限制图片格式,为image/*: multiple:规定是否 ...
- Android 开机启动服务
在xml中注册 <!-- 开机广播 --> <receiver android:name=".receiver.BootBroadcastReceiver"> ...
- andorid 向上滑动控制标题栏显示
要实现这样的功能,原理不难,监听滑动距离再设置标题栏的透明度 下面是监听一个带头view的list实现核心代码: mbar是标题栏 mListView.setOnScrollListener(new ...
- Objective-C Runtime Reference
This document describes the OS X Objective-C 2.0 runtime library support functions and data structur ...
- Notepad++设计Tab制表符为4个空格
Notepad++中,常常需要将一个Tab制表符转换成4个空格.这种情况大多发生在对空白检查严格的情况下,比如Python程序. 设置 → 首选项 → 制表符设置 → 勾选“ 转换为空格 ”.
- bzip2命令
bzip2命令——压缩文件 命令所在路径:/usr/bin/bzip2 示例1: # bzip2 yum.log 压缩当前目录下yum.log文件成yum.log.bz2 示例2: # bzip2 - ...