ok6410按键中断编程,linux按键裸机
6410按键中断编程
一、流程分析
外部中断控制寄存器(s3c6410x 359页)
1、EINTxCONy: 外部中断组x的第y个控制器。这个就是设置中断的触发方式。有5种触发方式。
2、EINTxFLTCONy:外部中断组x的第y个滤波功能控制器。S3C6410对于外部中断有滤波功能,这个就是用来设置滤波功能。有延迟滤波,有数字滤波。滤波,可以用来滤掉毛刺信号。在以前51做按键外部中断,按键是有抖动的,就需要一个去抖动的一个东西。但是有了这个滤波的话,直接设定滤波的时间,就可以滤掉这一段时间的毛刺了。就不用再加去抖动的程序了。
3、EINTxMASK:外部中断组x的屏蔽寄存器。用来使能中断的。当要使用某个中断的时候,就需要让这个中断使能,就需要在这个寄存器中的对应位写入0,来打开中断。默认为中断都是屏蔽的。
4、EINTxPEND:外部中断组x的中断挂起寄存器。这个寄存器就是用来保存中断的状态的。当对应的中断产生时,对应的位为1。当中断处理完毕后,需要往对应对写入1进行清除。
1.1设置引脚为中断模式
初始化中断源,也就是设置中断源是什么,以及中断的触发方式(高电平,低电平,上边沿,下降沿,双边沿)
#define GPNCON (volatile unsigned long*)0x7f008830
void button_init()
{
*(GPNCON) = 0xaaa;
}
1.2中断控制器
初始化中断控制器,也就是使能对应的中断,让中断信号能够传递到CPU。在这里还需要设置中断优先级,中断滤波等与中断的相关设置
这两个是中断控制器,分别管理各自的32个中断(6410数据手册410页)
为了节约中断,不可能为每个外部管脚都分配一个中断号,所以就会把某几个外部中断给合并成一个中断号。例如,对于外部中断0-3,就合并成了一个中断号,INT_EINT0。当这4个中断有任意一个产生中断时,INT_EINT0会挂起,CPU就会知道产生了外部中断0-3中断,然后去执行中断处理,在中断服务程序中,为了知道具体是哪一个中断,还需要去查询寄存器以知道是哪一个中断产生。
S3C6410中断处理有向量模式和非向量方式。因为要与之前的ARM系列兼容,所以保存了非向量方式。
1.3中断触发方式
//配置按键中断下降沿出发
*(EINT0CON0) = 0x222;
1.4取消中断屏蔽
//打开外部中断(取消中断屏蔽)
*(EINT0MASK) = 0;
1.5使能中断号
//使能外部中断号
*(VIC0INTENABLE) = 0x00000003;
1.6编写中断处理入口
//将函数地址赋给中断处理程序
*(VIC0VECTADDR0) = (int)key1_lsr;
*(VIC0VECTADDR1) = (int)key2_lsr;
1.7开启向量中断
1.8打开总中断
1.9编写中断服务函数
在中断函数前和中断函数末尾都有使用嵌入汇编。这段代码是固定的。目的是为了保存环境,将r0-r12,lr寄存器的值给压入栈中,然后执行完后,在将这些值返回给r0-r12,pc寄存器。这样r0-r12寄存器的内容就恢复了,同时pc得到返回地址,就返回到中断前的程序地址去了。
这里有sub lr,lr,#4。将lr的值减去4。这个原因就要从ARM的流水线说起了。ARM采用流水线,取址,译码,执行。所以pc的值永远是当前执行指令的地址+8.
中断跳转的时候,会将pc的值给lr,pc的值为当前执行程序地址+8,lr的值就是pc的值。而返回的地址应该是执行阶段的下一条地址,也就是当前执行程序地址+4,所以直接返回lr的值就不对了,应该返回lr-4的值。
中断处理完后,需要将中断挂起位给清零。这里,很简单的将所有中断位都给清零。然后再将中断执行地址给清0。
这个寄存器,当执行中断函数的时候,值是中断函数的入口地址。往这个寄存器写入任意的值,就清除这个中断了。所以最后需要将这个寄存器给清0。
if((0x01 & GPNDAT) == 0)
led_on(1);
因为外部中断源INT_EINT0里面包含外部0~3四个外部中断,所以要通过相应I/O口寄存器数据判断是哪个中断被触发。
二、源代码如下:
/*interrupt registes*/
#define EXT_INT_0_CON *((volatile unsigned int *)0x7f008900)
#define EXT_INT_0_MASK *((volatile unsigned int *)0x7f008920)
#define EXT_INT_0_PEND *((volatile unsigned int *)0x7f008924) #define VIC0INTENABLE *((volatile unsigned int *)0x71200010) #define EINT0_VECTADDR *((volatile unsigned int *)0x71200100)
#define EINT5_VECTADDR *((volatile unsigned int *)0x71200104) #define VIC0ADDRESS *((volatile unsigned int *)0x71200f00)
#define VIC1ADDRESS *((volatile unsigned int *)0x71300f00) #define GPNDAT *((volatile unsigned int *)0x7F008834)
void key1_handle()
{
__asm__( "sub lr, lr, #4\n"
"stmfd sp!, {r0-r12, lr}\n"
:
:
);
if((0x01 & GPNDAT) == )
led_on();
if((0x02 & GPNDAT) == )
led_on();
if((0x04 & GPNDAT) == )
led_on();
if((0x08 & GPNDAT) == )
led_on();
/* 清除中断 */
EXT_INT_0_PEND = ~0x0;
VIC0ADDRESS = ;
VIC1ADDRESS = ; __asm__(
"ldmfd sp!, {r0-r12, pc}^ \n"
:
:
); } void key6_handle()
{
__asm__( "sub lr, lr, #4\n"
"stmfd sp!, {r0-r12, lr}\n"
:
:
);
if((0x10 & GPNDAT) == )
led_on();
if((0x20 & GPNDAT) == )
led_off();
/* 清除中断 */
EXT_INT_0_PEND = ~0x0;
VIC0ADDRESS = ;
__asm__(
"ldmfd sp!, {r0-r12, pc}^ \n"
:
:
);
} void init_irq()
{
EXT_INT_0_CON = 0x222; /* 配置为下降沿触发 */ EXT_INT_0_MASK = ; /* 取消屏蔽外部中断 */ VIC0INTENABLE = 0x00000003; /* 使能外部中断*/ EINT0_VECTADDR = (int)key1_handle; /* 用户按下key时,CPU就会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS并跳转到这个地址去执 */
EINT5_VECTADDR = (int)key6_handle; __asm__( "mrc p15,0,r0,c1,c0,0\n"
"orr r0,r0,#(1<<24)\n"
"mcr p15,0,r0,c1,c0,0\n" "mrs r0,cpsr\n"
"bic r0, r0, #0x80\n"
"msr cpsr_c, r0\n"
:
:
);
}
当然还有还有IO初始化设置
#define GPNCON (volatile unsigned long*)0x7f008830 void button_init()
{
*(GPNCON) = 0x00000aaa; //设置按键1到按键6
}
ok6410按键中断编程,linux按键裸机的更多相关文章
- 专题2-通过按键玩中断\2440按键中断编程lesson2
1.程序优化 修改Makefile 把main.c里面的mmu代码复制到mmu.c并修改如下 main.c的修改 由于在bootloader当中一般不会使用MMU,所以 main.c 加入led.c文 ...
- 14.linux按键驱动程序(一)
按键驱动程序 本文学习主要包含按键硬件的实现.中断分层管理.按键定时器去抖.阻塞性驱动程序设计.这里面需要使用到混杂设备驱动和中断处理程序的内容. 一.创建按键混杂设备驱动模型 int key_ope ...
- Linux按键设备驱动一
① request_irq函数用于注册中断 int request_irq(unsigned int irq, void(*handler)(int, void*, struct pt_reg*), ...
- 在Linux下的中断方式读取按键驱动程序
// 在Linux下的中断方式读取按键驱动程序 //包含外部中断 休眠 加入poll机制 // 采用异步通知的方式 // 驱动程序发 ---> app接收 (通过kill_fasync()发送) ...
- 字符设备驱动笔记——中断方式按键驱动之linux异常处理结构(四)
.中断方式获取按键值 单片机: )按键按下 )cup发生中断,跳转到异常向量入口执行 )b 函数 a.保存被中断的现场 b.执行中断处理函数 c.恢复 linux: )trap_init()函数构造异 ...
- Linux按键驱动程序设计--从简单到不简单【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51399353 混杂设备驱动模型: 1. 混杂设备描述 在Linux系统中,存在一 ...
- Linux按键驱动程序设计详解---从简单到不简单【转】
转自:http://blog.csdn.net/coding__madman/article/details/51399353 版权声明:本文为博主原创文章,未经博主允许不得转载. 混杂设备驱动模型: ...
- 15.linux按键驱动程序(二)
linux按键驱动程序 包含内容定时器延时去抖动,阻塞型设备驱动设计 一.定时器延时去抖 按键所用开关为机械弹性开关,当机械触点断开.闭合时,由于机械触点的弹性作用,开关不会马上稳定地接通或断开.因而 ...
- 全志A33 lichee 开发板 Linux中断编程原理说明
开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 本节实验目标实现按键触发中断 ...
随机推荐
- [k]web页面-browser兼容问题-1
1:空的a标签在IE7/8下不能点击(2015-05-22) html代码: <ul class='oUl'><li><a href="#"> ...
- 2小时入门Robot Framework
1.介绍 1.1.介绍Robot Robot Framework是一个基于关键字驱动的自动化测试框架.通过该框架,测试人员可使用python封装关键字,并在非代码环境下使用关键字构建可被执行的测试用例 ...
- linux琐碎知识点
1.awk的使用方式,pattern支持正则表达式 awk 'pattern{action}' {filenames} 其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找 ...
- MySQL中的增删改查
将表cm_application中的state字段类型改为字符串型 alter table cm_application modify STATE varchar(50); 将表cm_applic ...
- bootstrap-datepicker的使用
转载自:http://michael-roshen.iteye.com/blog/1779541 在普通的网页中显示datepicker比较简单,将bootstrap-datepicker-zh_CN ...
- jquery-validation-1.13.1 自定义验证正则
/*** check Mobile***********************/ jQuery.validator.addMethod("isMobile", function( ...
- Keepalived虚拟ip
linux下如何设置vip(虚拟ip) 在做HA的时候需要为服务器设计虚拟IP,也就是一个主机对应多个IP地址?刚听起来好神奇,原来这样也是可能的看了下面的这个链接 自己配了一下http://hi.b ...
- IOS- 内存管理机制
iOS平台内存常见问题 作为iOS平台的开发者,是否曾经为内存问题而苦恼过?内存莫名的持续增长,程序莫名的crash,难以发现 的内存泄漏,这些都是iOS平台内存相关的常见问题:本文将会详细介绍iOS ...
- 根据OSG中的ref_ptr和Reference简化的智能指针
main.cpp测试代码 #include "TestSmartPointer" void fun() { SP<TestSmartPointer> sp1=new T ...
- Git命令之从GitHub上下载开源项目
1,先在本地创建一个目录,作为本地仓库,如: 2,使用Git init 初始化仓库,git初始化完成后,会生成一个隐藏的git文件如: 3,clone Git项目,如: 4,这个项目就是合Github ...