zoukankan      html  css  js  c++  java
  • S5PV210中断体系

    第一节 关于S5PV210的中断体系结构
    S5PV210的中断控制器是由4个向量中断控制器(VIC)、ARM PrimeCell PL192 和 4个 TrustZone Interrupt Controller (TZIC)共同组成。 S5PV210共支持93个中断源,待会我们将使能其中的一个外部中断,让大家了解中断处理的完整过程。
    第二节 程序相关讲解
    完整代码见目录详细代码下载链接。
    1. start.S
    共4个步骤,其中第2、4步和中断相关:
    第一步 清bss;
    第二步 开中断,设置CPSR 寄存器,允许中断发生,代码如下:
    mov r0, #0x53      
    msr CPSR_cxsf, r0
    第三步 跳转到main;
    第四步 中断处理;程序正常执行时,只会运行到第三步就跳转到main而不会执行该部分代码。当有中断发生时,PC才会跳转到该部分代码,进行中断相关的处理。别急,后面会详细解释该段代码。
    2. main.c
    共4个步骤,其中第2、3、4步和中断相关:
    第一步 初始化串口;
    第二步 中断相关初始化,调用了system_initexception();

    代码如下:
    void system_initexception( void)
    {
    // 设置中断向量表
    pExceptionUNDEF = (unsigned long)exceptionundef;
    pExceptionSWI = (unsigned long)exceptionswi;
    pExceptionPABORT = (unsigned long)exceptionpabort;
    pExceptionDABORT = (unsigned long)exceptiondabort;
    pExceptionIRQ = (unsigned long)IRQ_handle;
    pExceptionFIQ = (unsigned long)IRQ_handle;
    // 初始化中断控制器
    intc_init();
    }
    这段代码主要做了下面两件事:
    1) 设置中断向量表
    当发生各种异常时,PC会自动跳转到相应的异常向量;S5PV210的异常向量表的起始地址是0xD0037400,我们需要特别注意的是,当发生IRQ中断异常时,对应的处理函数是IRQ_handle(),即我们在start.S中第四步所设置的代码如下:
    IRQ_handle:
    // 设置中断模式的栈
    ldr sp, =0xD0037F80
    // 保存现场
    sub lr, lr, #4
    stmfd sp!, {r0-r12, lr}
    // 跳转到中断处理函数
    bl irq_handler
    // 恢复现场
    ldmfd sp!, {r0-r12, PC}
    注释已经写得很清楚了,当发生IRQ中断异常时,会根据中断向量表里的设置,跳转到该部分代码,然后设置中断模式下的栈,保存现场,再调用中断处理函数irq_handler(),处理完中断后再恢复现场。irq_handler()里会怎么做,后面再解释。
    2) 初始化中断控制器
    调用了函数intc_init(),其代码如下: 

    void intc_init(void)
    {
    // 禁止所有中断
    VIC0INTENCLEAR = 0xffffffff;
    VIC1INTENCLEAR = 0xffffffff;
    VIC2INTENCLEAR = 0xffffffff;
    VIC3INTENCLEAR = 0xffffffff;
    // 选择中断类型为IRQ
    VIC0INTSELECT = 0x0;
    VIC1INTSELECT = 0x0;
    VIC2INTSELECT = 0x0;
    VIC3INTSELECT = 0x0;
    // 清VICxADDR
    intc_clearvectaddr();
    }

    首先先禁止所有中断,然后选择中断类型为IRQ,最后清寄存器VICxARRD,VICxADDr是用来保存当前发生的中断的处理函数的
    第三步 设置外部中断相关寄存器
    代码如下: 

    // 1111 = EXT_INT[16]
    GPH2CON |= 0xF;
    // 010 = Falling edge triggered
    EXT_INT_2_CON |= 1<<1;
    // unmasked
    EXT_INT_2_MASK &= ~(1<<0);

    首先配置GPH2_0引脚为中断功能; 然后设置外部中断EINT16_31为下降沿触发;

    image 

    最后是不屏蔽该中断;

    image
    第四步 设置VIC相关寄存器
    代码如下:

    // 设置中断EINT16_31的处理函数
    intc_setvectaddr(NUM_EINT16_31, isr_key);
    // 使能中断EINT16_31
    intc_enable(NUM_EINT16_31);
    这里调用了两个函数:
    1) intc_setvectaddr()
    它的作用是设置VICVECTADDR这一类寄存器,作用是保存各个中断的处理函数,这里我们的外部中断EINT16_31的中断处理函数是isr_key()。

    image

    前面提到,在start.S的第四步中,会调用函数irq_handler(),其代码如下:

    void irq_handler(void)
    {
    unsigned long vicaddr[4] = {VIC0ADDR,VIC1ADDR,VIC2ADDR,VIC3ADDR};
    int i=0;
    void (*isr)(void);
    for(; i<4; i++)
    {
    if(intc_getvicirqstatus(i) != 0)
    { isr = vicaddr[i]; break; }
    }
    (*isr)();
    }

    当有中断发生时,硬件上会将当前中断的中断处理函数从寄存器VICVECTADDR自动拷贝到寄存器VICDDR中,所以我们在irq_handler()函数里会调用保存在寄存器VICDDR里的中断处理函数即可。 再来看看外部中断EINT16_31的处理函数isr_key(),代码如下:

    void isr_key(void)
    {
    printf("we get company ");
    beep();
    // clear VIC0ADDR intc_clearvectaddr();
    // clear pending
    bit EXT_INT_2_PEND |= 1<<0;
    }
    首先打印一句"we get company",然后蜂鸣器会响一下,最后是清VIC相关寄存器VIC0ADDR和外部中断相关寄存器EXT_INT_2_PEND。
    2) intc_enable()
    在VIC里通过设置寄存器VICINTENABLE使能外部中断EINT16_31。
    image

    第五步 死循环
    打印数字1、2、3、4…,等待外部中断EINT16_31的发生。
    第三节 实验现象
    首先会不断的打印数字1、2、3、4...,当我们按下KEY1时会产生外部中断EINT16_31时,会跳转到IRQ_handler,然后调用irq_handler(),最后调用对应的中断处理函数isr_key()。该函数首先打印"we get company:EINT16_31",然后清中断。

    详细代码下载链接:http://download.csdn.net/detail/klcf0220/5741305

  • 相关阅读:
    linux命令之------Linux文档编辑
    linux命令之------Linux文件系统具体目录
    linux命令之------快捷键说明
    linux命令之------Tar解压缩
    CentOS7如何关闭防火墙
    centos7中运行ifconfig提示-bash: ifconfig: command not found
    System.getProperty、PropConfig.loadConfig应用
    Java高并发syncronized深入理解
    json的工具以及浏览器排序问题
    Mockito: InvalidUseOfMatchersException
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3185705.html
Copyright © 2011-2022 走看看