.中断方式获取按键值

单片机:
)按键按下
)cup发生中断,跳转到异常向量入口执行
)b 函数
a.保存被中断的现场
b.执行中断处理函数
c.恢复
linux:
)trap_init()函数构造异常向量
)vector_irq + stubs_offset 跳转,vector_irq用宏来实现
a.保存寄存器的值
b.asm_do_IRQ
c.恢复
2.linux异常处理结构分析
---------------------------------------------
trap_init()函数构造了异常向量
把__vectors_start代码复制到vectors这个地址中去
--------------------------------------------- 1)
/arch/arm/kernel/traps.c
trap_init()
{
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
......
}
vectors ====> CONFIG_VECTORS_BASE 异常向量的地址,可配置项 2)
/arch/arm/kernel/entry-armv.S
__vectors_start分析:
-------------------------------------------
__vectors_start:
ARM( swi SYS_ERROR0 )
THUMB( svc # )
THUMB( nop )
W(b) vector_und + stubs_offset @这些都是异常向量
W(ldr) pc, .LCvswi + stubs_offset
W(b) vector_pabt + stubs_offset
W(b) vector_dabt + stubs_offset
W(b) vector_addrexcptn + stubs_offset
W(b) vector_irq + stubs_offset
W(b) vector_fiq + stubs_offset
  ......
----------------------------------------------
3)分析vector_und
vector_und由vector_stub宏定义而来
vector_stub und, UND_MODE
---------------------------------------------------------
//宏定义
.macro vector_stub, name, mode, correction=
.align vector_\name:
.if \correction
sub lr, lr, #\correction
.endif
  ...... //替换后
.macro vector_stub, name, mode, correction=
.align vector_und: @定义了一个标号 @
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
@ (parent CPSR)
@
stmia sp, {r0, lr} @ save r0, lr
mrs lr, spsr
str lr, [sp, #] @ save spsr @
@ Prepare for SVC32 mode. IRQs remain disabled.
@
mrs r0, cpsr
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0 ....... .endm -------------------------------------------------------------
4)

.long __und_usr @ (USR_26 / USR_32) //作用:保存寄存器,做处理,恢复寄存器
.long __und_invalid @ (FIQ_26 / FIQ_32)
.long __und_invalid @ (IRQ_26 / IRQ_32)
.long __und_svc @ (SVC_26 / SVC_32)
.long __und_invalid @
.long __und_invalid @
.long __und_invalid @
.long __und_invalid @
.long __und_invalid @
.long __und_invalid @
.long __und_invalid @ a
.long __und_invalid @ b
.long __und_invalid @ c
.long __und_invalid @ d
.long __und_invalid @ e
.long __und_invalid @ f .align
-----------------------------------------------------------------
==========================================================================

分析vector_irq
1)W(b) vector_irq + stubs_offset
-----------------------------------------------------------------
2)
vector_stub irq, IRQ_MODE,
替换后
.macro vector_stub, name, mode, correction=
.align vector_irq: //计算返回地址
sub lr, lr, #\correction @
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
@ (parent CPSR)
@
stmia sp, {r0, lr} @ save r0, lr
mrs lr, spsr
str lr, [sp, #] @ save spsr @
@ Prepare for SVC32 mode. IRQs remain disabled.
@
mrs r0, cpsr
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0 @
@ the branch table must immediately follow this code
@
and lr, lr, #0x0f
THUMB( adr r0, 1f )
THUMB( ldr lr, [r0, lr, lsl #] )
mov r0, sp
ARM( ldr lr, [pc, lr, lsl #] )
movs pc, lr @ branch to handler in SVC mode
ENDPROC(vector_\name) .align
@ handler addresses follow this label
:
.endm
-----------------------------------------------------------

3)
.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)
.long __irq_invalid @
.long __irq_invalid @
.long __irq_invalid @
.long __irq_invalid @
.long __irq_invalid @
.long __irq_invalid @
.long __irq_invalid @ a
.long __irq_invalid @ b
.long __irq_invalid @ c
.long __irq_invalid @ d
.long __irq_invalid @ e
.long __irq_invalid @ f ------------------------------------------------------
4)
__irq_usr分析:
__irq_usr:
usr_entry @入口
kuser_cmpxchg_check get_thread_info tsk
#ifdef CONFIG_PREEMPT
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
add r7, r8, # @ increment it
str r7, [tsk, #TI_PREEMPT]
#endif irq_handler @处理函数
#ifdef CONFIG_PREEMPT
ldr r0, [tsk, #TI_PREEMPT]
str r8, [tsk, #TI_PREEMPT]
teq r0, r7
ARM( strne r0, [r0, -r0] )
THUMB( movne r0, # )
THUMB( strne r0, [r0] )
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_on
#endif mov why, #
b ret_to_user
UNWIND(.fnend )
ENDPROC(__irq_usr) .ltorg .align
------------------------------------------------------
usr_entry分析:

.macro usr_entry
UNWIND(.fnstart )
UNWIND(.cantunwind ) @ don't unwind the user space
sub sp, sp, #S_FRAME_SIZE
ARM( stmib sp, {r1 - r12} ) @保存寄存器
THUMB( stmia sp, {r0 - 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 ...... .endm
------------------------------------------------------------
irq_handler分析:

.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, BSYM(1b)
bne asm_do_IRQ @跳转到C程序里面处理 ...... .endm
5) 调用asm_do_IRQ C处理程序

字符设备驱动笔记——中断方式按键驱动之linux异常处理结构(四)的更多相关文章

  1. 字符设备驱动笔记——中断方式按键驱动之linux中断处理结构(五)

    一.单片机下的中断处理 )分辨是哪一个中断 )调用处理函数 )清中断 二.linux下的中断处理 1)/arch/arm/kernel/irq.c asmlinkage void __exceptio ...

  2. linux驱动之中断方式获取键值

    linux驱动之中断方式获取键值 ----------------------------------------------------------------------------------- ...

  3. linux字符驱动之poll机制按键驱动

    在上一节中,我们讲解了如何自动创建设备节点,实现一个中断方式的按键驱动.虽然中断式的驱动,效率是蛮高的,但是大家有没有发现,应用程序的死循环里的读函数是一直在读的:在实际的应用场所里,有没有那么一种情 ...

  4. linux字符设备学习笔记【原创】

    1.申请设备号 int register_chrdev_region(dev_t from, unsigned count, const char *name) 指定从设备号from开始,申请coun ...

  5. ARM Linux 驱动Input子系统之按键驱动测试

    上一篇已经谈过,在现内核的中引入设备树之后对于内核驱动的编写,主要集中在硬件接口的配置上了即xxxx.dts文件的编写. 在自己的开发板上移植按键驱动: 1.根据开发板的原理图 确定按键的硬件接口为: ...

  6. 3.字符设备驱动------Poll机制

    1.poll情景描述 以之前的按键驱动为例进行说明,用阻塞的方式打开按键驱动文件/dev/buttons,应用程序使用read()函数来读取按键的键值. ) { read(fd, &key_v ...

  7. 谈谈Linux字符设备驱动的实现

    @ 目录 字符设备驱动基础 申请设备号 创建设备节点 在驱动中实现操作方法 文件IO调用驱动中的操作 应用程序与驱动的数据交互 内核驱动如何控制外设 控制LED的简单驱动实例 驱动程序的改进 框架复盘 ...

  8. 入门级的按键驱动——按键驱动笔记之poll机制-异步通知-同步互斥阻塞-定时器防抖

    文章对应视频的第12课,第5.6.7.8节. 在这之前还有查询方式的驱动编写,中断方式的驱动编写,这篇文章中暂时没有这些类容.但这篇文章是以这些为基础写的,前面的内容有空补上. 按键驱动——按下按键, ...

  9. 驱动开发--【字符设备、块设备简介】【sky原创】

    驱动开发   字符设备,块设备,网络设备   字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问   EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是 ...

随机推荐

  1. 浏览器 UA 判断

    export const inBrowser = typeof window !== 'undefined' export const inWeex = typeof WXEnvironment != ...

  2. 纯jascript解决手机端拍照、选图后图片被旋转问题

    需要的js1 需要的js2 这里主要用到Orientation属性. Orientation属性说明如下: 旋转角度 参数 0° 1 顺时针90° 6 逆时针90° 8 180° 3 <!DOC ...

  3. exception Access restriction: The type 'BASE64Encoder' is not API

      Created by Marydon on 1.情景展示 在eclipse中切换jdk版本后,报错信息为:exception Access restriction: The type 'BASE6 ...

  4. ASP.NET MVC:通过FileResult向浏览器发送文件

    在 Controller 中我们可以使用 FileResult 向客户端发送文件. FileResult FileResult 是一个抽象类,继承自 ActionResult.在 System.Web ...

  5. python线程详解

    #线程状态 #线程同步(锁)#多线程的优势在于可以同时运行多个任务,至少感觉起来是这样,但是当线程需要共享数据时,可能存在数据不同步的问题. #threading模块#常用方法:'''threadin ...

  6. 1、配置JAVA的环境变量

    想要成功配置Java的环境变量,那肯定就要安装JDK,才能开始配置的. 想要成功配置Java的环境变量,那肯定就要安装JDK,才能开始配置的. 安装JDK 向导进行相关参数设置.如图:   正在安装程 ...

  7. SpringMVC 类内部的RequestMapping注解能否被继承?

    首先注意标题,说的是类内部的注解 结论是: 不能,但是子类却可以享有父类中该注解带来的效果. 看了一下这个:http://elf8848.iteye.com/blog/1621392 自己也试了一下, ...

  8. bss段,代码段及数据段,堆栈段的区别

    bss段,代码段及数据段,堆栈段的区别 时间:2012-11-21 10:0772人阅读 BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英 ...

  9. hibernate4无法保存数据

    hibernate4无法保存数据 author: hiu 以后都发文章我都备注一下作者了,hiu就是我了 红色字体更新日期:2014-07-08 初次使用hibernate4,使用getCurrent ...

  10. 【mysql+RBAC】RBAC权限处理(转载:http://www.cnblogs.com/xiaoxi/p/5889486.html 平凡希)

    1.这里我只讲核心,mysql查询语句:FIND_IN_SET(str,strlist) 2.具体教程可以参考[童攀老师的RBAC],很清晰,赞一个. 3.详解:mysql的find_in_set 首 ...