Tiny4412中断介绍

  通过几天裸板驱动开发,今天对ARM的中断做一些简单总结,前面我们已经了解了ARM的7种异常模式,中断是异常模式的一种,在ARM中异常事件发生将会触发中断,但是,所有的中断都不能直接访问cpu,而是都统一由GIC(中断管理器)来管理;下面是samsung提供的模式图:

其中GIC管理的中断有分为:

 

  (1)SGI:一个cpu中断另一个cpu(cpu0 ->cpu1)

  (2)PPI:一个中断只能中断一个cpu

  (3)SPI:一个中断可以中断多个cpu

  处理一个中断大致需要三步:

  (1)cpu permit interrupt (cpu允许中断)

  (2)GIC enable (启用GIC)

  (3)SET Interrupt source (设置中断源)

  下面是用SGI实现的一个程序:

  头文件:

 1 #ifndef __BUNFLY_H
 2 #define __BUNFLY_H
 3 
 4 #define ICCICR_CPU0    (*(volatile unsigned long *)0x10480000)
 5 #define ICCPMR_CPU0    (*(volatile unsigned long *)0x10480004)
 6 #define ICDDCR        (*(volatile unsigned long *)0x10490000)
 7 #define ICDIPR2_CPU0    (*(volatile unsigned long *)0x10490408)
 8 #define ICDIPTR2_CPU0    (*(volatile unsigned long *)0x10490808)
 9 #define ICDISER0_CPU0    (*(volatile unsigned long *)0x10490100)
10 #define ICDSGIR        (*(volatile unsigned long *)0x10490f00)
11 #define ICCEOIR_CPU0 (*(volatile unsigned long *)0x10480010)
12 #define ICCIAR_CPU0  (*(volatile unsigned long *)0x1048000c)
13 
14 #endif    //__BUNFLY_H
  1 #include "bunfly.h"
  2 
  3 int (*printf)(char *, ...) = 0xc3e114d8;
  4 void enable_mmu();
  5 void init_table(unsigned long *addr);
  6 void memcpy(unsigned char *dest, unsigned char *src, int len);
  7 extern unsigned long  vector_start;
  8 void do_irq();
  9 
 10 int main()
 11 {    
 12     memcpy(0x70000000, vector_start, 0x1000);    
 13     enable_mmu();
 14 
 15     *(unsigned long *)0x47000000 = do_irq;
 16 
 17     //step 1: set cpu permit interrupt
 18     __asm__ __volatile__(
 19         "mrs r0, cpsr
"
 20         "bic r0,r0, #0x80
"
 21         "msr cpsr, r0
"
 22         :::"r0"
 23     );
 24 
 25     //step 2: set GIC (cgi) enable
 26     ICCICR_CPU0 = 1;//cpu接口控制寄存器(总开关)
 27     ICCPMR_CPU0 =0xff;//中断总优先级(门槛)
 28     ICDDCR = 1;//本中断开关
 29     ICDIPR2_CPU0 = (3 << 9);//本中断优先级
 30     ICDIPTR2_CPU0 = (1 << 9);//目标cpu
 31     ICDISER0_CPU0 = (1 << 9);//启用本中断
 32     
 33     //step 3: set interrupt source
 34     ICDSGIR = 9 | (1 << 16);
 35         
 36     printf("welcom back
");
 37 }
 38 
 39 void do_irq()
 40 {
 41     unsigned long ack_id = 0;
 42     unsigned long cpu_id = 0;
 43     unsigned long data = ICCIAR_CPU0;
 44 
 45     /*clean interrupt*/
 46     ack_id = data & 0x3ff;
 47     cpu_id = data & (0x7 << 10);
 48     ICCEOIR_CPU0 = ack_id | cpu_id;
 49 
 50     printf("this is interrupt
");
 51     printf("cup_id is %d
", cpu_id >> 10);
 52     printf("ack_id is %d
", ack_id);
 53 
 54 }
 55 
 56 void memcpy(unsigned char *dest, unsigned char *src, int len)
 57 {
 58     int i = 0;
 59     for(i = 0; i < len; i++) {
 60         dest[i] = src[i];
 61     }
 62 }
 63 
 64 void enable_mmu()
 65 {
 66     /*构建表*/
 67     unsigned long addr = 0x50000000;
 68     init_table(addr);
 69     /*打开mmu*/
 70     unsigned long mmu = 0;
 71     mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8);
 72     __asm__ __volatile__ (
 73         "mov r0, #3
"
 74         "MCR p15, 0, r0, c3, c0, 0
"//设置为管理员
 75         "MCR p15, 0, %0, c2, c0, 0
"//设置表的地址
 76         "MCR p15, 0, %1, c1, c0, 0
"//开启mmu
 77         :    
 78         :    "r" (addr), "r" (mmu)
 79         :
 80     );
 81 
 82 }
 83 
 84 __asm__(
 85 
 86 "vector: 
"
 87 "    b reset
"
 88 "    b und
"
 89 "    b swi
"
 90 "    b pre_abt
"
 91 "    b data_abt
"
 92 "    .word 0x0
"
 93 "    b irq
"
 94 "    b fiq
"
 95 "reset:
"
 96 "und:
"
 97 "    mov sp, #0x47000000
"
 98 "    stmdb sp!, {r0-r12, lr}
"
 99 
100 "    ldr r3, =0x47000004
"
101 "    ldr r2, [r3]
"
102 "    blx r2
"
103 
104 "    mov sp, #0x47000000
"
105 "    ldmdb sp, {r0-r12, pc}^    
"
106 
107 "swi:
"
108 "    mov sp, #0x47000000
"
109 "    stmdb sp!, {r0-r12, lr}^
"
110 
111 "    mov sp, #0x47000000
"
112 "    ldmdb sp, {r0-r12, pc}^    
"
113 
114 "pre_abt:
"
115 
116 "data_abt:
"
117 "    mov sp, #0x47000000
"
118 "    sub lr, lr, #4
"
119 "    stmdb sp!, {r0-r12, lr}
"
120 
121 "    ldr r3, =0x47000008
"
122 "    ldr r2, [r3]
"
123 "    blx r2
"
124 
125 "    mov sp, #0x47000000
"
126 "    ldmdb sp, {r0-r12, pc}^    
"
127 "irq:
"
128 
129 "    mov sp, #0x47000000
"
130 "    sub lr, lr, #4
"
131 "    stmdb sp!, {r0-r12, lr}
"
132 
133 "    ldr r3, =0x47000000
"
134 "    ldr r2, [r3]
"
135 "    blx r2
"
136 
137 "    mov sp, #0x47000000
"
138 "    ldmdb sp, {r0-r12, pc}^    
"
139 
140 "fiq:
"
141 
142     ".global vector_start
"
143 "vector_start: 
"
144     ".word vector 
 "
145 
146 );
147 
148 void init_table(unsigned long *addr)
149 {
150     unsigned long va = 0;
151     unsigned long phys = 0;
152 
153     //0x40000000-0x80000000 -> 0x40000000-0x80000000    
154     for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
155         phys = va;
156         addr[va >> 20] = phys | 2;
157     }
158 
159     //0x10000000-0x14000000 -> 0x10000000-0x140000000    
160     for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
161         phys = va;
162         addr[va >> 20] = phys | 2;
163     }
164     //0x10000000-0x14000000 -> 0x10000000-0x140000000    
165     for(va = 0x0; va < 0x10000000; va += 0x100000) {
166         phys = va + 0x70000000;
167         addr[va >> 20] = phys | 2;
168     }
169             
170 }

 运行结果如下:

原文地址:https://www.cnblogs.com/wenqiang/p/4778349.html