一:外部中断  

   在之前我们学习按键驱动的时候,我们检测按键有没有按下是通过轮循的方式(也就是我们说的死循环),这样虽然可以检测实现按键,但太浪费系统资源了,不论我们按键中断有没有发生,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. 【45】java的封装剖析

    类是构造对象的模板或蓝图. 封装的一些概念 从形式上看,封装不过是将数据和行为组合到一个包中,并对对象的使用者隐藏了数据的实现形式. 每个对象都包含实例域和方法.实例域的集合代表了一个集合的状态,通过 ...

  2. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  3. ruby rails_autolink不能加载的原因

    从rails 3.1.0开始,默认在ActionView::Helper::TextHelper中的auto_link方法已经被移除,放到了第三方的gem里:rails_autolink.遂想试一下其 ...

  4. List,Set,Map三种接口的区别

    set --其中的值不允许重复,无序的数据结构 list   --其中的值允许重复,因为其为有序的数据结构  map--成对的数据结构,健值必须具有唯一性(键不能同,否则值替换)   List按对象进 ...

  5. java Map遍历

    http://www.cnblogs.com/fczjuever/archive/2013/04/07/3005997.html 1. 阐述 对于Java中Map的遍历方式,很多文章都推荐使用entr ...

  6. Oracle官方文档学习路线图

  7. MySQL MEB常见用法

    1. 备份成镜像 备份: ./mysqlbackup --socket=/usr/local/mysql-advanced--linux-glibc2.-x86_64/data/mysql.sock ...

  8. Django Channels 入门指南

    http://www.oschina.NET/translate/in_deep_with_django_channels_the_future_of_real_time_apps_in_django ...

  9. Ocelot中文文档-跟踪

    Ocelot使用一个杰出的项目Butterfly 提供了跟踪功能. 为了使用跟踪,请阅读Butterfly的文档. 在Ocelot中如果你想跟踪一个ReRoute,你需要做如下事情: 在Configu ...

  10. Nowcoder84D

    Nowcoder84D 传送门 很有趣的进制转换题! 如果x满足题意,那么x+k-1一定能符合要求! 因为k-1用k进制表示就是1,-1,1+(-1)=0所以数位之和不变! 用map维护一下前缀和.就 ...