历史上的今天
返回首页

历史上的今天

今天是: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<    INTPND = (1<}

 

void irq_fun(int bit)

{

    unsigned int val = EINTPEND;

    

    .......

 

}

推荐阅读

史海拾趣

BELDEN公司的发展小趣事

BELDEN公司的故事始于1902年,当Joseph C. Belden在美国芝加哥创立这家公司时,他怀揣着对电线电缆制造的深厚热情与独特见解。初创时期,公司致力于研发和生产高品质的电线电缆产品,很快便在市场中赢得了良好的声誉。经过多次试验,公司成功发明了“Beldenamel”绝缘材料,这种柔韧的珐琅绝缘材料为公司的成功奠定了坚实的基础。随着产品的不断优化和市场的逐步拓展,BELDEN逐渐在电子行业中崭露头角。

Eagle-Picher公司的发展小趣事

1958年,Eagle-Picher公司的电池技术得到了重大的突破。在美国宇航局的探索者1号卫星上,Eagle-Picher的电池成功发射到太空,为卫星的运行提供了稳定的电源。这一里程碑式的事件标志着Eagle-Picher的电池技术在太空探索领域的应用达到了新的高度,也为公司赢得了更多的科研和商业机会。

Etron公司的发展小趣事

1991年,台湾的电子行业正蓬勃发展,钰创科技(Etron)在这一时期应运而生,创始人凭借对市场敏锐的洞察力,决定专注于利基型缓冲记忆体产品与系统晶片的设计与生产。初创时期,公司面临着技术、资金和市场等多重挑战。然而,钰创科技凭借其团队的技术实力和创新精神,成功开发出了一系列具有竞争力的产品,逐渐在市场上崭露头角。

成都芯进(CrossChip)公司的发展小趣事

成都芯进电子一直致力于打破国外芯片市场的垄断地位,实现进口替代。他们在电流传感器领域取得了显著成果,产品已经全面进入工控、光伏、储能等领域,并获得了阳光电源、英威腾、欣旺达、安克等客户的认可。这一成就不仅展示了公司的技术实力和市场竞争力,也为国产芯片事业的发展做出了积极贡献。

Global Power Technology Co., Ltd公司的发展小趣事
首先拔掉电源插头,确保安全;然后取出冰箱内的食物和储物盒,用温水和中性洗涤剂清洗冰箱内部和外部;最后用干净的布擦干冰箱,确保没有残留水分。
Fullywell Semiconductor Co Ltd公司的发展小趣事

为了进一步拓宽业务范围和提升技术实力,Fullywell在2015年进行了一次重要的收购。公司成功收购了某家专注于传感器技术的初创企业,将其先进的技术和产品线纳入麾下。这次收购不仅丰富了Fullywell的产品线,还使其在物联网、智能家居等新兴领域具备了更强的竞争力。随后,公司进行了业务整合,优化了资源配置,实现了优势互补,为公司的持续发展注入了新的动力。

问答坊 | AI 解惑

[汽车电子]全球定位系统信号接收机射频模块的设计

 1 引言      典型的GPS接收机主要由4部分组成:天线、射频前端、相关器和导航解算部分。其中,天线主要负责信号的接收;射频前端负责信号的下变频,在当前的数字化接收机中还包括A/D转换,它是所有后端处理的 ...…

查看全部问答>

传感器网络展望

任何一个传感器网络所承载的数据量将随着网络设备复杂性的增加而增加。低档设备只能传递1bit增量的数据,指示简单的开、关状态。而高档的传感器不仅本身智能化,同时可以传送以字节计量的复杂数据类型。许多面向bit的工业网络如ASI、DeviceNet、 In ...…

查看全部问答>

这个芯片的型号是什么

一个热释电红外感应电路,谁知道这个电路里用的IC型号是什么? …

查看全部问答>

[活动] 2009 NI 前沿技术论坛

尊敬的工程师: 感谢您对NI长期以来的支持,2009第五届NI测控前沿技术论坛即将拉开帷幕。 作为广受好评的年度盛会,您不仅可以通过资深工程师的讲解了解最新前沿技术,还可以亲自投票选择自己感兴趣的专题内容。 NI诚邀您参与第五届测控前 ...…

查看全部问答>

转贴:电子企业招聘试题

电子企业招聘笔试面试题目 一、模拟电路 1、基尔霍夫定理的内容是什么?(仕兰微电子) 基尔霍夫电流定律是一个电荷守恒定律,即在一个电路中流入一个节点的电荷与流出同一个节点的电荷相等.基尔霍夫电压定律是一个能量守恒定律,即在一个回路中回 ...…

查看全部问答>

提问幼稚问题:sql ce 20数据库建立同步时,是不是建立一次让本地数据库与分发远程数据库的连接就可以?

高人前辈们好!     sql ce 20数据库建立同步时,是不是建立一次让本地数据库与分发远程数据库的连接就可以?     就比如在程序初始化的时候,让本地的数据库和远程数据库建立合并复制关系,以后就再也不用管它,它将会自动 ...…

查看全部问答>

DDR2匹配电阻

最近在用EP3C25324做设计,第一次用所以请各位大侠帮忙。问题:外接DDR2 SDRAM,DDR2的信号线不接串、并联匹配电阻可以不?因为接上电阻实在太复杂了,不好布线呀。  在线等答案,谢谢! [ 本帖最后由 lan54160 于 2011-7-22 13:26 编辑 ]…

查看全部问答>

例子应当恰当

       学习UC/OS很长的一段时间了,可是还是不能够写程序,就像写作文一样,不知道从何下手。反而觉得前后台的程序比较的容易懂,而多任务的转来拐去的任务,真不知道如何写!看他人的例程,好像多是两个任务,一个 ...…

查看全部问答>

急需一个LPC2210 UCOS II KEIL工程模板

急需一个LPC2210 UCOS II  KEIL工程模板,在周立功下的不是嵌入式的模板,并编译也不通过,现在需要一个UCOS II 的模板,谢谢!邮箱:zsj88@126.com…

查看全部问答>