首页 > 技术文章 > Crotex A9 中断流程

Je-Cortex 2015-09-26 15:02 原文

Cortex A9 按键中断(SPI)流程

示例: KEY2 中断控制点亮 LED2  

【0】检测按键k2,按键k2按下一次,灯LED2闪一次。

【1】查看原理图,连接引脚和控制逻辑
(1)按键k2 连接在GPX1_1引脚
(2)控制逻辑
       k2 按下  ---- K2闭合 ---- GPX1_1 低电压
       k2 常态  ---- K2打开 ---- GPX1_1 高电压

【2】查看相应的芯片手册

    【2-1】循环检测GPX1_1引脚输入的电平,为低电压时,按键按下

        (1)配置GPX1_1引脚功能为输入,设置内部上拉下拉禁止。
               GPX1.CON = GPX1.CON &(~(0xf<<4)) ;
   (2)循环检测 :  

 1 while(1)
 2 {
 3     if(!(GPX1.DAT & (0x1<<1)))  // 返回为真,按键按下
 4     {    
 5         msdelay(10);
 6         if(!(GPX1.DAT & (0x1<<1))) //二次检测,去抖
 7         {
 8             GPX2.DAT |= 0x1 << 7;  //Turn on LED2
 9             mydelay_ms(500);
10             GPX2.DAT &= ~(0x1<<7);  //Turn off LED2
11             mydelay_ms(500);
12       
13             while(!(GPX1.DAT & (0x1<<1)));
14         }
15     }
16 }

       

   【2-2】中断方法检测按键
          将K2按下时,GPX1_1引脚获得的电平,作为异常事件。使能异常处理,k2每按下一次,响应一次异常处理。SPI 传递流程如下示:

     (1)外设一级 --- GPIO控制器
           0-- 将GPX1_1引脚的上拉和下拉禁止
                GPX1PUD[3:2]= 0b00;

           1-- 将GPX1_1引脚功能设置为中断功能 WAKEUP_INT1[1] --- EXT_INT41[1]
                GPX1CON[7:4] = 0xf

           2-- EXT_INT41CON  配置触发电平
                当前配置成下降沿触发:
                EXT_INT41CON[6:4] = 0x2

           3-- EXT_INT41_FLTCON0 配置中断引脚滤波
                默认就是打开的,不需要配置

           4--EXT_INT41_MASK 中断使能寄存器
                使能INT41[1]
                EXT_INT41_MASK[1] = 0b0

           5--EXT_INT41_PEND 中断状态寄存器
                当GPX1_1引脚接收到中断信号,中断发生,中断状态寄存器EXT_INT41_PEND 相应位会自动置1
                注意:中断处理完成的时候,需要清除相应状态位。置1清0.
                EXT_INT41_PEND[1] =0b1 
    (2)中断控制器

         0--找到外设中断名称和GIC中断控制器对应的名称

           查看芯片手册(本例:Exynos_4412 -- 9.2表)
            WAKEUP_INT1[1] --- EXT_INT41[1] --- INT[9] --- SPI[25]/ID[57]

         1--使能cpu0的spi25/id57
            ICDISER.ICDISER1 |= (0x1 << 25);    //57/32 =1...25 取整数(那个寄存器) 和余数(哪位)

         2--全局使能cpu0中断处理
            CPU0.ICCICR |= 0x1;

           3--优先级屏蔽寄存器,设置cpu0能处理所有的中断。
              CPU0.ICCPMR = 0xFF;

           4--GIC使能 
             ICDDCR =1;

           5--设置SPI[25]/ID[57]由那个cpu处理,当前设置为cpu0的irq中断
               ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25  interrupts are sent to processor 0   //57/4 = 14..1 14号寄存器的[15:8]

     (3)ARM内核(cpu0)


         1--四大步三小步 --- 硬件       

        (1)拷贝 CPSR 到 SPSR_<mode>
        (2)设置适当的 CPSR 位:                                
           (2-1)--改变处理器状态进入 ARM 态
           (2-2)--改变处理器模式进入相应的异常模式
           (2-3)--设置中断禁止位禁止相应中断 (如果需要)
        (3)保存返回地址到 LR_<mode>
        (4)设置 PC 为相应的异常向量
          2--中断服务程序 --- start.S 汇编
  1 .text
  2 .global _start
  3 _start:
  4         b        reset
  5         ldr        pc,_undefined_instruction
  6         ldr        pc,_software_interrupt
  7         ldr        pc,_prefetch_abort
  8         ldr        pc,_data_abort
  9         ldr        pc,_not_used
 10         ldr        pc,_irq
 11         ldr        pc,_fiq
 12 
 13 _undefined_instruction: .word  _undefined_instruction
 14 _software_interrupt:    .word  _software_interrupt
 15 _prefetch_abort:        .word  _prefetch_abort
 16 _data_abort:            .word  _data_abort
 17 _not_used:                .word  _not_used
 18 _irq:                    .word  irq_handler
 19 _fiq:                    .word  _fiq
 20 
 21 
 22 reset:
 23 
 24     ldr    r0,=0x40008000
 25     mcr    p15,0,r0,c12,c0,0        @ Vector Base Address Register
 26 
 27         mrs      r0,cpsr
 28         bic        r0,r0,#0x1f
 29         orr        r0,r0,#0xd3
 30         msr        cpsr,r0         @ Enable svc mode of cpu
 31 
 32         mov    r0, #0xfffffff
 33           mcr    p15, 0, r0, c1, c0, 2      @ Defines access permissions for each coprocessor
 34                                     @ Privileged and User mode access
 35 
 36     /*
 37      * Invalidate L1 I/D
 38      */
 39     mov    r0, #0            @ set up for MCR
 40     mcr    p15, 0, r0, c8, c7, 0    @ invalidate TLBs
 41     mcr    p15, 0, r0, c7, c5, 0    @ invalidate icache
 42 
 43 
 44     @Set the FPEXC EN bit to enable the FPU:
 45     MOV r3, #0x40000000
 46     fmxr FPEXC, r3
 47 
 48     /*
 49      * disable MMU stuff and caches
 50      */
 51     mrc    p15, 0, r0, c1, c0, 0
 52     bic    r0, r0, #0x00002000    @ clear bits 13 (--V-)
 53     bic    r0, r0, #0x00000007    @ clear bits 2:0 (-CAM)
 54     orr    r0, r0, #0x00001000    @ set bit 12 (---I) Icache
 55     orr    r0, r0, #0x00000002    @ set bit 1  (--A-) Align
 56     orr    r0, r0, #0x00000800    @ set bit 11 (Z---) BTB
 57     mcr    p15, 0, r0, c1, c0, 0
 58 
 59 /* LED Test Code */
 60 
 61     ldr r0, =0x114001E0
 62     ldr r1, [r0]
 63     bic r1, r1, #0xf0000
 64     orr r1, r1, #0x10000
 65     str r1, [r0]
 66 
 67     ldr r0, =0x114001E8
 68     ldr r1, [r0]
 69     bic r1, r1, #0x300
 70     str r1, [r0]
 71 
 72     ldr r0, =0x114001E4
 73     ldr r1, [r0]
 74     orr r1, r1, #0x10
 75     str r1, [r0]
 76 
 77 init_stack:
 78         ldr        r0,stacktop         /*get stack top pointer*/
 79 
 80     /********svc mode stack********/
 81         mov        sp,r0
 82         sub        r0,#128*4          /*512 byte  for irq mode of stack*/
 83     /****irq mode stack**/
 84         msr        cpsr,#0xd2
 85         mov        sp,r0
 86         sub        r0,#128*4          /*512 byte  for irq mode of stack*/
 87     /***fiq mode stack***/
 88         msr     cpsr,#0xd1
 89         mov        sp,r0
 90         sub        r0,#0
 91     /***abort mode stack***/
 92         msr        cpsr,#0xd7
 93         mov        sp,r0
 94         sub        r0,#0
 95     /***undefine mode stack***/
 96         msr        cpsr,#0xdb
 97         mov        sp,r0
 98         sub        r0,#0
 99    /*** sys mode and usr mode stack ***/
100         msr        cpsr,#0x10
101         mov        sp,r0             /*1024 byte  for user mode of stack*/
102 
103         b        main
104 
105     .align    4
106 
107     /****  swi_interrupt handler  ****/
108 
109 
110     /****  irq_handler  ****/
111 irq_handler:
112 
113     sub  lr,lr,#4
114     stmfd sp!,{r0-r12,lr}
115     .weak do_irq
116     bl    do_irq
117     ldmfd sp!,{r0-r12,pc}^
118 
119 stacktop:    .word         stack+4*512
120 .data
121 
122 stack:     .space  4*512
start.S

               3--中断处理程序 --- do_irq函数 c语言(函数原型void name(void))
                 (1) 读取正在处理的中断ID寄存器(ICCIAR)
                 irq_num = (CPU0.ICCIAR & 0x1FF);
               (2)根据irq_num,分支处理中断
               (3)清除中断状态位 
                    (3-1)i.外设级,EXT_INT41_PEND |= 0x1 << 1;
                    (3-2)ii.GIC级,ICDICPR.ICDICPR1 |= 0x1 << 25;
                    (3-3)iii.CPU0级 CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;

C代码:

 1 #include "exynos_4412.h"
 2 
 3 void mydelay_ms(int ms)
 4 {
 5     int i, j;
 6     while(ms--)
 7     {
 8         for (i = 0; i < 5; i++)
 9             for (j = 0; j < 514; j++);
10     }
11 }
12 
13 void do_irq(void )
14 {
15     int irq_num;
16     irq_num = (CPU0.ICCIAR & 0x1FF);
17     switch (irq_num) {
18 
19     case 57: //
20         //Clear Pend
21         EXT_INT41_PEND |= 0x1 << 1;
22         ICDICPR.ICDICPR1 |= 0x1 << 25;
23 
24         //Turn on LED2
25         GPX2.DAT |= 0x1 << 7;
26         mydelay_ms(500);
27 
28         //Turn off LED2
29         GPX2.DAT &= ~(0x1 << 7);
30         mydelay_ms(500);
31 
32 
33         break;
34     }
35 
36     // End of interrupt
37     CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;
38 
39 }
40 
41 
42 int main(void)
43 {
44     GPX2.CON = (GPX2.CON & ~(0xf << 28)) | 1 << 28; //GPX2_7:output, LED2
45 
46     //Key_2  Interrupt  GPX1_1
47     GPX1.PUD = GPX1.PUD & ~(0x3 << 2); // Disables Pull-up/Pull-down
48     GPX1.CON = (GPX1.CON & ~(0xF << 4)) | (0xF << 4); //GPX1_1: WAKEUP_INT1[1](EXT_INT41[1])
49     EXT_INT41_CON = (EXT_INT41_CON & ~(0x7 << 4)) | 0x2 << 4;
50     EXT_INT41_MASK = (EXT_INT41_MASK & ~(0x1 << 1)); //  Bit: 0 = Enables interrupt
51 
52      //* GIC interrupt controller:
53 
54     // Enables the corresponding interrupt SPI25-- Key_2
55     ICDISER.ICDISER1 |= (0x1 << 25);
56     CPU0.ICCICR |= 0x1; //Global enable for signaling of interrupts
57     CPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. threshold
58     ICDDCR = 1; //Bit0:  GIC global enable
59 
60     ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25  interrupts are sent to processor 0
61 
62 
63     while (1);
64 
65     return 0;
66 }

 

推荐阅读