物联网之ARM体系结构及接口技术六(中断机制)

中断机制

中断

中断 过程

1. 中断初始化

   a. 管脚初始化

   b. 中断控制器初始化

2.中断向量表

   a.中断发生后,硬件自动跳转

   b. 现场保护

   c. 调用中断处理

3.中断处理

   a. 根据中断号做相应处理

   b. 清中断

  c. 现场恢复

中断源

Exynos4412中断控制器包含160个中断控制源,

分三类分别是:

1.用于CPU之间通信的SGI

(Software Generated Interrupt),

2.专用于特定CPU核的PPI

(Private Peripheral Interrupt)

3.被多个CPU核共享的SPI

(Shared Peripheral Interrupt)

中断控制器

中断源分发给不同的CPU.

每个中断都有一个唯一对应的ID号,当中断发生时,该ID号会写入一个特定的寄存器。

中断处理程序可以读取该寄存器来决定该调用哪个具体的中断处理函数。

中断初始化

int main(void)
{
/*初始化中断
一. 通过电路图找到K3 的中断管脚
二. 看芯片手册找到对应的特殊功能寄存器
1.  设置管脚控制模块(GPIO):              外*/
    GPX1.GPX1CON = (GPX1.GPX1CON & ~(0xF << 8)) | (0xF << 8);   // 设置管脚为中断模式   
    EXT_INT41_CON = (EXT_INT41_CON & ~(0x7 << 8)) | 0x2 << 8; //设置中断触发方式为下降沿
    EXT_INT41_MASK = (EXT_INT41_MASK & ~(0x1 << 2)); //管脚中断使能(一关)
/*2.  设置功能模块(中断控制模块 GIC):    内*/ 
    ICDISER.ICDISER1 |= (0x1 << 26); //使能对应中断(二关) 
    ICDIPTR.ICDIPTR14 = 0x01010101;  //SPI25  SPI26  interrupts are sent to processor 0                      ICDDCR = 1;          //分发器中断使能 (三关)
    CPU0.ICCPMR = 0xFF;  //设置CPU的中断优先级门限值,当前为最低,所有的中断都可以处理     
    CPU0.ICCICR |= 0x1;  //CPU接口中断使能(四关)

中断向量表

_start: b       start_code

        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

irq_handler:

sub  lr,lr,#4

stmfd sp!,{r0-r12,lr}  @保护现场

bl do_irq

ldmfd sp!,{r0-r12,pc}^ @恢复现场

ARM 指令

协处理器指令

MRC Pn,op1,Rd,CRn,CRm,op2  //mrc  p15,0,r0,c1,c0,0 读入cp15的c1寄存器的内容到r0中

MCR Pn,op1,Rd,CRn,CRm,op2  //mcr  p15,0,r0,c1,c0,0 写r0内容到cp15的c1寄存器中

    @ set Vector Base Address 为0x40008000

    ldr      r0,=0x40008000

    mcr    p15,0,r0,c12,c0,0

中断处理

void do_irq(void )
{
  /* 获取中断ID号,并根据不同的中断号做相应的处理 */
  int irq_num;
  irq_num = (CPU0.ICCIAR & 0x3FF);
  switch (irq_num) {
    case 58: //k3
      printf("IRQ interrupt num = %d\n",irq_num);
      EXT_INT41_PEND |= 0x1 << 2; // 清管脚控制模块的GPIO 的中断标志
      ICDICPR.ICDICPR1 |= 0x1 << 26;//清中断控制模块GIC 的中断标志(即清除分配器中的58号中断标志)
      break;
    case 57: //k2
      break;
  }
  /*结束中断  将处理完成的中断ID号写入该寄存器,则表示相应的中断处理完成*/
  CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x3FF))|irq_num;
} 

猜你喜欢

转载自blog.csdn.net/weixin_39148042/article/details/82470474
今日推荐