Crotex A9 中断流程

目录

  • 目录
  • 需求
  • 实现流程
    • 查看原理图连接引脚和控制逻辑
    • 查看相应芯片手册
      • 循环检测
      • 中断方法实现按键检测
  • 附录代码

需求

了解Cortex A9 按键中断(SPI)流程,实例:KEY2中断控制点亮LED2

实现检测按键k2,按键按下一次,实现LED灯闪一下。

实现流程

查看原理图:连接引脚和控制逻辑

  1. 连接引脚
    按键k2连接在GPX1_1 引脚
  2. 控制逻辑
    k2按下 —- k2闭合 —- GPX1_1 低电压
    K2常态 —- k2打开 —- GPX1_1 高电压

查看相应芯片手册

循环检测

  1. 配置GPX1_1引脚功能
    设置:引脚功能为输入,内部上下拉禁止
  2. 循环检测代码实现:
    while(1)
    {
        if(!(GPX1.DAT & (0x1<<1)))  // 返回为真,按键按下
      {    
         msdelay(10);
          if(!(GPX1.DAT & (0x1<<1))) //二次检测,去抖
          {
              GPX2.DAT |= 0x1 << 7;  //Turn on LED2
              mydelay_ms(500);
             GPX2.DAT &= ~(0x1<<7);  //Turn off LED2
             mydelay_ms(500);

             while(!(GPX1.DAT & (0x1<<1)));
         }
    }   

中断方法实现按键检测

将K2按下时,GPX1_1引脚获得的电平,作为异常事件。使能异常处理,k2每按下一次,响应一次异常处理。SPI 传递流程如下示:
Crotex A9 中断流程_第1张图片

  1. 外设一级:GPIO控制器

    1. 将GPX1_1引脚的上拉和下拉禁止
      GPX1PUD[3:2]=0B00;
    2. 将GPX1_1引脚功能设置为中断功能
      WAKEUP_INT1[1] — EXT_INT41[1]
      GPX1CON[7:4]=0xf
    3. EXT_INT41CON 配置触发电平
      当前配置成下降沿触发:
      EXT_INT41CON[6:4]=0X2
    4. EXT_INIT41_FLTCON0 配置中断引脚滤波
      默认就是打开,不需要配置
    5. EXT_INT41_MASK 中断使能寄存器
      使能INT41[1]:
      EXT_INT41_MASK[1]=0B0
    6. EXT_INT41_PEND 中断状态寄存器
      当GP1_1引脚收到中断信号,中断发生,中断状态寄存器 EXT_INT41_PEND 相应位会自动置1。
      注:中断处理完成的时候,需手动清除相应状态为,置1清零
      EXT_INT41_PEND[1]=0b1
  2. 中断控制器

    1. 找到外设中断名称与GIC中断控制器对应的名称
      查看芯片手册(本例:Exynos_4412 – 9.2表)
      WAKEUP_INT[1] — EXT_INT41[1] — INT[9] — SPI[25]/ID[57]
    2. 使能cpu0的spi25/id57
      ICDISER.ICDISER1 |= (0x1 << 25); //57/32 =1…25 取整数(那个寄存器) 和余数(哪位)
    3. 全局使能cpu0中断处理
      CPU0.ICCICR |= 0x1;
    4. 优先级屏蔽寄存器,设置cpu0能处理所有的中断
      CPU0.ICCPMR = 0xFF;
    5. GIC使能
      ICDDCR =1;
    6. 设置SPI[25]/ID[57]由那个cpu处理,当前设置为cpu0的irq中断
      ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25 interrupts are sent to processor 0 //57/4 = 14..1 14号寄存器的
  3. ARM内核(cpu0)
    Crotex A9 中断流程_第2张图片

    1. 四大步三小步
      1. 拷贝 CPSR 到 SPSR_
      2. 设置适当的 CPSR 位:
        – 改变处理器状态进入 ARM 态
        – 改变处理器模式进入相应的异常模式
        – 设置中断禁止位禁止相应中断 (如果需要)
      3. 保存返回地址到 LR_
      4. 设置 PC 为相应的异常向量
    2. 中断服务程序代码:start.S
      见附录附录代码
    3. 中断处理程序代码:do_irq函数c语言
      1. 读取正在处理的中断ID寄存器(ICCIAR)
        irq_num = (CPU0.ICCIAR & 0x1FF);
      2. 根据irq_num,分支处理中断
      3. 清除中断状态位
        i.外设级,EXT_INT41_PEND |= 0x1 << 1;
        ii.GIC级,ICDICPR.ICDICPR1 |= 0x1 << 25;
        iii.CPU0级 CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;
      4. c代码如下示:
        
        #include "exynos_4412.h"
        
        void mydelay_ms(int ms)
        {
          int i, j;
          while(ms--)
          {
              for (i = 0; i < 5; i++)
                  for (j = 0; j < 514; j++);
          }
        }
        
        void do_irq(void )
        {
         int irq_num;
         irq_num = (CPU0.ICCIAR & 0x1FF);
         switch (irq_num) {
        
         case 57: //
             //Clear Pend
             EXT_INT41_PEND |= 0x1 << 1;
             ICDICPR.ICDICPR1 |= 0x1 << 25;
        
             //Turn on LED2
             GPX2.DAT |= 0x1 << 7;
             mydelay_ms(500);
        
             //Turn off LED2
             GPX2.DAT &= ~(0x1 << 7);
             mydelay_ms(500);
              break;
         }
          // End of interrupt
         CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;
        
        }
        
        
        int main(void)
        {
         GPX2.CON = (GPX2.CON & ~(0xf << 28)) | 1 << 28;  //GPX2_7:output, LED2
        
         //Key_2 Interrupt GPX1_1
         GPX1.PUD = GPX1.PUD & ~(0x3 << 2); // Disables Pull-up/Pull-down
         GPX1.CON = (GPX1.CON & ~(0xF << 4)) | (0xF << 4); //GPX1_1: WAKEUP_INT1[1](EXT_INT41[1])
         EXT_INT41_CON = (EXT_INT41_CON & ~(0x7 << 4)) | 0x2 << 4;
         EXT_INT41_MASK = (EXT_INT41_MASK & ~(0x1 << 1)); // Bit: 0 = Enables interrupt
        
          //* GIC interrupt controller:
        
         // Enables the corresponding interrupt SPI25-- Key_2
         ICDISER.ICDISER1 |= (0x1 << 25);
         CPU0.ICCICR |= 0x1; //Global enable for signaling of interrupts
         CPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. threshold
         ICDDCR = 1; //Bit0: GIC global enable
        
         ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25 interrupts are sent to processor 0
        
          while (1);
        
          return 0;
        }

附录代码

中断服务代码:start.S

   .text
   .global _start
   _start:
           b        reset
           ldr        pc,_undefined_instruction
           ldr        pc,_software_interrupt
           ldr        pc,_prefetch_abort
           ldr        pc,_data_abort
           ldr        pc,_not_used
          ldr        pc,_irq
          ldr        pc,_fiq

  _undefined_instruction: .word  _undefined_instruction
  _software_interrupt:    .word  _software_interrupt
  _prefetch_abort:        .word  _prefetch_abort
  _data_abort:            .word  _data_abort
  _not_used:                .word  _not_used
  _irq:                    .word  irq_handler
  _fiq:                    .word  _fiq


  reset:

      ldr    r0,=0x40008000
      mcr    p15,0,r0,c12,c0,0        @ Vector Base Address Register

          mrs      r0,cpsr
          bic        r0,r0,#0x1f
          orr        r0,r0,#0xd3
          msr        cpsr,r0         @ Enable svc mode of cpu

          mov    r0, #0xfffffff
            mcr    p15, 0, r0, c1, c0, 2      @ Defines access permissions for each coprocessor
                                      @ Privileged a
 nd User mode access

      /* * Invalidate L1 I/D */
      mov    r0, #0 @ set up for MCR
      mcr    p15, 0, r0, c8, c7, 0    @ invalidate TLBs
      mcr    p15, 0, r0, c7, c5, 0    @ invalidate icache


      @Set the FPEXC EN bit to enable the FPU:
      MOV r3, #0x40000000
      fmxr FPEXC, r3

      /* * disable MMU stuff and caches */
      mrc    p15, 0, r0, c1, c0, 0
      bic    r0, r0, #0x00002000 @ clear bits 13 (--V-)
      bic    r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
      orr    r0, r0, #0x00001000 @ set bit 12 (---I) Icache
      orr    r0, r0, #0x00000002 @ set bit 1 (--A-) Align
      orr    r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
      mcr    p15, 0, r0, c1, c0, 0

  /* LED Test Code */

      ldr r0, =0x114001E0
      ldr r1, [r0]
      bic r1, r1, #0xf0000
      orr r1, r1, #0x10000
      str r1, [r0]

      ldr r0, =0x114001E8
      ldr r1, [r0]
      bic r1, r1, #0x300
      str r1, [r0]

      ldr r0, =0x114001E4
      ldr r1, [r0]
      orr r1, r1, #0x10
      str r1, [r0]

  init_stack:
          ldr        r0,stacktop         /*get stack top pointer*/

      /********svc mode stack********/
          mov        sp,r0
          sub        r0,#128*4 /*512 byte for irq mode of stack*/
      /****irq mode stack**/
          msr        cpsr,#0xd2
          mov        sp,r0
          sub        r0,#128*4 /*512 byte for irq mode of stack*/
      /***fiq mode stack***/
          msr     cpsr,#0xd1
          mov        sp,r0
          sub        r0,#0
      /***abort mode stack***/
          msr        cpsr,#0xd7
          mov        sp,r0
          sub        r0,#0
      /***undefine mode stack***/
          msr        cpsr,#0xdb
          mov        sp,r0
          sub        r0,#0
     /*** sys mode and usr mode stack ***/
         msr        cpsr,#0x10
         mov        sp,r0             /*1024 byte for user mode of stack*/

         b        main

     .align    4

     /**** swi_interrupt handler ****/


     /**** irq_handler ****/
 irq_handler:

     sub  lr,lr,#4
     stmfd sp!,{r0-r12,lr}
     .weak do_irq
     bl    do_irq
     ldmfd sp!,{r0-r12,pc}^

 stacktop:    .word         stack+4*512
 .data

 stack:     .space  4*512

你可能感兴趣的:(Crotex A9 中断流程)