Tiny4412之外部中断
一:外部中断
在之前我们学习按键驱动的时候,我们检测按键有没有按下是通过轮循的方式(也就是我们说的死循环),这样虽然可以检测实现按键,但太浪费系统资源了,不论我们按键中断有没有发生,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之外部中断的更多相关文章
- Exynos4412的外部中断是如何安排的?
作者 彭东林 pengdonglin137@163.com 平台 Linux4.9 tiny4412 概述 结合tiny4412开发板分析一下Exynos4412的外部中断是如何组织的. ...
- STM32f103之外部中断
一.背景 有个需求,IO口检测上升沿,然后做相应的动作.在此记录STM32F103的外部中断结构及配置方法, 以备下次快速上手使用. 有许多不太明白,又是老司机(:-D)帮忙,真的是站在别人的肩膀上会 ...
- STM32之EXTI——外部中断
互联网的广大网友,大家早上中午晚上好.EXTI...故名思义..EX表外,出..I表示Intrrupt..所以合起来就是外部中断...说到这..我觉得我最近的六级水平(背单词)又进了一步,稍微自夸了下 ...
- 转别人的 STM32外部中断使用注意事项
前言:这些问题都是我之前在工作中遇到的,后来觉得需要总结,自己记忆不好,所以在这个给自己打个mark. 一:触发方式 STM32 的外部中断是通过边沿来触发的,不支持电平触发: 二:外部中断分组 ST ...
- STM32外部中断初理解
PA0,PB0...PG0--->EXTI0 PA1,PB1...PG1--->EXTI1 ....... PA15,PB15...PG15--->EXTI15 以上为GPIO和中断 ...
- STM32——外部中断EXIT实现
外部中断实现步骤: 一.初始化,包括:1.AFIO时钟中断和GPIO时钟使能: 2.GPIO初始化 ...
- STM32 GPIO外部中断总结
一.STM32中断分组: STM32 的每一个GPIO都能配置成一个外部中断触发源,这点也是 STM32 的强大之处.STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB ...
- 向linux内核中添加外部中断驱动模块
本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...
- STM32学习笔记(九) 外部中断,待机模式和事件唤醒
学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为 ...
随机推荐
- 为什么要使用“var me=this”这样的写法
很多人都会奇怪,为什么在Ext JS 4中会大量使用"var me=this"这样的写法,其实,在官方论坛以下地址的帖子已经给出了很好的说明: http://www.sencha. ...
- REST(Representational State Transfer表述性状态转移)
参考内容:http://www.csdn.net/article/2013-06-13/2815744-RESTful-API 定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的 Web ...
- Orientation Auto Rotation旋转屏幕crash问题(Unity3D开发之十四)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/44133127 ...
- DEVICE_ATTR实例分析
在内核中, sysfs 属性一般是由 __ATTR 系列的宏来声明的,如对设备的使用 DEVICE_ATTR ,对总线使用 BUS_ATTR ,对驱动使用 DRIVER_ATTR ,对类别(class ...
- iOS和OS X中的bundle
bundle也可以称之为包(package). 它在iOS和OS X中实际为一个文件夹但却当成单独的文件来对待. 每一个app都有一个bundle,并且你可以通过在xxx.app图标上右击鼠标然后选择 ...
- cocos2D v3.x中动作回调函数的变化
cocos2D v3.x版本中的动作的回调函数不能再带任何参数并且不能返回任何值. 官方给出的传递参数的办法是: 选择器(selector)不能带有任何形参,选择器需要的参数必须通过ivar或prop ...
- Android特效专辑(十二)——仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View
Android特效专辑(十二)--仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术 ...
- 色彩转换——RGB & HSV
RGB to HSV The R,G,B values are divided by 255 to change the range from 0..255 to 0..1: R' = R/255 G ...
- ExtAspNet页面跳转的方法
一:如果在Page_Load中则可以用Response.Redirect("ABC.aspx"); 二:在其它事件中可以用以下方法: protected void Button1_ ...
- Android TV listView焦点平滑移动
先上TV上效果图 Mark下思路: package com.test.ui; import java.lang.reflect.Method; import android.annotation.Su ...