Tiny4412中断介绍
2015-09-02 13:40
267 查看
通过几天裸板驱动开发,今天对ARM的中断做一些简单总结,前面我们已经了解了ARM的7种异常模式,中断是异常模式的一种,在ARM中异常事件发生将会触发中断,但是,所有的中断都不能直接访问cpu,而是都统一由GIC(中断管理器)来管理;下面是samsung提供的模式图:
![](http://images2015.cnblogs.com/blog/794836/201509/794836-20150902130720513-1460914771.png)
其中GIC管理的中断有分为:
![](http://images2015.cnblogs.com/blog/794836/201509/794836-20150902131250903-975100450.png)
(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实现的一个程序:
头文件:
运行结果如下:
![](http://images2015.cnblogs.com/blog/794836/201509/794836-20150902130720513-1460914771.png)
其中GIC管理的中断有分为:
![](http://images2015.cnblogs.com/blog/794836/201509/794836-20150902131250903-975100450.png)
(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实现的一个程序:
头文件:
#ifndef __BUNFLY_H #define __BUNFLY_H #define ICCICR_CPU0 (*(volatile unsigned long *)0x10480000) #define ICCPMR_CPU0 (*(volatile unsigned long *)0x10480004) #define ICDDCR (*(volatile unsigned long *)0x10490000) #define ICDIPR2_CPU0 (*(volatile unsigned long *)0x10490408) #define ICDIPTR2_CPU0 (*(volatile unsigned long *)0x10490808) #define ICDISER0_CPU0 (*(volatile unsigned long *)0x10490100) #define ICDSGIR (*(volatile unsigned long *)0x10490f00) #define ICCEOIR_CPU0 (*(volatile unsigned long *)0x10480010) #define ICCIAR_CPU0 (*(volatile unsigned long *)0x1048000c) #endif //__BUNFLY_H
#include "bunfly.h" int (*printf)(char *, ...) = 0xc3e114d8; void enable_mmu(); void init_table(unsigned long *addr); void memcpy(unsigned char *dest, unsigned char *src, int len); extern unsigned long vector_start; void do_irq(); int main() { memcpy(0x70000000, vector_start, 0x1000); enable_mmu(); *(unsigned long *)0x47000000 = do_irq; //step 1: set cpu permit interrupt __asm__ __volatile__( "mrs r0, cpsr\n" "bic r0,r0, #0x80\n" "msr cpsr, r0\n" :::"r0" ); //step 2: set GIC (cgi) enable ICCICR_CPU0 = 1;//cpu接口控制寄存器(总开关) ICCPMR_CPU0 =0xff;//中断总优先级(门槛) ICDDCR = 1;//本中断开关 ICDIPR2_CPU0 = (3 << 9);//本中断优先级 ICDIPTR2_CPU0 = (1 << 9);//目标cpu ICDISER0_CPU0 = (1 << 9);//启用本中断 //step 3: set interrupt source ICDSGIR = 9 | (1 << 16); printf("welcom back\n"); } void do_irq() { unsigned long ack_id = 0; unsigned long cpu_id = 0; unsigned long data = ICCIAR_CPU0; /*clean interrupt*/ ack_id = data & 0x3ff; cpu_id = data & (0x7 << 10); ICCEOIR_CPU0 = ack_id | cpu_id; printf("this is interrupt\n"); printf("cup_id is %d\n", cpu_id >> 10); printf("ack_id is %d\n", ack_id); } void memcpy(unsigned char *dest, unsigned char *src, int len) { int i = 0; for(i = 0; i < len; i++) { dest[i] = src[i]; } } void enable_mmu() { /*构建表*/ unsigned long addr = 0x50000000; init_table(addr); /*打开mmu*/ unsigned long mmu = 0; mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8); __asm__ __volatile__ ( "mov r0, #3\n" "MCR p15, 0, r0, c3, c0, 0\n"//设置为管理员 "MCR p15, 0, %0, c2, c0, 0\n"//设置表的地址 "MCR p15, 0, %1, c1, c0, 0\n"//开启mmu : : "r" (addr), "r" (mmu) : ); } __asm__( "vector: \n" " b reset\n" " b und\n" " b swi\n" " b pre_abt\n" " b data_abt\n" " .word 0x0\n" " b irq\n" " b fiq\n" "reset:\n" "und:\n" " mov sp, #0x47000000\n" " stmdb sp!, {r0-r12, lr}\n" " ldr r3, =0x47000004\n" " ldr r2, [r3]\n" " blx r2\n" " mov sp, #0x47000000\n" " ldmdb sp, {r0-r12, pc}^ \n" "swi:\n" " mov sp, #0x47000000\n" " stmdb sp!, {r0-r12, lr}^\n" " mov sp, #0x47000000\n" " ldmdb sp, {r0-r12, pc}^ \n" "pre_abt:\n" "data_abt:\n" " mov sp, #0x47000000\n" " sub lr, lr, #4\n" " stmdb sp!, {r0-r12, lr}\n" " ldr r3, =0x47000008\n" " ldr r2, [r3]\n" " blx r2\n" " mov sp, #0x47000000\n" " ldmdb sp, {r0-r12, pc}^ \n" "irq:\n" " mov sp, #0x47000000\n" " sub lr, lr, #4\n" " stmdb sp!, {r0-r12, lr}\n" " ldr r3, =0x47000000\n" " ldr r2, [r3]\n" " blx r2\n" " mov sp, #0x47000000\n" " ldmdb sp, {r0-r12, pc}^ \n" "fiq:\n" ".global vector_start\n" "vector_start: \n" ".word vector \n " ); void init_table(unsigned long *addr) { unsigned long va = 0; unsigned long phys = 0; //0x40000000-0x80000000 -> 0x40000000-0x80000000 for(va = 0x40000000; va < 0x80000000; va += 0x100000) { phys = va; addr[va >> 20] = phys | 2; } //0x10000000-0x14000000 -> 0x10000000-0x140000000 for(va = 0x10000000; va < 0x14000000; va += 0x100000) { phys = va; addr[va >> 20] = phys | 2; } //0x10000000-0x14000000 -> 0x10000000-0x140000000 for(va = 0x0; va < 0x10000000; va += 0x100000) { phys = va + 0x70000000; addr[va >> 20] = phys | 2; } }
运行结果如下:
![](http://images2015.cnblogs.com/blog/794836/201509/794836-20150902134059169-1725223191.png)
相关文章推荐
- CLR via C#(01)-.NET平台下代码是怎么跑起来的
- 转帖-linux文件系统
- 记录自己的编程记录
- jackson annotations注解详解
- python cookbook:第一章 数据结构和算法
- GNS3模拟cisco7200与实体系统联网、启动telnet、SSH2,具体操作留存
- apk防止反编译
- iOS TableView实现上拉加载更多数据
- 共享bean
- 2015年下半年的关注点
- java多选框改成左右多选下拉框
- 程序猿讨厌没有价值的任务
- 微店2016——判断给定的字符串是否是整数
- 从键盘输入字符串并输出该字符串(汇编程序)
- XCode 常用快捷键
- POJ 3150 Cellular Automaton(矩阵快速幂)
- Appium+Robotframework实现iOS应用的自动化测试-4:OS X中安装和启动RIDE
- MFC状态栏的使用详解
- html 简介和基本格式
- linux下C语言如何得到调用我的函数的文件名和行号