你的位置:首页 > 操作系统

[操作系统]Crotex A9 中断流程


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 LED211       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中断控制器对应的名称

           查看芯片手册(本例: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内核(cpu)


         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,#0x10101     mov    sp,r0       /*1024 byte for user mode of stack*/102 103     b    main104 105   .align  4106 107   /**** swi_interrupt handler ****/108 109 110   /**** irq_handler ****/111 irq_handler:112 113   sub lr,lr,#4114   stmfd sp!,{r0-r12,lr}115   .weak do_irq116    bl  do_irq117   ldmfd sp!,{r0-r12,pc}^118 119 stacktop:  .word     stack+4*512120 .data121 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 Pend21     EXT_INT41_PEND |= 0x1 << 1;22     ICDICPR.ICDICPR1 |= 0x1 << 25;23 24     //Turn on LED225     GPX2.DAT |= 0x1 << 7;26     mydelay_ms(500);27 28     //Turn off LED229     GPX2.DAT &= ~(0x1 << 7);30     mydelay_ms(500);31 32 33     break;34   }35 36   // End of interrupt37   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, LED245 46   //Key_2 Interrupt GPX1_147   GPX1.PUD = GPX1.PUD & ~(0x3 << 2); // Disables Pull-up/Pull-down48   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 interrupt51 52   //* GIC interrupt controller:53 54   // Enables the corresponding interrupt SPI25-- Key_255   ICDISER.ICDISER1 |= (0x1 << 25);56   CPU0.ICCICR |= 0x1; //Global enable for signaling of interrupts57   CPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. threshold58   ICDDCR = 1; //Bit0: GIC global enable59 60   ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25 interrupts are sent to processor 061 62 63   while (1);64 65   return 0;66 }