linux学习(5)中断过程

来源:互联网 发布:未播先火的网络剧 编辑:程序博客网 时间:2024/06/01 16:25

1、ARM状态下各状态使用的寄存器


2、CPSR中各位的意义



3、中断操作过程

1、中断控制器汇集各类外设发出的中断信号,告诉CPU
2、CPU保存当前程序运行环境,调用ISR处理中断
3、在ISR中通过读取中断控制器,外设的相关寄存器来识别这是哪个中断,并进行相应的处理
4、清中断:通过读写中断控制器和外设的相关寄存器来完成
5、恢复之前运行环境

4、按键中断 代码详解

  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       @ 进入中断模式   1110010(中断模式)   CPSR的 I,F位置1,关中断
    ldr sp, =3072           @ 设置中断模式栈指针


    msr cpsr_c, #0xd3       @ 进入管理模式 1110011
    ldr sp, =4096           @ 设置管理模式栈指针,
                            @ 其实复位之后,CPU就处于管理模式,
                            @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略


    bl  init_led            @ 初始化LED的GPIO管脚
    bl  init_irq            @ 调用中断初始化函数,在init.c中,将三个按键的引脚都设置为中断引脚,同时是能中断
    msr cpsr_c, #0x53       @ 设置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
    

发生中断
进入中断模式,进入中断栈  sp=3072,进入0X18处,即HandleIRQ,然后调用处理函数EINT_Handle (先分辨中断,然后处理中断,最后清除)

#include "s3c24xx.h"


void EINT_Handle()
{
    unsigned long oft = INTOFFSET;
    unsigned long val;
    
    switch( oft )
    {
        // S2被按下
        case 0: 
        {   
            GPFDAT |= (0x7<<4);   // 所有LED熄灭
            GPFDAT &= ~(1<<4);      // LED1点亮
            break;
        }
        
        // S3被按下
        case 2:
        {   
            GPFDAT |= (0x7<<4);   // 所有LED熄灭
            GPFDAT &= ~(1<<5);      // LED2点亮
            break;
        }


        // K4被按下
        case 5:
        {   
            GPFDAT |= (0x7<<4);   // 所有LED熄灭
            GPFDAT &= ~(1<<6);      // LED4点亮                
            break;
        }


        default:
            break;
    }


    //清中断
    if( oft == 5 ) 
        EINTPEND = (1<<11);   // EINT8_23合用IRQ5
    SRCPND = 1<<oft;
    INTPND = 1<<oft; // 清除中断

}



main 函数

int main()
{
    while(1);
    return 0;
}

0 0
原创粉丝点击