.中断方式获取按键值

单片机:
)按键按下
)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. linux sar命令详细说明相关参数

    详细说明linux的sar命令 sar(System Activity Reporter系统活动情况报告)是目前 Linux 上最为全面的系统性能分析工具之一,可以从多方面对系统的活动进行报告,包括: ...

  2. 网路总结01-HTTP协议和NSURLConnection

  3. css中clear属性的认识

    今天在看博客园的页面布局时发现有不少空白的div只有css属性:clear:both. 然后去W3C文档里和百度补脑了一下,总结如下: 这是之前我写的一段测试代码: <div style=&qu ...

  4. def函数之另类用法

    #python 27 #xiaodeng def list_opts(): return [ ('name', 'xiaodeng'), ('age', 28), ('), ('where', 'en ...

  5. Java BigDecimal进行精确计算

    前言 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以 ...

  6. python接口自动化(二十七)--html 测试报告——上(详解)

    简介 上一篇我们批量执行完用例后,生成的测试报告是文本形式的,不够直观,而且报告一般都是发给leader的,所以最好是直观一目了然,为了更好的展示测试报告,最好是生成 HTML 格式的.unittes ...

  7. 从gentoo回归Arch,上组图

    Arch一直在我笔记本里边,只是玩gentoo时我不进Arch了,现在回归Arch,升级到了最新,用上了gentoo的最新的2.6.31内核(自己配置,无initrd),引导程序用的grub4dos: ...

  8. redis安装配置文件配置

    环境: 虚拟机redhat5.5安装redis4.0.2 虚拟机IP:192.168.60.130 reids端口:6379 安装步骤不详述了(可参考: 亲密接触Redis-第一天), 大致步骤如下: ...

  9. nyoj----522 Interval (简单树状数组)

    Interval 时间限制:2000 ms  |  内存限制:65535 KB 难度:4   描述 There are n(1 <= n <= 100000) intervals [ai, ...

  10. iOS - PairProgramming 结对编程

    1.PairProgramming 结对编程(Pair-Programming)可能是近年来最为流行的编程方式.所谓结对编程,也就是两个人写一个程序,其中,一个人叫 Driver,另一个人叫 Obse ...