s3c2440中断控制器操作

发布者:素心静听最新更新时间:2021-09-03 来源: eefocus关键字:s3c2440  中断控制器  工作模式 手机看文章 扫描二维码
随时随地手机看文章

一、ARM中断体系结构

arm有7中异常工作模式


用户模式、快中断模式、管理模式、数据访问终止模式、中断模式、系统模式、未定义指令终止模式。

几种模式有什么不同呢,

1、不同的寄存器

2、不同的权限

3、触发条件


对于不同的寄存器,ARM920T有31个通用的32位寄存器和6个程序状态寄存器。这37个寄存器分为7组,进入某个工作模式时就使用他那组的寄存器。有些寄存器,不同的工作模式下有他的副本,当切换到另一个工作模式时,那个工作模式的寄存器副本将被使用:这些寄存器被称为备份寄存器(图中灰色部分的寄存器)

在ARM状态下,每种工作模式都有16个通用的寄存器和一个(或两个,这取决于不同的工作模式)程序状态寄存器。图中R0-R15可以直接访问,这些寄存器除了R15外都是通用寄存器,即他们既可以保存数据又可以保存地址。另外R13-R15稍有特殊。R13是栈指针寄存器,通常被用来保存栈指针。14被称为程序连接寄存器,当执行BL子程序调用指令时,R14中得到R15(程序计数器PC)的备份。而当发生中断或异常时,对应的R14_svc、R14_irq、R14_fiq、R14_abt、R14_und中保存R15的返回值。


快速中断模式有7个备份寄存器R8-R14,这使得进入快速中断模式执行很大部分程序时,只要不改变R0-R7,不用保存任何寄存器。七种工作模式都有自己独占的寄存器副本R13和R14,这使得每个模式都有自己的栈指针寄存器和连接寄存器。

每种工作模式除了R0-R15外,还有第17个寄存器CPSR,即当前程序状态寄存器。CPSR中一些位被用来标识各种状态,一些位被用来标识当前处于什么工作模式。

如图CPSR

CPSR各位的意义:

(1)T位:置位时,CPU处Thumb状态,否则处于ARM状态

(2)中断禁止位:I位和F位属于中断禁止位。他们被置位时IRQ中断和FIQ中断分别被禁止。

(3)工作模式位:标识CPU当前处于什么工作模式。可以编写这些位,使CPU进入指定的工作模式。

除CPSR外,还有快速中断模式、中断模式、管理模式、数据访问终止模式和未定义指令终止魔兽等5中工作模式都有独占的寄存器SPSR,即程序状态保存寄存器。当切换进入这些工作模式时,在SPSR中保存前一个工作模式的CPSR的值,这样,当返回前一个工作模式时,可以将SPSR中的值恢复到CPSR中。


综上所述,当一个异常发生时,将切换进入相应的工作模式,这时ARM920T CPU核将自动完成如下的事情:

(1)、在异常工作模式的连接寄存器R14中保存前一个工作模式的下一条即将执行指令的地址,对于ARM状态,这个值是当前pc值加4或加8。

(2)、将CPSR的值复制到异常模式的SPSR

(3)、将CPSR的工作模式位设置为这个异常模式对应的工作模式。

(4)、令PC值等于这个异常模式在异常向量表的地址。即跳转去执行异常向量表中的相应的指令。

相反地、从异常工作模式退出返回之前的工作模式时,需要通过软件完成以下事情:

(1)、前面进入异常工作模式时,连接寄存器保存了前一工作模式的一个指令地址,将他减去一个适当的值后赋给PC寄存器。

(2)、将SPSR的值复制回CPSR。


CPSR模式位设置如下图:

二、s3c2440的中断控制器


CPU工作的过程中如何知道各类外设发生了某些不预期的事件呢,比如串口接收到了新数据、USB接口插入了设备、按下了某个按键等。主要有两种方法:

(1)是查询方式:程序循环地查询各设备的状态并作出相应的反应。实现比较简单,常用在功能相对单一的系统中,比如在一个温度检测系统对温度的不断检查。缺点是占用CPU资源,不适用于多任务系统。

(2)、中断方式:当某事件发生时,硬件会设置某个寄存器;CPU在每执行完一个指令时,通过硬件查看这个寄存器,如果发现所关注的时

间发生了,则中断当前程序流程,跳转到一个固定的地址处理这件事,最后返回继续执行被中断的程序。他的实现相对复杂,但是效率很高,是常用的方法。


中断体系外设、内部外设与CPU核的硬件框图:

不论何种CPU,中断的处理是相似的。

(1)、中断控制器汇集各类外设发出的中断信号,然后告诉CPU。

(2)、CPU保存当前程序的运行环境,调用中断服务程序来处理这些中断。

(3)、在ISR中通过读取中断控制器,外设的相关寄存器来识别这是哪个中断,并进行相应的处理。

(4)、清楚中断:通过读写中断控制器和外设的相关寄存器来实现。

(5)、最后恢复被中断程序的运行环境(即上面保存的各个寄存器等),继续执行。


对于不同的CPU而言,中断的处理只是细节的不同。


中断处理框图:

从中断控制器结构图看出

SUBSRCPND和SRCPND寄存器表明有哪些中断被触发,正在等待处理;SUBMASK(INTSUBMASK寄存器)和MASK(INTMASK寄存器)用于屏蔽某些中断。

图中的“Request sources(with sub-register)”表示INT_RXD0、INT_TXD0等中断源(这类中断源S3C2440有15个)。他们不同于“Request sources(without sub-register”。


附图s3c2440异常向量表:

综上所述,使用中断的步骤如下:

(1)设置好中断模式和快速中断模式下的栈:当发生中断IRQ时,CPU进入中断模式,这时使用中断模式下的栈;当发生快速中断时,CPU进入快速中断模式,这时使用快速中断模式下的栈。

(2)准备好中断处理函数。

a、异常向量:

在异常向量表中设置好进入中断模式或快速中断模式时的跳转函数,他们的异常向量分别是0x00000018、0x0000001c。

b、中断服务程序(ISR)

IRQ、FIQ的跳转函数,具体将调用具体中断的服务函数、



对于IRQ,读取INTPND寄存器或INTOFFSET寄存器的值来判断中断源,然后分别处理。

对FIQ,由于只有一个中断可以设为FIQ,无需判断中断源。



c、清除中断:如果不清除中断,则CPU会误以为这个中断又一次发生。



清除中断时从源头开始:首先,需要的话,操作具体外设清除中断信号,比如EINTPEND;其次,清除SUBSRCPND(用到的话)、SRCPND寄存器中的相应的位;最后清除INTPND寄存器中相应的位。

(3)、进入、退出中断模式或快速中断模式时,需要保存、恢复被中断程序的运行环境。

(4)、根据具体中断设置相关外设,比如GPIO中断,需要将相应的引脚功能设置为外部中断、设置中断触发条件等,一些中断有自己的屏蔽寄存器,还要开启它,比如,GPIO的外设中断,EINTMASK。

(5)、对于“Request sources(without sub-register)”的中断,将INTSUBMASK寄存器中相应的位设为0.

(6)、确定使用中断的方式:FIQ或IRQ

a、如果是FIQ,则在INTMOD寄存器中设置相应位为1

b、如果是IRQ,则在RIORITY寄存器中设置优先级

(7)、如果是IRQ,将INTMAK寄存器中相应的位设为0(FIQ不受INITMSK寄存器的控制)。

(8)、设置CPSR寄存器中的I位(对于IRQ)或F位(对于FIQ)为0,使能IRQ或FIQ、



在s3c2440中中断控制器相关的8个寄存器:



1、SUBSRCPND

SUBSRCPND被用来标识INT_RXD0、INT_TXD0等中断是否已经发生,每位对应一个中断。当这些中断发生且没有被INTSUBMSK寄存器屏蔽,则他们的若干位将汇集出现在SRCPND寄存器的一位上,比如、只要INT_RXD0、INT_TXD0或INT_ERR0一个发生且没有被屏蔽,则SRCPND寄存器INT_UART0位被置1.

要清除中断时,往SUBSRCPND中相应的位写1


2、INTSUBMSK

用来屏蔽SUBSRCPND寄存器所标识的中断

3、SRCPND

SRCPND寄存器每一位用来标识一个或一类中断是否已经发生,清除中断时与SUBSRCPND类似。

4、INTMSK

INTMSK寄存器用来屏蔽SRCPND寄存器所标识的中断。

5、INTMOD

当INTMOD寄存器中某位写入1时,它对应的中断被设为FIQ,同一时间里,INTMOD寄存器中只能有一位写入1。

6、PRIORITY

优先级寄存器,有多个中断同时发生时,中断控制器将选出优先级最高的中断源



7、INTPND

经过优先级仲裁器选出优先级最高的中断后,这个中断在INTPND寄存器中相应的位被置1,随后,CPU将进入中断模式处理它。同一时间段里,此寄存器只有一位被置1:在ISR中,可以根据这个位确定是哪个中断。清除中断时,往这个位写1.

8、INTOFFSET寄存器

这个寄存器被用来表示INTPND寄存器中哪个位被置1了,即INTPND寄存器中位【x】位1时,INTOFFSET寄存器的值为x(x为0-31)。

在清除SRCPND、INTPND寄存器时,INTOFFSET寄存器被自动清除。




三、实现按键中断,led灯亮程序


head.S


 


@******************************************************************************

@ File:head.S

@ 功能:初始化,设置中断模式、管理模式的栈,设置好中断处理函数

@******************************************************************************       

   

.extern     main

.text 

.global _start 

_start:

@******************************************************************************       

@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用

@******************************************************************************       

    b   Reset


@ 0x04: 未定义指令中止模式的向量地址

HandleUndef:

    b   HandleUndef 

 

@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式

HandleSWI:

    b   HandleSWI


@ 0x0c: 指令预取终止导致的异常的向量地址

HandlePrefetchAbort:

    b   HandlePrefetchAbort


@ 0x10: 数据访问终止导致的异常的向量地址

HandleDataAbort:

    b   HandleDataAbort


@ 0x14: 保留

HandleNotUsed:

    b   HandleNotUsed


@ 0x18: 中断模式的向量地址

    b   HandleIRQ


@ 0x1c: 快中断模式的向量地址

HandleFIQ:

    b   HandleFIQ


Reset:                  

    ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈

    bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启

    

    msr cpsr_c, #0xd2       @ 进入中断模式

    ldr sp, =3072           @ 设置中断模式栈指针


    msr cpsr_c, #0xd3       @ 进入管理模式

    ldr sp, =4096           @ 设置管理模式栈指针,

                            @ 其实复位之后,CPU就处于管理模式,

                            @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略


    bl  init_led            @ 初始化LED的GPIO管脚

    bl  init_irq            @ 调用中断初始化函数,在init.c中

    msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断

    

    ldr lr, =halt_loop      @ 设置返回地址

    ldr pc, =main           @ 调用main函数

halt_loop:

    b   halt_loop


HandleIRQ:

    sub lr, lr, #4                  @ 计算返回地址

    stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器

                                    @ 注意,此时的sp是中断模式的sp

                                    @ 初始值是上面设置的3072

    

    ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  

    ldr pc, =EINT_Handle            @ 调用中断服务函数,在interrupt.c中

int_return:

    ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr

    


 


init.c


 


/*

 * init.c: 进行一些初始化

 */ 


#include "s3c24xx.h"


/*

 * LED1,LED2,LED4对应GPF4、GPF5、GPF6

 */

#define    GPF4_out    (1<<(4*2))

#define    GPF5_out    (1<<(5*2))

#define    GPF6_out    (1<<(6*2))


#define    GPF4_msk    (3<<(4*2))

#define    GPF5_msk    (3<<(5*2))

#define    GPF6_msk    (3<<(6*2))


/*

 * S2,S3,S4对应GPF0、GPF2、GPG3

 */

#define GPF0_eint     (0x2<<(0*2))

#define GPF2_eint     (0x2<<(2*2))

#define GPG3_eint     (0x2<<(3*2))


#define GPF0_msk    (3<<(0*2))

#define GPF2_msk    (3<<(2*2))

#define GPG3_msk    (3<<(3*2))


/*

 * 关闭WATCHDOG,否则CPU会不断重启

 */

void disable_watch_dog(void)

{

    WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可

}


void init_led(void)

{

    // LED1,LED2,LED4对应的3根引脚设为输出

    GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);

    GPFCON |= GPF4_out | GPF5_out | GPF6_out;

}


/*

 * 初始化GPIO引脚为外部中断

 * GPIO引脚用作外部中断时,默认为低电平触发、IRQ方式(不用设置INTMOD)

 */ 

void init_irq( )

{

    // S2,S3对应的2根引脚设为中断引脚 EINT0,ENT2

    GPFCON &= ~(GPF0_msk | GPF2_msk);

    GPFCON |= GPF0_eint | GPF2_eint;


    // S4对应的引脚设为中断引脚EINT11

    GPGCON &= ~GPG3_msk;

    GPGCON |= GPG3_eint;

    

    // 对于EINT11,需要在EINTMASK寄存器中使能它

    EINTMASK &= ~(1<<11);

        

    /*

     * 设定优先级:

     * ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2

     * 仲裁器1、6无需设置

     * 最终:

     * EINT0 > EINT2 > EINT11即K2 > K3 > K4

     */

    PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;


    // EINT0、EINT2、EINT8_23使能

    INTMSK   &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));

}

s3c2440.h

/* WOTCH DOG register */

#define     WTCON           (*(volatile unsigned long *)0x53000000)


/* SDRAM regisers */

#define     MEM_CTL_BASE    0x48000000

#define     SDRAM_BASE      0x30000000


/* NAND Flash registers */

#define NFCONF              (*(volatile unsigned int  *)0x4e000000)

#define NFCMD               (*(volatile unsigned char *)0x4e000004)

#define NFADDR              (*(volatile unsigned char *)0x4e000008)

#define NFDATA              (*(volatile unsigned char *)0x4e00000c)

#define NFSTAT              (*(volatile unsigned char *)0x4e000010)


/*GPIO registers*/

#define GPBCON              (*(volatile unsigned long *)0x56000010)

[1] [2]
关键字:s3c2440  中断控制器  工作模式 引用地址:s3c2440中断控制器操作

上一篇:一起学mini2440裸机开发(二)--MDK自带的S3C2440.s分析
下一篇:S3C2440中的异常与中断

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved