通过 按键 学习 中断

中断处理流程深度剖析

中断概念:
CPU在工作的过程中,经常需要与外设进行交互,交互的方式包括“轮询方式”,“中断方式”。
1、轮询方式:
CPU不断地查询设备的状态。该方式实现比较简单,但CPU利用率很低,不适合多任务的系统。
2、中断方式:
CPU在告知硬件开始一项工作后,CPU就去做别的事去了,当硬件完成了该项工作后,向CPU发送一个信号,告知CPU它已经完成了这项工作。

中断生命周期:
这里写图片描述

中断源:
在中断的生命周期中,中断源的作用是负责产生中断信号。
S3C2440支持60个中断源;
S3C6410支持64个中断源;
S5PV210支持93个中断源;

中断处理:
非向量方式(2440开发板)
这里写图片描述

向量方式(6410和210开发板)
这里写图片描述

6410开发板按键中断

总流程:
1、按键初始化,将GPIO端口设置为中断源的方式。
2、初始化中断控制器
3、中断处理程序

1、按键初始化,将GPIO端口设置为中断源的方式
按键电路原理图:
这里写图片描述

这里写图片描述

配置GPIO口的中断功能:
这里写图片描述

代码举例:

#define GPNCON (volatile unsigned long*)0x7f008830

#define GPN0_INTERRUPT (0b10<<(0*2))
#define GPN1_INTERRUPT (0b10<<(1*2))
#define GPN2_INTERRUPT (0b10<<(2*2))
#define GPN3_INTERRUPT (0b10<<(3*2))
#define GPN4_INTERRUPT (0b10<<(4*2))
#define GPN5_INTERRUPT (0b10<<(5*2))

void button_init()//使能6个按键的中断
{
    *(GPNCON) |= GPN0_INTERRUPT;
    *(GPNCON) |= GPN1_INTERRUPT;
    *(GPNCON) |= GPN2_INTERRUPT;
    *(GPNCON) |= GPN3_INTERRUPT;
    *(GPNCON) |= GPN4_INTERRUPT;
    *(GPNCON) |= GPN5_INTERRUPT;
}

2、初始化中断控制器 和 中断处理程序
采用向量方式中断。

注意:需要初始化irq模式下的栈sp指针:

init_stack:
    msr cpsr_c, #0xd2
    ldr sp, =0x53000000    @初始化r13_irq,用于中断
    msr cpsr_c, #0xd3
    ldr sp, =0x54000000    @4是任意指定的内存位置,指向内存64M的位置
    mov pc, lr

代码举例:

/*中断寄存器*/
#define EXT_INT_0_CON    *((volatile unsigned int *)0x7f008900)   
#define EXT_INT_0_MASK   *((volatile unsigned int *)0x7f008920) 
#define EXT_INT_0_PEND   *((volatile unsigned int *)0x7f008924)     

#define VIC0INTENABLE    *((volatile unsigned int *)0x71200010)   

#define EINT0_VECTADDR   *((volatile unsigned int *)0x71200100)  
#define EINT5_VECTADDR   *((volatile unsigned int *)0x71200104)    
#define VIC0ADDRESS      *((volatile unsigned int *)0x71200f00)   
#define VIC1ADDRESS      *((volatile unsigned int *)0x71300f00)

void key1_handle()
{
    //保护现场
    __asm__(    
        "sub lr, lr, #4\n"  
        "stmfd sp!, {r0-r12, lr}\n"       
        : 
        : 
    );

    lightLED();

    /* 清除中断 */
    EXT_INT_0_PEND = ~0x0;  
    VIC0ADDRESS = 0; 
    VIC1ADDRESS = 0; 

    //恢复现场
    __asm__( 
        "ldmfd sp!, {r0-r12, pc}^ \n"       
        : 
        : 
    ); 
}

void key6_handle()
{
    //保护现场
    __asm__(    
        "sub lr, lr, #4\n"  
        "stmfd sp!, {r0-r12, lr}\n"       
        : 
        : 
    );

    offLED();

    /* 清除中断 */
    EXT_INT_0_PEND = ~0x0; 
    VIC0ADDRESS = 0; 
    VIC1ADDRESS = 0;   

    //恢复现场
    __asm__( 
        "ldmfd sp!, {r0-r12, pc}^ \n"       
        : 
        : 
    ); 
}

void init_irq()
{ 
    EXT_INT_0_CON = (0b010)|(0b010<<8);//配置为下降沿触发

    EXT_INT_0_MASK = 0;                //取消屏蔽外部中断 

    VIC0INTENABLE |= (0b1)|(0b10);     //使能外部中断

    //用户按下key时,CPU就会自动的将VIC0VECTADDR0的值赋给
    //VIC0ADDRESS并跳转到这个地址去执行 
    EINT0_VECTADDR = (int)key1_handle;  
    EINT5_VECTADDR = (int)key6_handle;

    //开启总中断
    __asm__(   
        "mrc p15,0,r0,c1,c0,0\n"
        "orr r0,r0,#(1<<24)\n"
        "mcr p15,0,r0,c1,c0,0\n"

        "mrs r0,cpsr\n"
        "bic r0, r0, #0x80\n"
        "msr cpsr_c, r0\n"            
        : 
        : 
    );
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值