S3C2440中断体系结构:外部中断实验

转自:http://blog.chinaunix.net/uid-22182617-id-399397.html

1 SUBSRCPNDSRCPND表明有哪些中断被触发了

    INTSUMMSKINTMSK寄存器用于屏蔽某些中断

中断触发→SUBSRCPND相应位置1→INTSUBMSK未屏蔽→SRCPND相应位置1→

                                                          ↑ 

                                                      中断触发

→若是FIQ中断:INTMOD相应位置1(同一时间,只能有一位置1)

→INTMSK未屏蔽→INTPND相应位置1(同一时间,只能有一位置1)

3 读取INTPND或INTOFFSET可以确定中断源

4 清除中断的顺序:SUBSRCPND(相应位写1)→SRCPND(相应位写1)→INTPND

5 自己觉得重要的几步:将相应引脚的功能设置为“外部中断”,设置中断触发条件,开启外设自己的屏蔽寄存器(若有)→INTSUBMSK中相应位设为0→FIQ:INTMOD相应位设为1

                                                     →IRQ:PRIORITY设置优先级

→IRQ:INTMSK相应位设为0→CPSR中的I和F位设为0,使能IRQ或FIQ

6 中断控制寄存器

(1)SUBSRCPND中几位若有一位置位,且未被INTSUBMSK屏蔽,则SRCPND中相应有一位置1(多对1的关系)

(2)INTMOD中设为1的为快速中断,设为0的为普通中断

(3)PRIORITY:中断优先级仲裁器6个输入引脚;PRIORITY中三位控制一个中断优先级仲裁器(总共7个),一位为ARB_MODE(仲裁器工作模式位),两位用于控制输入信号的优先级

具体哪位对应哪位:请查看S3C2440官方手册,上面写的很详细

(4)INTOFFSET:INTPND寄存器位[x]置1时,INTOFFSET寄存器的值为x,在清除SRCPND、INTPND时,INTOFFSET自动清除

7 外部中断实验:(实验用板:mini2440,是S3C2440的处理器,再参照原理图即可作相应调整)完整代码:int.tar.gz

(1)head.S

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

@ File:head.S

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

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

  

.extern     main  @引用其它文件中的mian标号

.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, #0xdf       @ 进入系统模式

    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

   

(2)init.c

/*

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

 */

 

#include "s3c24xx.h"

 

/*

 * LED1-4对应GPB5、GPB6、GPB7、GPB8

 */

#define GPB5_out        (1<<(5*2))      // LED1

#define GPB6_out        (1<<(6*2))      // LED2

#define GPB7_out        (1<<(7*2))      // LED3

#define GPB8_out        (1<<(8*2))      // LED4

 

/*

 * K1-K4对应GPG0、GPG3、GPG5、GPG6

 */

#define GPG0_eint      (2<<0)     // K1,EINT8

#define GPG3_eint       (2<<(3*2))      // K2,EINT11

#define GPG5_eint       (2<<(5*2))      // K3,EINT13

#define GPG6_eint       (2<<(6*2))      // K4,EINT14

 

 

/*

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

 */

void disable_watch_dog(void)

{

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

}

 

void init_led(void)

{

    GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;

}

 

/*

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

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

 */

void init_irq( )

{

 

    GPGCON  = GPG0_eint | GPG3_eint |GPG5_eint | GPG6_eint;

 

   //使能EINT8 EINT11 EINT13 EINT14

    EINTMASK&=(~(1<<8)) & (~(1<<11)) & (~(1<<13)) & (~(1<<14));

 

   //EINT8 EINT11 EINT13 EINT14中断优先级一样,无需设置

 

    // EINT8、EINT11、EINT13、EINT14使能

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

}

(3)interrupt.c

#include "s3c24xx.h"

 

void EINT_Handle()

{

    unsigned long oft = INTOFFSET;

    unsigned long val;

   

    if( oft==5)

        {  

            GPBDAT |= (0x0f<<5);   // 所有LED熄灭

           

            // 需要进一步判断是K1还是K2,或是K1、K2被同时按下

            val = EINTPEND;

            if (val & (1<<8))

                GPBDAT &= ~(1<<5);      // K1被按下,LED1点亮

            if (val & (1<<11))

                GPBDAT &= ~(1<<6);      // K2被按下,LED2点亮

         if (val & (1<<13))

                GPBDAT &= ~(1<<7);      // K3被按下,LED3点亮

            if (val & (1<<14))

                GPBDAT &= ~(1<<8);      // K4被按下,LED4点亮

        }       

 

    //清中断

    if( oft == 5 )

    EINTPEND = (1<<8) | (1<<11)| (1<<13)| (1<<14);   // EINT8_23合用IRQ5

    SRCPND = 1<<oft;

    INTPND = 1<<oft;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值