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\n"
 20         "bic r0,r0, #0x80\n"
 21         "msr cpsr, r0\n"
 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\n");
 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\n");
 51     printf("cup_id is %d\n", cpu_id >> 10);
 52     printf("ack_id is %d\n", 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\n"
 74         "MCR p15, 0, r0, c3, c0, 0\n"//设置为管理员
 75         "MCR p15, 0, %0, c2, c0, 0\n"//设置表的地址
 76         "MCR p15, 0, %1, c1, c0, 0\n"//开启mmu
 77         :    
 78         :    "r" (addr), "r" (mmu)
 79         :
 80     );
 81 
 82 }
 83 
 84 __asm__(
 85 
 86 "vector: \n"
 87 "    b reset\n"
 88 "    b und\n"
 89 "    b swi\n"
 90 "    b pre_abt\n"
 91 "    b data_abt\n"
 92 "    .word 0x0\n"
 93 "    b irq\n"
 94 "    b fiq\n"
 95 "reset:\n"
 96 "und:\n"
 97 "    mov sp, #0x47000000\n"
 98 "    stmdb sp!, {r0-r12, lr}\n"
 99 
100 "    ldr r3, =0x47000004\n"
101 "    ldr r2, [r3]\n"
102 "    blx r2\n"
103 
104 "    mov sp, #0x47000000\n"
105 "    ldmdb sp, {r0-r12, pc}^    \n"
106 
107 "swi:\n"
108 "    mov sp, #0x47000000\n"
109 "    stmdb sp!, {r0-r12, lr}^\n"
110 
111 "    mov sp, #0x47000000\n"
112 "    ldmdb sp, {r0-r12, pc}^    \n"
113 
114 "pre_abt:\n"
115 
116 "data_abt:\n"
117 "    mov sp, #0x47000000\n"
118 "    sub lr, lr, #4\n"
119 "    stmdb sp!, {r0-r12, lr}\n"
120 
121 "    ldr r3, =0x47000008\n"
122 "    ldr r2, [r3]\n"
123 "    blx r2\n"
124 
125 "    mov sp, #0x47000000\n"
126 "    ldmdb sp, {r0-r12, pc}^    \n"
127 "irq:\n"
128 
129 "    mov sp, #0x47000000\n"
130 "    sub lr, lr, #4\n"
131 "    stmdb sp!, {r0-r12, lr}\n"
132 
133 "    ldr r3, =0x47000000\n"
134 "    ldr r2, [r3]\n"
135 "    blx r2\n"
136 
137 "    mov sp, #0x47000000\n"
138 "    ldmdb sp, {r0-r12, pc}^    \n"
139 
140 "fiq:\n"
141 
142     ".global vector_start\n"
143 "vector_start: \n"
144     ".word vector \n "
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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值