精华内容
下载资源
问答
  • 中断处理(中断向量寄存器

    千次阅读 2014-04-08 20:10:45
     /* 在中断控制器里使能这些中断 */  VIC0INTENABLE |= (0x3); /* bit0: eint0~3, bit1: eint4~11 */  VIC0VECTADDR0 = eint0_3_irq;  VIC0VECTADDR1 = eint4_11_irq; } void do_irq(void...


    #define GPNCON     (*((volatile unsigned long *)0x7F008830))
    #define GPNDAT     (*((volatile unsigned long *)0x7F008834))

    #define EINT0CON0  (*((volatile unsigned long *)0x7F008900))
    #define EINT0MASK  (*((volatile unsigned long *)0x7F008920))

    #define EINT0PEND  (*((volatile unsigned long *)0x7F008924))

    #define PRIORITY    (*((volatile unsigned long *)0x7F008280))
    #define SERVICE     (*((volatile unsigned long *)0x7F008284))
    #define SERVICEPEND (*((volatile unsigned long *)0x7F008288))


    #define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))
    #define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))
    #define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))
    #define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))
    #define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))
    #define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))
    #define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))
    #define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))
    #define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))

    #define VIC0VECTADDR0      (*((volatile unsigned long *)0x71200100))
    #define VIC0VECTADDR1      (*((volatile unsigned long *)0x71200104))
    #define VIC0ADDRESS        (*((volatile unsigned long *)0x71200f00))

    void eint0_3_irq(void)                   //分辨组内哪个中断
    {
     int i;
     
     printf("eint0_3_irq\n\r");  /* K1~K4 */
     for (i = 0; i < 4; i ++)
     {
      if (EINT0PEND & (1<<i))
      {
       if (GPNDAT & (1<<i))
       {
        printf("K%d released\n\r", i+1);
       }
       else
       {
        printf("K%d pressed\n\r", i+1);
       }
      }
     }

    }

    void eint4_11_irq(void)
    {
     int i;
     printf("eint4_11_irq\n\r"); /* K5~K6 */
     for (i = 4; i < 6; i ++)
     {
      if (EINT0PEND & (1<<i))
      {
       if (GPNDAT & (1<<i))
       {
        printf("K%d released\n\r", i+1);
       }
       else
       {
        printf("K%d pressed\n\r", i+1);
       }
      }
     }

    }


    void irq_init(void)
    {
     /* 配置GPIO引脚为中断引脚 */
     /* GPN0~5 设为中断引脚 */
     GPNCON &= ~(0xfff);
     GPNCON |= 0xaaa;

     /* 设置中断触发方式为: 双边沿触发 */
     EINT0CON0 &= ~(0xfff);
     EINT0CON0 |= 0x777;

     /* 使能中断 */
     EINT0MASK &= ~(0x3f);

     /* 在中断控制器里使能这些中断 */
     VIC0INTENABLE |= (0x3); /* bit0: eint0~3, bit1: eint4~11 */

     VIC0VECTADDR0 = eint0_3_irq;
     VIC0VECTADDR1 = eint4_11_irq;


    }


    void do_irq(void)
    {
     int i = 0;

     void (*the_isr)(void);

     the_isr = VIC0ADDRESS;             //分辨哪个组中断
      
     /* 2.1 分辨是哪个中断 */
     /* 2.2 调用它的处理函数 */ 
     /* 2.3 清中断 */ 

     the_isr();
     
     EINT0PEND   = 0x3f;  /* 清中断 */
     VIC0ADDRESS = 0;
    }


     

    展开全文
  •  前面我们的按键程序已经能工作了,但是有一个缺点,就是它在中断处理函数里是一个一个判断中断的(虽然用了循环),如果有一天我们程序中有好多好多中断,比如触摸屏中断,按键中断,UART中断等等。我们难道要一个...

    【说明】

                  前面我们的按键程序已经能工作了,但是有一个缺点。我们发现中断有64组,那就假设我们这64组全用了,当发生中断的时候,我们需要用64个IF 语句来判别到底是哪个中断组发生了,麻烦不说,还浪费时间,那有什么办法改进吗?有!6410中断控制器有个机制叫“中断向量寄存器” 

     

    【中断控制器】

                  

                 1)6410有2个中断控制器,每个有31组中断,上图是0-31组的示意图

                 2)每一组有一个寄存器,里面可以存放该组对应的中断处理函数

                 3)当发生中断的时候,对应组的寄存器值会自动复制到VICxADDRESS,X指对应的控制器,比如第30组就复制给VIC0ADDRESS,32组个给VIC1ADDRESS

                 4)我们在初始化中断的时候就初始化对应组寄存器的处理函数,当发生中断时,软件上我们判断VICxADDRESS是不是为0,如果不是就调用它

                 5)调用完后我们将VICxADDRESS清为0,防止后续的中断处理出错。

                 6)这样就不需要判别是哪组放生了中断,很方便,但是由于一组中断又分为好多中断源,所以在某一组中断处理函数中还是需要简单得判别一下。

     

     

    【源代码】

                 

    #include "stdio.h"
    #define GPNCON     (*((volatile unsigned long *)0x7F008830))
    #define GPNDAT     (*((volatile unsigned long *)0x7F008834))
    #define EINT0CON0  (*((volatile unsigned long *)0x7F008900))
    #define EINT0MASK  (*((volatile unsigned long *)0x7F008920))
    #define EINT0PEND  (*((volatile unsigned long *)0x7F008924))
    #define PRIORITY    (*((volatile unsigned long *)0x7F008280))
    #define SERVICE     (*((volatile unsigned long *)0x7F008284))
    #define SERVICEPEND (*((volatile unsigned long *)0x7F008288))
    #define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))
    #define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))
    #define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))
    #define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))
    #define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))
    #define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))
    #define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))
    #define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))
    #define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))
    
    #define VIC0VECTADDR0      (*((volatile unsigned long *)0x71200100))
    #define VIC0VECTADDR1      (*((volatile unsigned long *)0x71200104))
    #define VIC0ADDRESS        (*((volatile unsigned long *)0x71200f00))
    
    void eint0_3_irq(void)
    {
            int i;
    
            printf("eint0_3_irq\n\r");  /* K1~K4 */
            for (i = 0; i < 4; i ++)
            {
                    if (EINT0PEND & (1<<i))
                    {
                            if (GPNDAT & (1<<i))
                            {
                                    printf("K%d released\n\r", i+1);
                            }
                            else
                            {
                                    printf("K%d pressed\n\r", i+1);
                            }
                    }
            }
    
    }
    
    void eint4_11_irq(void)
    {
            int i;
            printf("eint4_11_irq\n\r"); /* K5~K6 */
            for (i = 4; i < 6; i ++)
            {
                    if (EINT0PEND & (1<<i))
                    {
                            if (GPNDAT & (1<<i))
                            {
                                    printf("K%d released\n\r", i+1);
                            }
                            else
                            {
                                    printf("K%d pressed\n\r", i+1);
                            }
                    }
            }
    
    }
    
    
    void irq_init(void)
    {
            /* 配置GPN0~5引脚为中断功能 */
            GPNCON &= ~(0xfff);
            GPNCON |= 0xaaa;
    
            /* 设置中断触发方式为: 双边沿触发 */
            EINT0CON0 &= ~(0xfff);
            EINT0CON0 |= 0x777;
    
            /* 禁止屏蔽中断 */
            EINT0MASK &= ~(0x3f);
    
            /* 在中断控制器里使能这些中断 */
            VIC0INTENABLE |= (0x3); /* bit0: eint0~3, bit1: eint4~11 */ 
    
            // 设置中断处理函数
            VIC0VECTADDR0 = (unsigned long)eint0_3_irq;
            VIC0VECTADDR1 = (unsigned long)eint4_11_irq;
    
    }
    
    
    void do_irq(void)
    {
            void (*the_isr)(void);
    
            // 读VICxADDRESS寄存器获得目前正在发生的中断的处理函数
            the_isr = VIC0ADDRESS;
    
            // 调用中断处理函数
            the_isr();
    
            // 清中断
            EINT0PEND   = 0x3f;
            VIC0ADDRESS = 0;
    }
    


     

    展开全文
  • 中断向量控制器和中断处理的主要寄存器 --参考朱有鹏ARM裸机 1、异常处理的2个阶段 可以将异常处理分为2个阶段来理解,第一阶段是异常向量表跳转 第二阶段就是进入了真正的异常处理程序irq_handler之后的部分。 ...

    中断向量控制器和中断处理的主要寄存器

    --参考朱有鹏ARM裸机

    1、异常处理的2个阶段

    可以将异常处理分为2个阶段来理解,第一阶段是异常向量表跳转

    第二阶段就是进入了真正的异常处理程序irq_handler之后的部分。


    2、中断处理的第一阶段处理

    (1)第一个阶段之所以能够进行,主要依赖于CPU设计的提供的异常向量表机制

    第一阶段的主要任务是从异常发生到响应异常并且保存、恢复现场,

    跳转到真正的异常处理程序处。

    (2)第二阶段的目的是识别多个中断源中究竟哪一个发生了中断,

    然后调用相应的中断处理程序来处理这个中断。


    3、S3C2440的第二阶段的处理过程

    (1)第一个问题:怎么找到具体是哪个中断:S3C2440的中断控制器中有一个寄存器

    寄存器的每一位对应一个中断源(那么一个寄存器应该对应于32个中断源)

    但是S3C2440中中断源不止32个,所以2440里面又弄了一个子中断寄存器。

    (2)怎么找到对应的ISR函数的问题?

    首先给每个中断做了一个编号,进入ISR_handler之后先通过查询中断控制器和

    相应 的子中断寄存器确定是什么中断源。

    然后用这个编号去ISR数组(ISR数组是中断初始化事先设定好的)

    就是把各个中断的ISR的函数名组成一个数组,用中断对应的编号作为索引来查询这个数组


    4、S5PV210的第二阶段处理过程

    (1)第一个问题,怎么找到具体是哪一个中断:S5PV210中支持的中断源很多,所以

    直接设计了4个中断寄存器,每个32位,每位对应于一个中断源。

    (理论上210最多支持128个中断源)

    210没有子中断源,每个中断都是并列的,当中断发生时,轮询的查找是哪个中断源寄存器

    ,看哪一位被置1,则这个位对应的寄存器就发生了中断,即找到了中断编号。


    (2)第二个问题:怎么找到对应的ISR问题

    210支持的中断很多,如果还是使用2440的中断函数数组的话,查找起来非常的花

    时间。于是210开拓了一种全新的寻找ISR的机制。

    210提供了很多寄存器来解决每个中断源对应ISR寻找问题,

    实现的效果就是,当发生了相应的中断,硬件会自动的将相应的ISR推入一定的寄存器中,

    我们软件只要去这个寄存器中执行函数就可以了。


    5、S5PV210的中断处理的主要寄存器

    5.1、VICnINTENABLE和VICnINTENCLEAR

    (1)VICnINTENABLE   这是中断的使能的寄存器,在你想要的中断源置位即可,

    VICnINTENCLEAR这个寄存器置1的话,就代表该中断不使能。

    5.2、VICnINTSELECT

    (1)设置各个中断的模式为IRQ还是FIQ,一般都设置成IRQ

    (2)IRQ和FIQ究竟有什么区别:210中支持2种中断,IRQ是普通中断,FIQ是快速中断。

    (3)FIQ比IRQ快的地方是在:第一:FIQ有专用的r8-r12,因此在FIQ的ISR中可以直接使用r8-r12

    而不用保存,这就能节省时间,

    第二:异常向量表FIQ是在最后面,所以中断服务程序就可以直接写在FIQ中断服务入口处。

    减少跳转的时间。


    5.3、VICnIRQSTATUS和VICnFIQSTATUS

    (1)中断状态寄存器,是只读的,当发生中断的时候,该位会置1,表示发生了中断。

    当我们执行完中断服务函数的时候,就是靠这个处理中断的第二阶段的第一阶段,

    就是靠查询这个寄存器来得到中断编号。


    5.4、VICnVECTPRIORITY0~VICnVECTPRIORITY31

    中断的优先级的寄存器,可以通过这个寄存器设置中断的优先级,实现中断嵌套。


    5.5、VICnVECTADDR0~VICnVECTADDR31、VICnADDR


    (1)这三个寄存器和210中断处理第二阶段的第二阶段有关。
    (2)VICnVECTADDR0到31这32个寄存器分别用来存放真正的各个中断对应的isr的函数地址。相当于每一个中断源都有一个VECTADDR寄存器,程序员在设置中断的时候,把这个中断的isr地址直接放入这个中断对应的VECTADDR寄存器即可。
    (3)VICnADDR这个寄存器是只需要读的,它里面的内容是由硬件自动设置的。当发生了相应中断时,硬件会自动识别中断编号,并且会自动找到这个中断的VECTADDR寄存器,然后将其读出复制到VICnADDR中,供我们使用。这样的设计避免了软件查找中断源和isr,节省了时间,提高了210的中断响应速度。


    总结:

    整个中断的流程分析:

    第一部分:我们为中断响应而坐的预备工作:

    1、初始化中断控制器

    2、绑定写好的ISR到中断控制器

    3、相应中断的所有条件使能

    第二部分:当硬件产生中断后如何自动执行ISR

    1、经过异常向量表跳转到IRQ、FIQ的入口

    2、做中断现场保护(start.s),然后跳入ISR_handler

    3、在ISR_handler中确定是哪一个中断,然后直接去这个VIC的ADDR

    寄存器中取ISR来执行即可。

    4、ISR执行完,中断现场恢复,直接返回继续做常规任务。













    展开全文
  • R8—R12,除快中断有自己寄存器(Rx_fiq),其他模式共用,共10个。 R13,栈指针寄存器。用户、系统共用外,其他模式有独立寄存器,共6个。 R14,连接寄存器。当程序跳转(BL)、异常模式时,用于保存当前PC值。同上,...

              ARM7内核寄存器分布

    ARM7TDMI-S内核共37个寄存器。

    R0R7,通用寄存器,共8个。

    R8R12,除快中断有自己寄存器(Rx_fiq),其他模式共用,共10个。

    R13,栈指针寄存器。用户、系统共用外,其他模式有独立寄存器,共6个。

    R14,连接寄存器。当程序跳转(BL)、异常模式时,用于保存当前PC值。同上,共6个。

    R15,程序计数寄存器,所有模式共用,1个。

    CPSR,程序状态寄存器,同上,1个。

    SPSR,程序状态保存寄存器,用户、系统模式没有。其他模式各自独立。进入异常模式时,用于保存用户、系统模式的CPSR。共5个。

    以上为ARM7内核中的37个寄存器。

    CPSR位分布

    ARM7LPC2000系列,中断向量控制器。

    ARM内核本身只有FRQIRQ2条中断输入信号线。为了扩展中断源,ARM7采用中断向量控制器管理中断源,从而扩展出来了32个中断请求输入。中断向量控制器属于内核外设!

    CPUIRQFIQ中断由CPSR67位控制,1禁止,0使能。

    中断分类,FIQ、向量IRQ、非向量IRQ,优先级依次降低。

    FIQ一般只分配一个,不建议分配两个以上。

    ②向量IRQ最多可分配16个相爱难过来那个IRQ中断。

    ③非向量IRQ中断只有一个。

    基于VIC的每一个中断都有一个VIC通道号。LPC2000系列不足32个中断。

    模块

    标志

    VIC通道号

    WTD

    看门狗

    0

    ——

    (保留给软件)

    1

    ARM内核

    EmbeddedICERx

    2

    ARM内核

    EmbeddedICETx

    3

    Timer0

    匹配、捕获

    4

    Timer1

    匹配、捕获

    5

    UART0

    6

    UART1

    7

    PWM0

    8

    I²C0

    SI(状态改变)

    9

    SPI0

    10

    SPI1

    11

    PLL

    PLL锁定(PLOCK)

    12

    RTC

    计数器增加

    13

        系统控制

    EINT0

    14

    EINT1

    15

    EINT2

    16

    EINT3

    17

    A/D0

    18

    I²C1

    SI(状态改变)

    19

    BOD

    掉电检测

    20

    VIC用若干寄存器配置管理32个中断源

    一,VIC控制配置寄存器

    中断选择寄存器            VICIntSelect

    中断使能寄存器            VICIntEnable

    中断使能清零寄存器        VICIntEnclr

    三个寄存器的32位对应相应32中断源,实现32个中断的配置。

    VICIntSelect      相应位置 相应中断分配 FIQ中断,置 分配 IRQ中断

    VICIntEnable     相应位置 使能分配的相应的中断,置 无效

    VICIntEnClr      相应位置 禁止分配的相应的中断,置 无效

    二,VIC地址寄存器

    向量地址寄存器          VICVectAddr     保存向量IRQ中断地址

    默认向量地址寄存器      VICDefVectAddr  保存非向量IRQ中断地址      

    向量地址寄存器015     VICVectAddr X   保存向量IRQ中断地址

    向量控制寄存器015     VICVectCntl X

    VICVectCntl X相应位描述

    31:6

    5

    4:0

    功能

    保留

    向量IRQ使能

    分配给该向量IRQ通道的中断请求或软件中断的编号

    VICVectCntl X   bit5  1使能中断,置0并不会禁止中断本身,中断只是变为分享量的形式ARM7硬件不支持中断嵌套。

    向量IRQ通道有01516个,优先级依次降低。

    VICVectCntl X    4:0 bit 存放  中断通道号(基于VIC的编号032),中断编号放入较高向量IRQ通道控制寄存器,该中断就是向量IRQ中断中优先级较高的!

    例如:VICVectCntl0 = 0x20 | 4;         定时器0分配为向量IRQ通道0

    三,状态寄存器

    IRQ状态寄存器  VICIRQStatus  读取得到分配并使能为IRQ的中断状态

    FIQ状态寄存器  VICFIQStatus  读取得到分配并使能为FIQ的中断状态

    所有中断状态寄存器 VICRawIntr 读取得到所有中断状态

    以上寄存器位分配,对应VIC通道号

    读取,某位是 则代表该中断激活。

    转载于:https://www.cnblogs.com/qianggezhishen/p/7349480.html

    展开全文
  • C66x DSP运行中断的简要流程: 1、使能了全局中断和子中断。假设硬件检測到中断发生,...3、CPU的PC指针读出中断向量表的地址,也就是把“ISTP寄存器的ISTB值+子中断向量偏移量”装入PC寄存器,这样就运行跳转。 ...
  • 在做stm32 iap升级固件的时候通常需要多份中断向量表。比如bootloader的中断向量表在0x00000000位置,应用程序...VTOR是arm内核的一个寄存器,叫做中断向量偏移量寄存器。当系统上电启动的时候CPU会从先找到中断向量...
  • 最后,通过设置中断控制寄存器,设计外部中断EINT3的初始化程序,并给出主程序流程图。实践证明程序运行稳定可靠。引言计算机体系结构中,异常或者中断是处理系统中突发事件的一种机制,几乎所有的处理器都提供这种...
  • 中断流程 中断向量

    千次阅读 2013-10-14 11:28:22
    巩固下中断流程,还有就是中断向量时不时又心虚了,还是记录下。 xxx中断流程: 单片机接收到中断后,  先屏蔽中断 查询RTE 表,以MSI 的形式发给IA. (假设中断号为67,RTE中对应的向量号位108) IA 发EOI 给...
  • 中断向量与向量地址 中断号——中段的编号 什么是中断向量?我们可以把它理解成中断服务程序的入口地址。 比如说在 x86 系列当中,我们可以把中断向量理解成中断服务程序的段地址和偏移量组成的一个向量。 有的时候...
  • ARM7中断向量控制器,学习体会

    千次阅读 2011-09-12 12:38:52
    ARM内核只有FIQ和IRQ两个中断线,如果要扩展中断,就须要用到中断向量控制器。 快速中断和IRQ中断使能,通过CPSR中的I标志位和F标志位设置1来使能中断。 中断寄存器的使用: 中断寄存器包括中断选择寄存器...
  • ATmega16的中断向量

    2013-04-23 17:07:58
    ATmega16的中断向量区,详细、寄存器
  • CPU获取中断向量和保存重要的寄存器需要花费9个CPU时钟周期,因此CPU能够快速地响应中断。此外,中断的极性可以通过硬件和软件进行控制,每个中断也可以在PIE模块内控制中断的使能或禁止。  显然,这种复用中断...
  • 首先能识别触发的中断(对应中断源必须打开,然后查询当前中断状态寄存器),硬件会操控PC跳到中断向量入口(IRQ_HANDLE,硬件控制的只要是IRQ中断类型就会进入),在中断跳转函数里面保存现场(保存R0等等工作寄存器)--...
  • 1.设置中断向量优先级分组(主次优先级) NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //中断向量优先级配置 ST的注释:那一组代表了什么样的主次优先级排位,比如:第0组,主优先级0位,次优先级4位...
  • ARM 中断向量介绍

    千次阅读 2017-07-21 11:08:51
    最后,通过设置中断控制寄存器,设计外部中断EINT3的初始化程序,并给出主程序流程图。实践证明程序运行稳定可靠。 引言 计算机体系结构中,异常或者中断是处理系统中突发事件的一种机制,几乎所有的处理器都...
  • 在做stm32 iap升级固件的时候通常需要多份中断向量表。比如bootloader的中断向量表在0x00000000位置,应用程序...VTOR是arm内核的一个寄存器,叫做中断向量偏移量寄存器。当系统上电启动的时候CPU会从先找到中断向量...
  • ARM7学习笔记——中断向量控制器VIC

    千次阅读 2015-09-15 22:15:59
    向量中断控制器概述    ARM7TDMI内核具有两个中断输入,分别为IRQ中断和FIQ中断。但是芯片内部有许多中断源,最多可以有32个中断输入请求。...允许中断源产生中断寄存器VICIntEnable和VICIntEnClr控
  • 原文地址 在做stm32 iap升级固件的时候通常需要多份中断向量表。比如bootloader的中断向量表在0x00000000位置,应用程序的中断向...VTOR是arm内核的一个寄存器,叫做中断向量偏移量寄存器。当系统上电启动的时候CPU...
  • 在32位ARM系统中,一般都是在中断向量表中放置一条分支指令或PC寄存器加载指令,实现程序跳转到中断服务例程的功能。
  • 在F281x DSP中采用外设中断扩展模块(Peripheral Interrupt Expansion,PIE)解决上述问题。外设中断扩展模块实质上是将中断向量表范围扩展...中断向量映射主要由以下位/信号来控制。  该位在状态寄存器1(ST1)的位
  • 中断向量为:编程将中断向量类型21H所对应的中断向量从中断向量表中取出来分别放在 SI 和 BP中。(直接用 MOV 指令即可) CODE SEGMENT ASSUME CS:CODE START: XOR AX,AX ;AX清空 MOV DS,AX ;DS不可直接 MOV 立即...
  • STM32中断向量偏移

    千次阅读 2019-01-25 11:26:22
    总结一下在IAP升级中APP程序的中断向量表的偏移 ...① 直接操作寄存器 在APP程序的main函数的开头设置中断向量表偏移 SCB-&gt;VTOR = FLASH_BASE | 0x10000; 其中0x10000是偏移量。。也就是前面的IAP...
  • 使用芯片提供的例程,中断向量处理程序也非常简单。在上面的AIC中断配置中,中断产生不是直接调用用于处理中断事务的函数,而是调用一个用汇编语言编写的函数,该函数主要功能是在中断处理函数调用前后,完成寄存器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 700
精华内容 280
关键字:

中断向量寄存器