1. ARM的中断模式有7种:

                                          1. 用户模式: 用于平时的程序运行

                                          2. 快速中断模式: 用于高速数据传输或者通道处理, 此模式的优先级最高 最容易被触发 32个中断只能有一个快速中断触发

                                          3. 中断模式:用于普通的中断模式

                                          4. 管理模式:操作系统使用的保护模式

                                          5. 数据访问终止模式: 当数据或指令与读取终止时候进入此模式

                                          6. 系统模式: 运行具有特权的操作系统任务

                                          7. 未定义指令终止模式:当未定义的指令执行时进入该模式 可用于支持硬件仿真。

 

2.  首先是看PSR (program status register)

     如果此寄存器的F-bit 设置成1 则arm不会再接受快速中断的请求。另外如果是I-bit 设置成了1 则CPU将会关闭所有的中断。 

 

上面的这个图解释了除了LCD之外的中断的模式:

SRCPND 这个寄存器可以查询到我们 那个地方发生了中断

SUBSRCPND 这个寄存器是用来管理串口等11个次一级重要的中断的

SUBMASK 是用来屏蔽SUBSRCPND所提供的中断

MASK用来屏蔽SRCPND寄存器上面的中断

MODE:设置成1 的时候可以把此寄存器设置成快速中断模式

 

 

Priority 如下图:

 

此图说明优先级是由这六个仲裁器去抉择的。寄存器位ARB_Mode和ARB_SEL的组合可以实现优先级的转换 情形如下所示:

 

 INTPND 寄存器 是记录哪一个中断拥有最高的优先级 且此寄存器只能有一位置位为1

 

 

 

 

 

下面来分析一下代码:

 1 @******************************************************************************
 2 @ File:head.S
 3 @ 功能:初始化,设置中断模式、管理模式的栈,设置好中断处理函数
 4 @******************************************************************************       
 5    
 6 .extern     main
 7 .text 
 8 .global _start 
 9 _start:
10 @******************************************************************************       
11 @ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
12 @******************************************************************************       
13     b   Reset
14 
15 @ 0x04: 未定义指令中止模式的向量地址
16 HandleUndef:
17     b   HandleUndef 
18  
19 @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
20 HandleSWI:
21     b   HandleSWI
22 
23 @ 0x0c: 指令预取终止导致的异常的向量地址
24 HandlePrefetchAbort:
25     b   HandlePrefetchAbort
26 
27 @ 0x10: 数据访问终止导致的异常的向量地址
28 HandleDataAbort:
29     b   HandleDataAbort
30 
31 @ 0x14: 保留
32 HandleNotUsed:
33     b   HandleNotUsed
34 
35 @ 0x18: 中断模式的向量地址
36     b   HandleIRQ
37 
38 @ 0x1c: 快中断模式的向量地址
39 HandleFIQ:
40     b   HandleFIQ
41 
42 Reset:                  
43     ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈
44     bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启
45     
46     msr cpsr_c, #0xd2       @ 进入中断模式
47     ldr sp, =3072           @ 设置中断模式栈指针
48 
49     msr cpsr_c, #0xd3       @ 进入管理模式
50     ldr sp, =4096           @ 设置管理模式栈指针,
51                             @ 其实复位之后,CPU就处于管理模式,
52                             @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略
53 
54     bl  init_led            @ 初始化LED的GPIO管脚
55     bl  init_irq            @ 调用中断初始化函数,在init.c中
56     msr cpsr_c, #0x53       @ 设置I-bit=0,开IRQ中断
57     
58     ldr lr, =halt_loop      @ 设置返回地址
59     ldr pc, =main           @ 调用main函数
60 halt_loop:
61     b   halt_loop
62 
63 HandleIRQ:
64     sub lr, lr, #4                  @ 计算返回地址
65     stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器
66                                     @ 注意,此时的sp是中断模式的sp
67                                     @ 初始值是上面设置的3072
68     
69     ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  
70     ldr pc, =EINT_Handle            @ 调用中断服务函数,在interrupt.c中
71 int_return:
72     ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr
73     

 

 

一些注解:

第46行: 

msr cpsr_c, #0xd2

msr 的意思是把一个立即数存储到一个PSR(program status register)那么这个寄存器是cpsr_c 又被称作寄存器R16是记录状态的寄存器(请参见2440datasheet P72)

这个就是R16寄存器 其中设置中断的时候需要吧第七位和第六位都需要置成1 这样子一开始先关闭中断和快速中断。

后面五位设置成中断模式(参见datasheet P78)

 

第47行:

 ldr sp, =3072           @ 设置中断模式栈指针
这里面的其实就是给中断分配一个内存区 这个数字可以“随意”取只要能让前面的程序有足够的内存就好。
第56行:
  msr cpsr_c, #0x53 : 这里面是开总中断 在管理模式下

第64行:
 sub lr, lr, #4                  @ 计算返回地址 这里是ARM自己的特定值记住便好
第65行:
stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器 这里面stmdb(stm相当于Push and DB (Decrement Before))Ex: STMFD    sp!, {r0-r5}  ; Push onto a Full Descending Stack
这里的意思是 把R0~R12还有lr(返回值的内容)压入栈
 ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr 第72行:LDM(相当于POP and ia Increment After ) 这句话表示把寄存器还原
Saved Process Status Registers (SPSRs)
Current Program Status Register (CPSR)
posted on 2019-05-27 17:58  闲云潭影  阅读(238)  评论(0编辑  收藏  举报