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, cpsrn"
20 "bic r0,r0, #0x80n"
21 "msr cpsr, r0n"
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 backn");
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 interruptn");
51 printf("cup_id is %dn", cpu_id >> 10);
52 printf("ack_id is %dn", 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, #3n"
74 "MCR p15, 0, r0, c3, c0, 0n"//设置为管理员
75 "MCR p15, 0, %0, c2, c0, 0n"//设置表的地址
76 "MCR p15, 0, %1, c1, c0, 0n"//开启mmu
77 :
78 : "r" (addr), "r" (mmu)
79 :
80 );
81
82 }
83
84 __asm__(
85
86 "vector: n"
87 " b resetn"
88 " b undn"
89 " b swin"
90 " b pre_abtn"
91 " b data_abtn"
92 " .word 0x0n"
93 " b irqn"
94 " b fiqn"
95 "reset:n"
96 "und:n"
97 " mov sp, #0x47000000n"
98 " stmdb sp!, {r0-r12, lr}n"
99
100 " ldr r3, =0x47000004n"
101 " ldr r2, [r3]n"
102 " blx r2n"
103
104 " mov sp, #0x47000000n"
105 " ldmdb sp, {r0-r12, pc}^ n"
106
107 "swi:n"
108 " mov sp, #0x47000000n"
109 " stmdb sp!, {r0-r12, lr}^n"
110
111 " mov sp, #0x47000000n"
112 " ldmdb sp, {r0-r12, pc}^ n"
113
114 "pre_abt:n"
115
116 "data_abt:n"
117 " mov sp, #0x47000000n"
118 " sub lr, lr, #4n"
119 " stmdb sp!, {r0-r12, lr}n"
120
121 " ldr r3, =0x47000008n"
122 " ldr r2, [r3]n"
123 " blx r2n"
124
125 " mov sp, #0x47000000n"
126 " ldmdb sp, {r0-r12, pc}^ n"
127 "irq:n"
128
129 " mov sp, #0x47000000n"
130 " sub lr, lr, #4n"
131 " stmdb sp!, {r0-r12, lr}n"
132
133 " ldr r3, =0x47000000n"
134 " ldr r2, [r3]n"
135 " blx r2n"
136
137 " mov sp, #0x47000000n"
138 " ldmdb sp, {r0-r12, pc}^ n"
139
140 "fiq:n"
141
142 ".global vector_startn"
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 }
运行结果如下:
上一篇:Tiny4412中断之看门狗
下一篇:Tiny4412模式跳转
推荐阅读最新更新时间:2024-11-11 11:57
推荐帖子
- 单口RAM、伪双口RAM、双口RAM与FIFO的区别
- 常用到的数据缓存IP有FIFO和RAM,其中RAM又分单口RAM、伪双口RAM、双口RAM。单口与双口的区别在于,单口只有一组数据线与地址线,因此读写不能同时进行。而双口有两组数据线与地址线,读写可同时进行。FIFO读写可同时进行,可以看作是双口。双口RAM分伪双口RAM(Xilinx称为Simpletwo-dualRAM)与双口RAM(Xilinx称为truetwo-dualRAM)。伪双口RAM,一个端口只读,另一个端口只写;而双口RAM两个端口都可以读写。
- Aguilera DSP 与 ARM 处理器
- 903恒温电烙铁电路图
- 核心的IC就是运放,或者LM324,LM358,通过双向可控硅来控制加热芯通断!温度控制采用热电偶,或者热敏电阻;电源采用220VAC直接RC降压。成本比较低廉,损坏之后可以参考此电路进行维修!903恒温电烙铁电路图903恒温电烙铁,通过运放温度控制双向可控硅来控制加热芯通断!下来看一看,学一学ok是用变压器降压的吗模糊到爆炸
- threetigher 家电维修集锦
- 关于testbench连接模块的问题
- 编了一个程序,用quartus调用modelsim的时候出现了下面的这个错误。。。Error:(vsim-3389)E:/project/test2/simulation/modelsim/hm.vt(53):Port\'counter\'notfoundintheconnectedmodule(7thconnection).出问题的代码是这个位置:hmi1(.clk(clk),.data(data),.key(key),.pulse(puls
- txws007 FPGA/CPLD
- PIC基本型8 位A-D 转换器.pdf
- PIC基本型8位A-D转换器很详细的介绍8位AD转换器原理和装配图内型,PDF电子书PIC基本型8位A-D转换器.pdf
- rain Microchip MCU
- 最后一天!有奖直播 | RSL15 - 安森美更高效更智能更安全的 BLE 5.2 蓝牙芯片
- 直播时间:2022年03月31日(周四)上午10:00-11:30直播主题:RSL15-安森美更高效更智能更安全的BLE5.2蓝牙芯片预约报名直播内容:从BLE背景以及市场分析着手,介绍安森美BLE家族并重点解析安森美最新推出的BLE5.2蓝牙芯片RSL15的新功能,例如CryptoCell-312与TrustZone安全性支持,AngleofArrival(AoA)与AngleofDeparture
- EEWORLD社区 RF/无线
- verilog如何用矩阵键盘按三次输入三位数(0-999)?
- verilog如何用矩阵键盘按三次输入三位数(0-999)?modulekey4x4(clk,rst_n,row,col,key_val);inputclk;inputrst_n;inputrow;//矩阵键盘行outputregcol;//矩阵键盘列outputregkey_val;//键盘值按键每按一次只会输出一个数字,连续按需要如下处理:n
- yuxuanwlfei FPGA/CPLD