Mini2440的外部中断编写

一、中断编写总框图

外部中断编写

 

二、分步介绍

1、初始化引脚

#define GPGCON (*(volatile unsigned long *)0x56000060)

image

对照上图将所有引脚设置为【10】变成外部中断功能(以GPG0 GPG3为例)

GPGCON &=  (~(3<<0)) & (~(3<<6));//清除设置位

GPGCON |= (2<<0) | (2<<6);//设置为外部中断功能

2、初始化中断

#define EINTMASK    (*(volatile unsigned long *)0x560000A4)

#define INTMSK         (*(volatile unsigned long *)0x4A000008)

EINTMASK

image

INTMSK

image

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

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

打开总中断:

/*打开总中断*/
__asm__ volatile(
    "mrs r0, cpsr "
    "bic r0, r0,#0x80 "
    /*只写控制位*/
    "msr cpsr_c, r0 "
    :
    :
);

3、进入中断

①保存环境

sub lr, lr,#4  /*保证返回时执行的是下一条命令*/
stmfd sp!, {r0-r12, lr}

②中断处理函数

bl handle_int

③恢复环境

ldmfd sp!, {r0-r12, pc}^ /*恢复环境*/

4、中断处理函数

//宏定义

#define EINTPEND    (*(volatile unsigned long *)0x560000A8)

#define SRCPND      (*(volatile unsigned long *)0x4A000000)

#define INTPND         (*(volatile unsigned long *)0x4A000010)

//处理函数
//判断中断源
unsigned long value = INTOFFSET;
unsigned long value2 = 0;

//根据中断源执行不同的中断处理
switch(value)
{
    case 5: //EXINT8_23
        value2 = EINTPEND & ((1<<8)|(1<<11));
        switch(value2)
        {
            case (1<<EINT8):  //K1
                led2_on();
                break;
            case (1<<EINT11): //K2
                led2_off();
                break;               
            default:
                break;
        }
        //清除EINT8_23中断标志
        EINTPEND = value2;
        break;
       
    default:
        break;
}

//清除中断标志
SRCPND = 1<<value;
INTPND = 1<<value;

5、注意问题

由于使用中断功能,当程序进入中断时,此时系统处于irq模式下,正常情况系统处于svc模式,而两者的r13是不一样的,所以初始化堆栈时需要分别进行初始化

init_stack:
msr cpsr_c, 0xd2
ldr sp, =0x33000000 @irq模式下初始化的是r13_irq
msr cpsr_c, 0xd3
ldr sp, =0x34000000 @svc模式下初始化的是r13_svc
mov pc, lr

博客结尾图

原文地址:https://www.cnblogs.com/TB-Go123/p/5252714.html