历史上的今天
今天是:2024年09月03日(星期二)
2021年09月03日 | S3C2440 开发板实战(4):外部中断
2021-09-03 来源:eefocus
最近学了一系列的中断程序,就复习下顺便撸一篇文来分享下学习。以外部中断为例(之前单片机用的最多的)
1. ARM 工作模式
ARM体系结构(除了Cortex之外支持7种工作模式),取决于程序状态寄存器中低5位的值(在第二部分会详细讲到)
• User (usr): The normal ARM program execution state
(用户模式:ARM程序的正常执行状态)
• FIQ (fiq): Designed to support a data transfer or channel process
(快速中断模式:处理高速中断用于高速数据传输或通道传输)
• IRQ (irq): Used for general-purpose interrupt handling
(外部中断模式:用于普通的中断处理)
• Supervisor (svc): Protected mode for the operating system
(管理模式:操作系统的保护模式,处理软中断SWI)
• Abort mode (abt): Entered after a data or instruction prefetch abort
(中止模式:处理存储器故障,实现虚拟存储器与存储器保护)
• System (sys): A privileged user mode for the operating system
(系统模式:运行特权级的操作系统任务)
• Undefined (und): Entered when an undefined instruction is executed
(未定义指令模式:处理未定义的指令,在执行未定义的指令时输入)
2. ARM处理器的寄存器组织
ARM处理器共有37个寄存器,包括31个通用寄存器(包括PC)和六个状态寄存器。如下图所示:

其中黑色带角标的我们可以这么理解:
由于任何工作状态出现异常,跳到其他的模式。以中断为例,需要保护现场,即将把r0 - r14全部保护起来,所以为了减少保护的寄存器,通过硬件操作在中断发生的时候把黑色角标对应的值传入,等待模式变回去的时候再提取表出来,达到恢复现场的功能。
所以对于快中断模式来说有很多的banked register,这是为了达到它的快速性,不用那么多数据搬来搬去。
对于程序状态寄存器(CPSR)也同理,在出现不用的模式切换的时候需要把CPSR值传入SPSR进行现场保护。
Program Status Register Format (PSR):

• N(符号标志):N = 1表示运算结果为负数,N = 0表示运算结果为正数
• Z(全0标志):运算结果为0时 Z = 1
• C(进借位标志):加法进位:C = 1; 减法借位: C = 1
• V(溢出标志):加减法运算结果有溢出时V = 1
• I(中断禁止控制位):I = 1表示禁止外部IRQ中断,I = 0表示允许外部IRQ中断
• F(快速中断禁止控制位):F = 1表示禁止FIQ中断,F = 0表示允许FIQ中断
• T(ARM与Thumb指令集之间的切换):T = 1表示执行Thumb指令,T = 0表示执行ARM指令
• M0-M4(模式选择位):其模式选择如下表所示:

PSR中的其余位是保留的。在更改PSR的标志或控制位时,必须确保这些未使用的位没有被更改。另外,程序不应该依赖于包含特定值的它们,因为在将来的处理器中,它们可能读取为1或0。(不管就行)
3. ARM处理器的异常及其相应过程
当程序的正常流必须暂时停止时,就会出现异常,例如为了从外设提供中断服务。在处理异常之前,必须保留当前处理器的状态,以便在处理程序例程完成后恢复原始程序。
有可能同时出现几个例外情况。如果发生这种情况,它们将按照固定的顺序被处理,在第四部分中通过优先级寄存器进行处理。
I. 初始化异常
主要是对与异常有关的寄存器进行操作。不同的异常配置不同的寄存器。
II. 进入异常的操作(硬件自动操作)
STEP1: 将下一条指令的地址保存在相应的链接寄存器中。
如果从ARM状态输入了异常,那么下一条指令的PC地址将被复制到Link Register(lr寄存器)(R14)。偏移量取决于中断的类型。

这样程序在从异常返回时从正确的位置恢复。这意味着异常处理程序不需要确定异常的状态。
STEP2: 将CPSR复制到对应的SPSR
STEP3: 将CPSR MODE位设置为对应异常的值
STEP4: PC值调至对应异常的程序位置执行(异常向量表 Exception Vectors )

所以按照这个表在程序的开头应该包含(以U-boot的start.S为例):
.globl _start
_start: b reset // 0x00
ldr pc, _undefined_instruction // 0x04
ldr pc, _software_interrupt // 0x08
ldr pc, _prefetch_abort // 0x0c
ldr pc, _data_abort // 0x10
ldr pc, _not_used // 0x14
ldr pc, _irq // 0x18
ldr pc, _fiq // 0x1c
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
III. 进入中断
* 在中断向量表中可以发现,Reset中使用的是b进行跳转,但是其他模式的跳转指令使用ldr,并且通过配合.word进行配合来做到PC跳转作用。其中差别在于b跳转是一个绝对跳转,在代码重定位之后,应该执行SDRAM中的程序而不是NOR FLASH中的。所以利用链接地址的办法,读SDRAM中执行中断函数的地址进行跳转,从而实现执行中断函数。
在中断函数中应该不用多说,就是那三步 :
保存现场
执行异常
恢复现场
IV. 跳出异常的操作
STEP1: 将LR中的值移动到PC。(下一条指令)
STEP2: 将SPSR复制回CPSR。
STEP3: 清除中断标志位。
4. ARM外部中断程序编写过程
I. 初始化外部中断
第一部分:中断初始化
首先先看中断源是如何进入CPU进行工作的,以芯片手册中中断流程图图为例进行讲解

Setp 1: 打开CPSR中 中断总开关
mrs r0, cpsr
bic r0, r0, #0xf //将模式设置为user模式
bic r0, r0, (1<<7) //外部中断IRQ打开
msr cpsr, r0 //user模式
ldr sp, =0x33f00000 //设置user的栈(没啥用只是和以后的中断地址做比较)
Step 2:SOURCE PENDING (SRCPND)REGISTER
用途:在中断完成之后将其对应为设置为1,进入中断再请求
这里将的是外部中断,所以并没有SUB-SOURCE,所以Sources直接从输入到寄存器SRCPND,他的作用为:指示中断请求状态,所以应该设置相应的位为“1”进入请求状态。
Step 3: INTERRUPT MODE (INTMOD) REGISTER
用途:将中断设置为快速中断模式
这个寄存器由32位组成,每个位与一个中断源相关。如果一个特定的位设置为1,则在FIQ(快速中断)模式下处理相应的中断。否则,它被处理在IRQ模式(正常中断)。由于我们很少使用到快中断模式,所以按照初始值设置为0x0000000就OK。
Step 4: INTERRUPT MASK (INTMSK) REGISTER
用途:屏蔽/打开中断请求
这个寄存器也有32位,每个位与一个中断源相关。如果一个特定的位被设置为1,CPU就不会为来自相应中断源的中断请求提供服务(注意,在该寄存器置1时,SRCPND寄存器的相应位也被设置为1),如果掩码位为0,则中断请求可以被服务。所以SRCPND不用进行初始化。
综上所述。在中断初始化函数中需要以下代码:
void init_EINT(void)
{
INTMSK &= ~((1<<0) | (1<<2) | (1<<5));
// 按键对应的中断: 中断 0 2 11 19 ->对应的位为:0 2 5
}
第二部分:外部中断IO口初始化(简化)
Step 1: LED初始化
由于led的程序之前写过,所以对于LED的初始化不做赘述。
Step2 : 按键初始化
寄存器1:GPxCON --------------------设置为中断模式
寄存器2:EXTINTx---------------------设置为双边触发
寄存器3:EINTMASK -----------------设置对应中断使能
void init_key(void)
{
GPFCON &= ~((3<<0) | (3<<4));
GPFCON |= ((2<<0) | (2<<4));
GPGCON &= ~((3<<6) | (3<<22));
GPGCON |= ((2<<6) | (2<<22));
EXTINT0 |= (7<<0) | (7<<8);
EXTINT1 |= (7<<12);
EXTINT2 |= (7<<12);
EINTMASK &= ~((1<<11) | (1<<19));
}
II. 进入中断
按照中断向量表我们编写中断函数irq:
do_irq:
/* 执行到这里之前:
* 1. lr_und保存有被中断模式中的下一条即将执行的指令的地址
* 2. SPSR_irq保存有被中断模式的CPSR
* 3. CPSR中的M4-M0被设置为10010, 进入到irq模式
* 4. 跳到0x18的地方执行程序
*/
// 1.保护现场
ldr sp, =0x33d00000
/* 在irq异常处理函数中有可能会修改r0-r12, 所以先保存 */
/* lr-4 是异常处理完后的返回地址, 也要保存 */
sub lr, lr, #4
stmdb sp!, {r0-r12, lr}
// 2.处理中断函数
bl Find_interrupt_source
/* 3.恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */
中断函数编写要点:
通过INTOFFSET、INTPEND和EINTPEND寄存器读出中断源
在中断发生完之后,要进行清中断(至顶向下清)
INTOFFSET和INTPEND是一样的,但是只能访问到一条线上的中断源(比如说EINT4-7 EINT8-23),这样在EINTPEND能够判断在具体是哪个中断。
故外部中断函数模板为:
void hand_irq_fun(void)
{
int bit = INTOFFSET;
if(bit == * || bit == *) // 目标中断位 (可不写)
irq_fun(bit);
SRCPND = (1< void irq_fun(int bit) { unsigned int val = EINTPEND; ....... }
史海拾趣
|
1 引言 典型的GPS接收机主要由4部分组成:天线、射频前端、相关器和导航解算部分。其中,天线主要负责信号的接收;射频前端负责信号的下变频,在当前的数字化接收机中还包括A/D转换,它是所有后端处理的 ...… 查看全部问答> |
|
尊敬的工程师: 感谢您对NI长期以来的支持,2009第五届NI测控前沿技术论坛即将拉开帷幕。 作为广受好评的年度盛会,您不仅可以通过资深工程师的讲解了解最新前沿技术,还可以亲自投票选择自己感兴趣的专题内容。 NI诚邀您参与第五届测控前 ...… 查看全部问答> |
|
电子企业招聘笔试面试题目 一、模拟电路 1、基尔霍夫定理的内容是什么?(仕兰微电子) 基尔霍夫电流定律是一个电荷守恒定律,即在一个电路中流入一个节点的电荷与流出同一个节点的电荷相等.基尔霍夫电压定律是一个能量守恒定律,即在一个回路中回 ...… 查看全部问答> |
|
提问幼稚问题:sql ce 20数据库建立同步时,是不是建立一次让本地数据库与分发远程数据库的连接就可以? 高人前辈们好! sql ce 20数据库建立同步时,是不是建立一次让本地数据库与分发远程数据库的连接就可以? 就比如在程序初始化的时候,让本地的数据库和远程数据库建立合并复制关系,以后就再也不用管它,它将会自动 ...… 查看全部问答> |
|
急需一个LPC2210 UCOS II KEIL工程模板,在周立功下的不是嵌入式的模板,并编译也不通过,现在需要一个UCOS II 的模板,谢谢!邮箱:zsj88@126.com… 查看全部问答> |




