zoukankan      html  css  js  c++  java
  • ARM中的中断

    在ARM中,事件发生将会触发中断,然而,中断并不会直接触发CPU,而是在由一个GIC,中断控制器来管理:

    其中,中断分为
    Supports three interrupt types:
     Private Peripheral Interrupt (PPI)一个中断源对应一个CPU
    Software Generated Interrupt (SGI)     CPU对应CPU
    Shared Peripheral Interrupt (SPI)    一个中断源对应多个CPU

    今天的例子是用SGI中断来实现的,在处理中断的时候,主要分三步:

         //step 1: cpu cpsr

      CPU允许中断
     20       __asm__ __volatile__(
     21           "mrs r0, cpsr "
     22           "bic r0, r0, #0x80 "//设置CPSR的I位,将IRQ位打开
     23           "msr cpsr, r0 "
     24           ::: "r0"
     25       );
     26
     27       //step 2: GIC

      GIC
     28       ICCICR_CPU0 = 1;//CPU接口控制寄存器
     29       ICCPMR_CPU0 = 0xff;//中断优先标志寄存器
     30       ICDDCR = 1;//设置本中断的开关
     31       ICDIPR0_CPU0 = (0x00 << 0);//本中断的优先级
     32       ICDIPTR0_CPU0 = 1;//选择指定的CPU
     33       ICDISER0_CPU0 = (1 << 0);//设置本中断开启
     34   各个寄存器描述如下:详细见4412     782页

      
     35       //step 3: interrupt source

      中断源
     36       ICDSGIR = 0 | (1 << 16) | (0 << 24);//SGI控制寄存器CPUTargetList.TargetListFi    lte
     37       printf("welcome back! ");

    下面是代码:

     1 #include"regs.h"
      2 
      3 int (*printf)(char *, ...) = 0xc3e114d8;
      4 
      5 void init_ttb(unsigned long *addr);
      6 void enable_mmu(void);
      7 unsigned long data_abort_init();
      8 void memcopy(unsigned long* dest,unsigned long* source,int len);
      9 void do_irq();
     10 
     11 int main()
     12 {
     13      *(unsigned long *)0x66000000 = do_irq;
     14     unsigned long source_addr=data_abort_init();
     15     printf("swi_souce addr is %x
    ",source_addr);
     16     memcopy(0x60000000,source_addr,0x1000);
     17     enable_mmu();
     18 
     19      //step 1: cpu cpsr
     20       __asm__ __volatile__(
     21           "mrs r0, cpsr
    "
     22           "bic r0, r0, #0x80
    "//设置CPSR的I位,将IRQ位打开
     23           "msr cpsr, r0
    "
     24           ::: "r0"
     25       );
     26 
     27       //step 2: GIC 
     28       ICCICR_CPU0 = 1;//CPU接口控制寄存器
     29       ICCPMR_CPU0 = 0xff;//中断优先标志寄存器
     30       ICDDCR = 1;//设置本中断的开关
     31       ICDIPR0_CPU0 = (0x00 << 0);//本中断的优先级
     32       ICDIPTR0_CPU0 = 1;//选择指定的CPU
     33       ICDISER0_CPU0 = (1 << 0);//设置本中断开启
     34 
     35       //step 3: interrupt source
     36       ICDSGIR = 0 | (1 << 16) | (0 << 24);//SGI控制寄存器CPUTargetList.TargetListFi    lte
     37       printf("welcome back! 
    ");
     38 }
     39 
     40 void do_irq()
     41     {
     42         unsigned long data = ICCIAR_CPU0;
     43         unsigned long irq_id = data & 0x3ff;
     44         unsigned long cpu_id = (data >> 10) & 0x7;
     45         ICCEOIR_CPU0 = irq_id | (cpu_id << 10);
     46         printf("irq is %d, cpu is %d
    ", irq_id, cpu_id);
     47     }
     48 
     49 void memcopy(unsigned long* dest, unsigned long* source,int len)
     50 {
     51     int i=0;;
     52     for(i=0;i<len;i++)
     53         dest[i]=source[i];
     54 }
     55 
     56 unsigned long  data_abort_init()
     57 {
     58     unsigned long source;
     59     __asm__ __volatile__(
     60          "ldr %0, =voliate_start
    "
     61          : "=r" (source)
     62      );
     63     return source;
     64 }
     65 
     66 __asm__(
     67 "voliate_start:
    "
     68     //跳转目录
     69     " b reset
    "
     70     " b undefined
    "
     71     " b swi
    "
     72     " b pre_abt
    "
     73     " b data_abt
    "
     74     " .word 0
    "//占位符号,一个位占4个字节
     75     " b irq
    "
     76     " b fiq
    "
     77 "
    "
     78     //跳转要分三部:
     79     //1:将PC保存到新模式下的lr中;
     80     //2:将CPSR保存在SPSR中
     81     //3:初始化SP
     82     //前两步由硬件完成,而第三部需要手动完成
     83 "reset:
    "
     84 
     85 "undefined:
    "
     86      "mov sp, #0x66000000
    "//初始化SP
     87      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
     88     //打印一句话 
     89      "ldr r0, =und_string
    "
     90      "ldr r2, show
    "
     91      "blx r2
    "
     92     //跳回来分两部
     93     //1:将CPSR保存在SPSR中
    84 
     85 "undefined:
    "
     86      "mov sp, #0x66000000
    "//初始化SP
     87      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
     88     //打印一句话 
     89      "ldr r0, =und_string
    "
     90      "ldr r2, show
    "
     91      "blx r2
    "
     92     //跳回来分两部
     93     //1:将CPSR保存在SPSR中
     94     //2:将PC保存到新模式下的lr中;
     95      "mov sp, #0x66000000
    "//
     96      "ldmea sp, {r0-r12, pc}^
    "// 
     97 
     98 "swi:
    "
     99 
    100 "pre_abt:
    "
    101 "data_abt:
    "
    102      "sub lr, lr, #4
    "
    103      "mov sp, #0x66000000
    "//初始化SP
    104      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
    105     //打印一句话 
    106      "ldr r0, =data_string
    "
    107      "ldr r2, show
    "
    108      "blx r2
    "
    109     //跳回来分两部
    110     //1:将CPSR保存在SPSR中
    111     //2:将PC保存到新模式下的lr中;
    112      "mov sp, #0x66000000
    "//
    113      "ldmea sp, {r0-r12, pc}^
    "// 
    114 
    115 "irq:
    "
    116     "sub lr, lr, #4
    "
    117      "mov sp, #0x66000000
    "//初始化SP
    118      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
    119     //打印一句话 
    120      "mov r2, #0x66000000
    "
    121      "ldr r1, [r2]
    "
    122      "blx r1
    "
    123 
    124    //  "ldr r0, =irq_string
    "
    125    //  "ldr r2, show
    "
    126    //  "blx r2
    "
    127     //跳回来分两部
    128     //1:将CPSR保存在SPSR中
    129     //2:将PC保存到新模式下的lr中;
    130      "mov sp, #0x66000000
    "//
    131      "ldmea sp, {r0-r12, pc}^
    "//
    132 "fiq:
    "
    133     "show:
    "
    134      ".word 0xc3e114d8
    "
    135 
    136     "und_string:
    "
    137      ".asciz "This is  UND!\n" 
    "
    138      "data_string:
    "
    139      ".asciz "This DATA_ABORT!\n" 
    "
    140      "irq_string:
    "
    141      ".asciz "This IRQ!\n" 
    "
    142 
    143         );
    144 
    145 void init_ttb(unsigned long *addr)
    146 {
    147     unsigned long va = 0;//定义虚拟地址
    148     unsigned long pa = 0;//定义物理地址
    149 
    150     //40000000-------80000000   ====  40000000------80000000
    151     for(va=0x40000000; va<=0x80000000; va+=0x100000){
    152         pa = va;
    153         addr[va >> 20] = pa | 2;
    154         //|2的目的是将0-2位置为10此时将是小页模式4K
    155     }
    156 
    157     //00000000-------10000000   ====  60000000------70000000
    158     for(va=0x00000000; va<=0x10000000; va+=0x100000){
    159         pa = va+0x60000000;
    160         addr[va >> 20] = pa | 2;
    161     }
    162 
    163     //10000000-------14000000   ====  10000000------14000000
    164     for(va=0x10000000; va<=0x14000000; va+=0x100000){
    165         pa = va;
    166         addr[va >> 20] = pa | 2;
    167     }
    168 
    169     //30000000-------40000000   ====  50000000------60000000
    170     for(va=0x30000000; va<0x40000000; va+=0x100000){
    171         pa = va + 0x20000000;
    172         addr[va >> 20] = pa | 2;
    173     }
    174 }
    175 
    176 void enable_mmu(void)
    177 
    178 {
    179     unsigned long addr = 0x70000000;
    180     init_ttb(addr);
    181     //step:初始化页表
    182 
    183     unsigned long mmu = 1 | (1 << 1) | (1 << 8);
    184     //将MMU的第0,1,8位置1
    185     __asm__ __volatile__(
    186         "mov r0, #3
    "
    187         "MCR p15, 0, r0, c3, c0, 0
    "//manager
    188         "MCR p15, 0, %0, c2, c0, 0
    "//addr  
    189         "MCR p15, 0, %1, c1, c0, 0
    "// enable mmu
    190         :
    191         : "r" (addr), "r" (mmu)
    192         : "r0"
    193     );
    194     printf("MMU is enable!
    ");
    195 }
    196 

    在代码中,主函数其他的部分在前面都已经说了,已不再说。主要是在VICTOR函数中,将处理中断的部分,做成了一个函数,以后更容易修改处理的部分。

     void do_irq()
     41     {
     42         unsigned long data = ICCIAR_CPU0;//取出IRQ  ID  和CPU  ID
     43         unsigned long irq_id = data & 0x3ff;
     44         unsigned long cpu_id = (data >> 10) & 0x7;
     45         ICCEOIR_CPU0 = irq_id | (cpu_id << 10);//清除CPU
     46         printf("irq is %d, cpu is %d ", irq_id, cpu_id);
     47     }
    //总的来说,在以前的基础上面,今天主要认识了GIC的配置,更重要的是,中断分为四步:

    1,CPU开

    2,GIC配置

    3,中断源

    4,处理中断,清中断


     

  • 相关阅读:
    bzoj1336: [Balkan2002]Alien最小圆覆盖
    bzoj3564: [SHOI2014]信号增幅仪
    [HDU5353]
    [codeforce1072D]
    [dp001]逛公园
    树上问题泛做
    [BZOJ2599]race
    [CEOI2019]MAGIC TREE
    [BZOJ2836]魔法树
    QTREE3
  • 原文地址:https://www.cnblogs.com/hongzhunzhun/p/4513031.html
Copyright © 2011-2022 走看看