一:外部中断  

   在之前我们学习按键驱动的时候,我们检测按键有没有按下是通过轮循的方式(也就是我们说的死循环),这样虽然可以检测实现按键,但太浪费系统资源了,不论我们按键中断有没有发生,cpu都要一直进行检测;这样操作系统就不能做其他事情了,因此这样肯定是不可取得,因此我们可以通过外部中断解决它;

  要处理一个中断,我们需要了解模式,而了解模式,有需要了解mmu;在学习这些之后我们就可以返回来处理我们按键驱动的时候留下的问题了;

  通过之前的按前驱动我们已经了解了按前驱动在板子上的位置以及按键的电路图以及他的引脚作用,下面我们就如何实现这个程序的步骤:

  我们知道控制按键的寄存器为:

外部中断对应的是:

0xf = EXT_INT43[2]

在EXT_INT43[2]中我们选择边沿触发方式:

通过key在核心板的引脚图我们可以知道外部中断源为26,中断号为64

需要我们配置的寄存器:

(1) EXT_INT43PEND (2)EXT_INT43MASK  (3)EXT_INT43CON

需要注意的是:中断状态:EXT_INT43_PEND[2],特别注意的是,要清中断,将值赋值为1.

  实现一个外部中断大致需要五步:

  (1)cpu允许中断

  (2)启用GIC

  (3)配置外部中断寄存器(xeint)

  (4)配置gpio(General Purpose Input Output (通用输入/输出)简称为GPIO,每个GPIO端口可通过软件分别配置成输入或输出)

  (5)外部中断源

下面是实现的具体代码:

 #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 ICDIPR0_CPU0 (*(volatile unsigned long *)0x10490400)
#define ICDIPTR0_CPU0 (*(volatile unsigned long *)0x10490800)
#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)
#define ICDIPR2_CPU0 (*(volatile unsigned long *)0x10490408)
#define ICDIPTR2_CPU0 (*(volatile unsigned long *)0x10490808)
#define ICDIPR3_CPU0 (*(volatile unsigned long *)0x1049040c)
#define ICDIPTR3_CPU0 (*(volatile unsigned long *)0x1049080c)
#define ICDIPR16_CPU0 (*(volatile unsigned long *)0x10490440)
#define ICDIPTR16_CPU0 (*(volatile unsigned long *)0x10490840)
#define ICDIPR18_CPU0 (*(volatile unsigned long *)0x10490448)
#define ICDIPTR18_CPU0 (*(volatile unsigned long *)0x10490848)
#define ICDISER2_CPU0 (*(volatile unsigned long *)0x10490108) #define WTCON (*(volatile unsigned long *)0x10060000)
#define WTDAT (*(volatile unsigned long *)0x10060004)
#define WTCNT (*(volatile unsigned long *)0x10060008)
#define WTCLRINT (*(volatile unsigned long *)0x1006000C) #define EXT_INT43_CON (*(volatile unsigned long *)0x11000e0c)
#define EXT_INT43_MASK (*(volatile unsigned long *)0x11000f0c)
#define EXT_INT43_PEND (*(volatile unsigned long *)0x11000f4c)
#define GPX3CON (*(volatile unsigned long *)0x11000c60) #define GPM4CON (*(volatile unsigned long *)0x110002e0)
#define GPM4DAT (*(volatile unsigned long *)0x110002e4) #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, 0x10000);
enable_mmu(); *(unsigned long *)0x47000000 = do_irq; //step 1: cpu permit interrupt
__asm__ __volatile__ (
"mrs r0, cpsr\n"
"bic r0, r0, #0x80\n"
"msr cpsr, r0\n"
::: "r0"
); //step 2: GIC (cgi) enable
ICCICR_CPU0 = ;//总开关
ICCPMR_CPU0 = 0xff;//总优先级(门槛)
ICDDCR = ; //本中断开关 ICDIPR16_CPU0 = ( << ); //本中断优先级
ICDIPTR16_CPU0 = ( << ); //目标cpu
ICDISER2_CPU0 = ( << ); //启用本中断 //step 3: Xeint
EXT_INT43_CON = ( << );//Triggers Both edge (设置为边沿触发)
EXT_INT43_MASK = ; //开启中断 //step 4: set gpio
GPX3CON = (0xf << ); //0xF = EXT_INT43[2] (gpio配置为外部中断)

//step 5: interrupt source printf("welcome back\n");
} void do_irq()
{
unsigned long data = ICCIAR_CPU0;
int irq = data & 0x3ff; //获得中断号
int cpu = (data >> ) & 0x7; //获得目标cpu
ICCEOIR_CPU0 = irq | (cpu << ); //清除中断
EXT_INT43_PEND |= ( << ); //清中断
printf("key 1 down, cpu is %d, irq is %d\n", cpu, irq);
} void enable_mmu()
{
unsigned long addr = 0x50000000;
init_table(addr);
unsigned long mmu = ;
mmu = | ( << ) | ( << ) | ( << ); __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"
:
: "r" (addr), "r" (mmu)
:
);
} void init_table(unsigned long *addr)
{
unsigned long va = ;
unsigned long phys = ; for(va = 0x40000000; va < 0x80000000; va+=0x100000)
{
phys = va;
addr[va >> ] = phys | ;
} for(va = 0x10000000; va < 0x14000000; va+=0x100000)
{
phys = va;
addr[va >> ] = phys | ;
} for(va = 0x0; va < 0x10000000; va+=0x100000)
{
phys = va + 0x70000000;
addr[va >> ] = phys | ;
}
} __asm__ (
"vector:\n"
" b reset\n"
" b undefined\n"
" b swi\n"
" b pre_abt\n"
" b data_abt\n"
" .word 0x0\n"
" b irq\n"
" b fiq\n" "reset:\n"
"undefined:\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" "mov 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 memcpy(unsigned char *dest, unsigned char *src, int len)
{
int i = ;
for(i = ; i < len; i++)
dest[i] = src[i];
}

  下面我们通过外部中断(KEY1)控制watchdog,在通过watchdog控制led灯,当key1按下时,led灯开始闪烁,再次按下停止闪烁:

  下面贴出代码:

  

 #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 ICDIPR0_CPU0 (*(volatile unsigned long *)0x10490400)
#define ICDIPTR0_CPU0 (*(volatile unsigned long *)0x10490800)
#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)
#define ICDIPR2_CPU0 (*(volatile unsigned long *)0x10490408)
#define ICDIPTR2_CPU0 (*(volatile unsigned long *)0x10490808)
#define ICDIPR3_CPU0 (*(volatile unsigned long *)0x1049040c)
#define ICDIPTR3_CPU0 (*(volatile unsigned long *)0x1049080c)
#define ICDIPR16_CPU0 (*(volatile unsigned long *)0x10490440)
#define ICDIPTR16_CPU0 (*(volatile unsigned long *)0x10490840)
#define ICDIPR18_CPU0 (*(volatile unsigned long *)0x10490448)
#define ICDIPTR18_CPU0 (*(volatile unsigned long *)0x10490848)
#define ICDISER2_CPU0 (*(volatile unsigned long *)0x10490108) #define WTCON (*(volatile unsigned long *)0x10060000)
#define WTDAT (*(volatile unsigned long *)0x10060004)
#define WTCNT (*(volatile unsigned long *)0x10060008)
#define WTCLRINT (*(volatile unsigned long *)0x1006000C) #define EXT_INT43_CON (*(volatile unsigned long *)0x11000e0c)
#define EXT_INT43_MASK (*(volatile unsigned long *)0x11000f0c)
#define EXT_INT43_PEND (*(volatile unsigned long *)0x11000f4c)
#define GPX3CON (*(volatile unsigned long *)0x11000c60) #define GPM4CON (*(volatile unsigned long *)0x110002e0)
#define GPM4DAT (*(volatile unsigned long *)0x110002e4) #endif //__BUNFLY_H
 #include "bunfly.h"

 void (*udelay)(int) = 0xc3e25f90;
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();
void led_on();
void led_off();
void wdt_on();
void wdt_off(); int main()
{
memcpy(0x70000000, vector_start, 0x1000);
enable_mmu(); *(unsigned long *)0x47000000 = do_irq; //step 1: cpu permit interrupt
__asm__ __volatile__(
"mrs r0, cpsr\n"
"bic r0,r0, #0x80\n"
"msr cpsr, r0\n"
:::"r0"
); //step 2: GIC (cgi) enable
ICCICR_CPU0 = ; //总开关
ICCPMR_CPU0 =0xff;//总优先级
ICDDCR = ; //本中断开关 //KEY
ICDIPR16_CPU0 = ( << );//本中断优先级
ICDIPTR16_CPU0 = ( << );//目标cpu
ICDISER2_CPU0 = ( << );//启用本中断 //WDT
ICDIPR18_CPU0 = ( << );
ICDIPTR18_CPU0 = ( << );
ICDISER2_CPU0 = ( << ); //step 3: Xeint
EXT_INT43_CON = (0x2 << );
EXT_INT43_MASK = ; //step 4: set gpio
GPX3CON = (0xf << ); //step 5: interrupt source printf("welcom back\n"); } void do_irq()
{
unsigned long data = ICCIAR_CPU0;
int irq = data & 0x3ff;
int cpu = (data >> ) & 0x7;
ICCEOIR_CPU0 = irq | (cpu << );
static int flags = ; if( == irq) {
printf("key 1 down\n");
if(EXT_INT43_PEND & (0x1 << )) {
EXT_INT43_PEND |= ( << );
if(flags) {
wdt_on();
flags = ;
}
else {
wdt_off();
led_off();
flags = ;
}
}
} if( == irq) {
WTCLRINT = ;//清中断
printf("wang wang wang ...\n");
if(flags) {
led_on();
flags = ;
}
else {
led_off();
flags = ;
}
}
} void led_on()
{
GPM4CON &= ~0xffff;
GPM4CON |= 0x1111;
GPM4DAT &= ~0xf;
} void led_off()
{ GPM4CON &= ~0xffff;
GPM4CON |= 0x1111;
GPM4DAT |= 0xf;
} void wdt_on()
{
WTCNT = 0x8000;
WTDAT = 0x8000;
WTCON = | ( << ) | ( << ) | ( << ) | ( << );
} void wdt_off()
{
WTCON = ;
} void memcpy(unsigned char *dest, unsigned char *src, int len)
{
int i = ;
for(i = ; i < len; i++) {
dest[i] = src[i];
}
} void enable_mmu()
{
/*构建表*/
unsigned long addr = 0x50000000;
init_table(addr);
/*打开mmu*/
unsigned long mmu = ;
mmu = | ( << ) | ( << ) | ( << );
__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 = ;
unsigned long phys = ; //0x40000000-0x80000000 -> 0x40000000-0x80000000
for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
phys = va;
addr[va >> ] = phys | ;
} //0x10000000-0x14000000 -> 0x10000000-0x140000000
for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
phys = va;
addr[va >> ] = phys | ;
}
//0x10000000-0x14000000 -> 0x10000000-0x140000000
for(va = 0x0; va < 0x10000000; va += 0x100000) {
phys = va + 0x70000000;
addr[va >> ] = phys | ;
} }

Tiny4412之外部中断的更多相关文章

  1. Exynos4412的外部中断是如何安排的?

    作者 彭东林 pengdonglin137@163.com   平台 Linux4.9 tiny4412   概述 结合tiny4412开发板分析一下Exynos4412的外部中断是如何组织的.   ...

  2. STM32f103之外部中断

    一.背景 有个需求,IO口检测上升沿,然后做相应的动作.在此记录STM32F103的外部中断结构及配置方法, 以备下次快速上手使用. 有许多不太明白,又是老司机(:-D)帮忙,真的是站在别人的肩膀上会 ...

  3. STM32之EXTI——外部中断

    互联网的广大网友,大家早上中午晚上好.EXTI...故名思义..EX表外,出..I表示Intrrupt..所以合起来就是外部中断...说到这..我觉得我最近的六级水平(背单词)又进了一步,稍微自夸了下 ...

  4. 转别人的 STM32外部中断使用注意事项

    前言:这些问题都是我之前在工作中遇到的,后来觉得需要总结,自己记忆不好,所以在这个给自己打个mark. 一:触发方式 STM32 的外部中断是通过边沿来触发的,不支持电平触发: 二:外部中断分组 ST ...

  5. STM32外部中断初理解

    PA0,PB0...PG0--->EXTI0 PA1,PB1...PG1--->EXTI1 ....... PA15,PB15...PG15--->EXTI15 以上为GPIO和中断 ...

  6. STM32——外部中断EXIT实现

    外部中断实现步骤: 一.初始化,包括:1.AFIO时钟中断和GPIO时钟使能:                          2.GPIO初始化                           ...

  7. STM32 GPIO外部中断总结

    一.STM32中断分组: STM32 的每一个GPIO都能配置成一个外部中断触发源,这点也是 STM32 的强大之处.STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB ...

  8. 向linux内核中添加外部中断驱动模块

    本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...

  9. STM32学习笔记(九) 外部中断,待机模式和事件唤醒

    学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为 ...

随机推荐

  1. OC语言(三)

    十九.一些规范 import系统自带的用尖括号<>来包含. 发现需求不清晰,一定要先搞明白才去做. 多文件开发,文件名和类名一致 命令行里的做法:(只是编译链接主文件,但是全部编译链接会出 ...

  2. infiniDB的论坛

    http://infinidb.co/community 包括了基本的内容. 安装目录?

  3. OpenCV 求外接矩形以及旋转角度

    程序没有写完整,大概功能就是实现了,希望大家分享学习,把他改对 // FindRotation-angle.cpp : 定义控制台应用程序的入口点. // // findContours.cpp : ...

  4. SpriteBuilder中的CCSprite9Slice是个什么鬼?

    CCSprite大家都知道,但是加上后面那一串又变成了神马呢? 我们可以首先到官方的API文档网站查一下,如下: http://www.cocos2d-swift.org/docs/api/Class ...

  5. LAV Filter 源代码分析 3: LAV Video (1)

    LAV Video 是使用很广泛的DirectShow Filter.它封装了FFMPEG中的libavcodec,支持十分广泛的视频格式的解码.在这里对其源代码进行详细的分析. LAV Video ...

  6. C语言之linux内核实现最大公约数算法

    最大公约数算法,又称欧几里德算法,至今已有几千年的历史了.在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算. 两个整数的最大 ...

  7. iPhone实现自定义多选列表

    好久没更新博客了,今天写了一个自定义的多选列表,可以跟爱学习的各位进行分享,首先我们先来看一下效果图: 一般大家都是用UITableView自己的编辑模式来实现CheckBox的,这里我们用自定义Ce ...

  8. HBase 协处理器实现二级索引

    HBase在0.92之后引入了coprocessors,提供了一系列的钩子,让我们能够轻易实现访问控制和二级索引的特性.下面简单介绍下两种coprocessors,第一种是Observers,它实际类 ...

  9. 面试之路(16)-归并排序详解(MergeSort)递归和非递归实现

    归并排序的概念及定义 归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并排序是建立 ...

  10. rails中validates_confirmation_of验证方法无效的解决办法

    rails的model中提供了很多种自带的验证方法,validates_confirmation_of可以验证变量xxx和xxx_confirmation是否相等:这可以用于验证2遍输入的密码是否一致 ...