在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
芯片精品文章合集(500篇!) 创芯人才网--重磅上线啦!
查看: 2033|回复: 0

[原创] ARM-Linux 中断分析

[复制链接]
发表于 2010-8-25 10:43:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
ARM体系结构中,把复位中断、快速中断等都看作‘异常’,当这些‘异常’发生时,CPU会到固定地址处去找指令,他们对应的地址如下:
n
地址
异常类型
进入时的工作模式
n
0x00000000
Reset
Supervisor
n
0x00000004
Und
Undefined
n
0x00000008
Soft interupt
Supervisor
n
0x0000000c
Abort(prefetch)
Abort
n
0x00000010
Abort(data)

Abort
n
0x00000014
Reserved
Reserved
n
0x00000018
IRQ
IRQ
n
0x0000001c
FIQ
FIQ
首先要明确的一点就是,无论内存地址空间是如何映射的,以上这些地址都不会变,比如当有快速中断发生时,ARM将铁定到0X0000001C这个地址处取指令。这也是BOOTLOADER把操作系统引导以后,内存必须重映射的原因!否则操作系统不能真正接管整套系统!
LINUX启动以后要初始化这些区域,初始化代码在main.c中的start_kernel()中,具体是调用函数trap_ini()来实现的。如下面所示(具体可参照entry-armv.S):
.LCvectors:
swi
SYS_ERROR0

b
__real_stubs_start + (vector_undefinstr - __stubs_start)

ldr
pc, __real_stubs_start + (.LCvswi - __stubs_start)

b
__real_stubs_start + (vector_prefetch - __stubs_start)

b
__real_stubs_start + (vector_data - __stubs_start)

b
__real_stubs_start + (vector_addrexcptn - __stubs_start)

b
__real_stubs_start + (vector_IRQ - __stubs_start)


b
__real_stubs_start + (vector_FIQ - __stubs_start)
ENTRY(__trap_init)

stmfd
sp!, {r4 - r6, lr}

adr
r1, .LCvectors
@ set up the vectors

ldmia
r1, {r1, r2, r3, r4, r5, r6, ip, lr}

stmia
r0, {r1, r2, r3, r4, r5, r6, ip, lr}

add
r2, r0, #0x200

adr
r0, __stubs_start
@ copy stubs to 0x200

adr
r1, __stubs_end
1:
ldr
r3, [r0], #4

str
r3, [r2], #4

cmp
r0, r1

blt
1b

LOADREGS(fd, sp!, {r4 - r6, pc})
以上可以看出这个函数初始化了中断向量,实际上把相应的跳转指令拷贝到了对应的地址。
当发生中断时,不管是从用户模式还是管理模式调用的,最终都要调用do_IRQ():
__irq_usr:
sub
sp, sp, #S_FRAME_SIZE

stmia
sp, {r0 - r12}
@ save r0 - r12

ldr
r4, .LCirq

add
r8, sp, #S_PC

ldmia
r4, {r5 - r7}
@ get saved PC, SPSR

stmia
r8, {r5 - r7}
@ save pc, psr, old_r0

stmdb
r8, {sp, lr}^

alignment_trap r4, r7, __temp_irq

zero_fp
1:
get_irqnr_and_base r0, r6, r5, lr

movne
r1, sp

adrsvc
ne, lr, 1b

@

@ routine called with r0 = irq number, r1 = struct pt_regs *

@

bne
do_IRQ
@ 调用do_IRQ来实现具体的中断处理

mov
why, #0

get_current_task tsk

b
ret_to_user
对于以上代码,在很多文章中都有过分析,这里不再赘述。
Linux每个中断通过一个结构irqdesc来描述,各中断的信息都在这个结构中得以体现:
struct irqdesc {

unsigned int
nomask
: 1;
/* IRQ does not mask in IRQ
*/

unsigned int
enabled
: 1;
/* IRQ is currently enabled
*/

unsigned int
triggered: 1;
/* IRQ has occurred

*/

unsigned int
probing
: 1;
/* IRQ in use for a probe
*/

unsigned int
probe_ok : 1;
/* IRQ can be used for probe
*/

unsigned int
valid
: 1;
/* IRQ claimable

*/

unsigned int
noautoenable : 1;
/* don't automatically enable IRQ */

unsigned int
unused
:25;

void (*mask_ack)(unsigned int irq);
/* Mask and acknowledge IRQ
*/

void (*mask)(unsigned int irq);
/* Mask IRQ

*/

void (*unmask)(unsigned int irq);
/* Unmask IRQ

*/

struct irqaction *action;

/*


* IRQ lock detection


*/

unsigned int
lck_cnt;

unsigned int
lck_pc;

unsigned int
lck_jif;
};
更多内容请查询:http://www.fly-sun.com.cn
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-23 13:14 , Processed in 0.021761 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表