6410之异常中断处理
2013-08-13 15:39
204 查看
单片机中断方式获取键值:
1.按键按下
2.CPU发生中断,跳转到异常向量入口地址执行
3.跳转到中断处理函数
中断处理函数的工作有:
a.保存被中断的现场
b.执行中断处理函数
c.恢复现场
linux中断方式获取键值:
1.异常向量的设置:ARM架构的CPU的异常向量基地之可以在0x00000000(比如之前裸板程序中所说的异常向量基地址就在这里),也可以是0xffff0000(linux内核使用的地址)可以查看trap_init函数进行查看它是如何将异常向量赋值到0xffff0000处的。拷贝的动作如下所示:
void __init early_trap_init(void)
{
。。。
memcpy((void *)vectors,
__vectors_start, __vectors_end - __vectors_start);
。。。
}
2.这里vectors,__vectors_start,__vectors_end的定义如下:
vectors:
unsigned long vectors = CONFIG_VECTORS_BASE; // #define CONFIG_VECTORS_BASE 0xffff0000即为linux的虚拟地址
__vectors_start,__vectors_end定义在entry-armv.S (arch\arm\kernel),定义如下:
.globl
__vectors_start
__vectors_start:
ARM( swi
SYS_ERROR0 )
THUMB( svc
#0 )
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
.globl
__vectors_end
__vectors_end:
从上面可以看到__vectors_start和__vectors_end之间就是异常向量处理跳转列表。
3.取irq为例:
W(b) vector_irq + stubs_offset
vector_irq 的定义如下:
vector_stub irq, IRQ_MODE, 4
展开为:
.macro
vector_stub, name, mode, correction=0
//.macro
vector_stub, irq, IRQ_MODE, 4
.align
5
vector_\name:
//vector_irq:
.if \correction
//.if 4
sub lr, lr, #\correction
//sub
lr, lr, #4 减去4个字节,保证中断返回还是执行的是当前指令
.endif
@
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
@ (parent CPSR)
@
stmia sp, {r0, lr}
@ save r0, lr
mrs lr, spsr
str lr, [sp, #8]
@ 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 #2] )
mov r0, sp
ARM( ldr
lr, [pc, lr, lsl #2] )
movs pc, lr
@ branch to handler in SVC mode
ENDPROC(vector_\name)
上面做好准备工作就会跳转到下面的列表,下面列表列出的是在各种模式下发生中断所要跳转的中断列表:
.long
__irq_usr
@ 0 (USR_26 / USR_32)
.long __irq_invalid
@ 1 (FIQ_26 / FIQ_32)
.long __irq_invalid
@ 2 (IRQ_26 / IRQ_32)
.long __irq_svc
@ 3 (SVC_26 / SVC_32)
.long __irq_invalid
@ 4
.long __irq_invalid
@ 5
.long __irq_invalid
@ 6
.long __irq_invalid
@ 7
.long __irq_invalid
@ 8
.long __irq_invalid
@ 9
.long __irq_invalid
@ a
.long __irq_invalid
@ b
.long __irq_invalid
@ c
.long __irq_invalid
@ d
.long __irq_invalid
@ e
.long __irq_invalid
@ f
比如在用户模式和svc模式下发生了中断,就会跳转到__irq_usr,或__irq_svc去执行。在其他工作模式下不可能发生中断异常,否则使用"__irq_invalid",ARM架构CPU中使用4位数据来表示工作模式(目前只有7中工作模式),所以共有16个跳转分支。
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, #1
@ increment it
str r7, [tsk, #TI_PREEMPT]
#endif
irq_handler //中断处理调用asm_do_IRQ函数,恢复现场
#ifdef CONFIG_PREEMPT
ldr r0, [tsk, #TI_PREEMPT]
str r8, [tsk, #TI_PREEMPT]
teq r0, r7
ARM( strne
r0, [r0, -r0] )
THUMB( movne
r0, #0 )
THUMB( strne
r0, [r0] )
#endif
mov why, #0
b ret_to_user
UNWIND(.fnend )
ENDPROC(__irq_usr)
1.按键按下
2.CPU发生中断,跳转到异常向量入口地址执行
3.跳转到中断处理函数
中断处理函数的工作有:
a.保存被中断的现场
b.执行中断处理函数
c.恢复现场
linux中断方式获取键值:
1.异常向量的设置:ARM架构的CPU的异常向量基地之可以在0x00000000(比如之前裸板程序中所说的异常向量基地址就在这里),也可以是0xffff0000(linux内核使用的地址)可以查看trap_init函数进行查看它是如何将异常向量赋值到0xffff0000处的。拷贝的动作如下所示:
void __init early_trap_init(void)
{
。。。
memcpy((void *)vectors,
__vectors_start, __vectors_end - __vectors_start);
。。。
}
2.这里vectors,__vectors_start,__vectors_end的定义如下:
vectors:
unsigned long vectors = CONFIG_VECTORS_BASE; // #define CONFIG_VECTORS_BASE 0xffff0000即为linux的虚拟地址
__vectors_start,__vectors_end定义在entry-armv.S (arch\arm\kernel),定义如下:
.globl
__vectors_start
__vectors_start:
ARM( swi
SYS_ERROR0 )
THUMB( svc
#0 )
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
.globl
__vectors_end
__vectors_end:
从上面可以看到__vectors_start和__vectors_end之间就是异常向量处理跳转列表。
3.取irq为例:
W(b) vector_irq + stubs_offset
vector_irq 的定义如下:
vector_stub irq, IRQ_MODE, 4
展开为:
.macro
vector_stub, name, mode, correction=0
//.macro
vector_stub, irq, IRQ_MODE, 4
.align
5
vector_\name:
//vector_irq:
.if \correction
//.if 4
sub lr, lr, #\correction
//sub
lr, lr, #4 减去4个字节,保证中断返回还是执行的是当前指令
.endif
@
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
@ (parent CPSR)
@
stmia sp, {r0, lr}
@ save r0, lr
mrs lr, spsr
str lr, [sp, #8]
@ 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 #2] )
mov r0, sp
ARM( ldr
lr, [pc, lr, lsl #2] )
movs pc, lr
@ branch to handler in SVC mode
ENDPROC(vector_\name)
上面做好准备工作就会跳转到下面的列表,下面列表列出的是在各种模式下发生中断所要跳转的中断列表:
.long
__irq_usr
@ 0 (USR_26 / USR_32)
.long __irq_invalid
@ 1 (FIQ_26 / FIQ_32)
.long __irq_invalid
@ 2 (IRQ_26 / IRQ_32)
.long __irq_svc
@ 3 (SVC_26 / SVC_32)
.long __irq_invalid
@ 4
.long __irq_invalid
@ 5
.long __irq_invalid
@ 6
.long __irq_invalid
@ 7
.long __irq_invalid
@ 8
.long __irq_invalid
@ 9
.long __irq_invalid
@ a
.long __irq_invalid
@ b
.long __irq_invalid
@ c
.long __irq_invalid
@ d
.long __irq_invalid
@ e
.long __irq_invalid
@ f
比如在用户模式和svc模式下发生了中断,就会跳转到__irq_usr,或__irq_svc去执行。在其他工作模式下不可能发生中断异常,否则使用"__irq_invalid",ARM架构CPU中使用4位数据来表示工作模式(目前只有7中工作模式),所以共有16个跳转分支。
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, #1
@ increment it
str r7, [tsk, #TI_PREEMPT]
#endif
irq_handler //中断处理调用asm_do_IRQ函数,恢复现场
#ifdef CONFIG_PREEMPT
ldr r0, [tsk, #TI_PREEMPT]
str r8, [tsk, #TI_PREEMPT]
teq r0, r7
ARM( strne
r0, [r0, -r0] )
THUMB( movne
r0, #0 )
THUMB( strne
r0, [r0] )
#endif
mov why, #0
b ret_to_user
UNWIND(.fnend )
ENDPROC(__irq_usr)
相关文章推荐
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之三--Linux对异常和中断的处理
- 中断机制和中断描述符表、中断和异常的处理
- ARM基础学习-SWI异常中断处理
- 文件读写函数因为信号中断异常返回处理
- ARM中断异常处理的返回
- <<Linux内核完全剖析 --基于0.12内核>>学习笔记 第4章 80x86保护模式及其编程 4.6 中断和异常处理
- C语言中处理异常中断的方法
- 6410之linux中断处理结构
- 第12课第4.1节 字符设备驱动程序之中断方式的按键驱动_Linux异常处理结构
- 典型中断2:有未经处理的异常: 0xC00000FD: Stack Overflow
- HVM的中断与异常处理
- s3c2410 中断异常处理
- S3C2410A的异常机制[中断处理]
- ARM中断异常处理的返回
- S3C6410之uboot回炉再造(6)异常中断处理
- 中断异常的处理
- linux中断(与异常)处理过程
- 中断和异常的处理
- s3c2410 中断异常处理
- 异常和中断处理 ARM系统开发者指南 Chapter9-1