上一篇讲到android驱动开发中,应用是怎样去操作底层硬件的整个流程,实现了按键控制led的亮灭。当然,这是一个非常easy的实例,只是略微演变一下,就能够得到广泛的应用。
如开发扫描头,应用透过监听上报的按键的键值,监听到,则调用扫描头的模块。成功,则点亮LED灯,并把扫描头解码后的条码信息。通过广播的形式发出。又扯到其他地方,这里主要说说中断。
1. 中断的一些概念
中断,是什么?
中断。能够看成是cpu对特殊事件的一种处理的机制,这类特殊事件一般指紧急事件或者说异常事件。非常easy的一个样例,你拿你手机正在看视频,来了一个电话。你接完电话,还是停在视频。本来你的cpu正在运行看视频这一系列的指令处理。但当接收到电话,会产生一个中断,cpu依据优先级推断。优先级高于当前则停止当前工作。并保存,然后运行中断的处理函数,其中断这一系列的事件处理完成以后。再运行保存在暂停队列中的工作。这是一个外部中断的样例。
那么中断,是指 CPU 在运行程序的过程中,出现了某些突发事件时 CPU 必须暂停运行当前的程序,转去处理突发事件,处理完成后 CPU 又返回原程序被中断的位置并继续运行。依据中断的来源,中断可分为内部中断和外部中断,内部中断的中断源来自 CPU内部(软件中断指令、溢出、除法错误等,比如,操作系统从用户态切换到内核态需借助 CPU 内部的软件中断),外部中断的中断源来自 CPU 外部,由外设提出请求。
中断,实现它的机制?
中断。当外设发出一个中断信号,cpu则依据中断信号,来进行分析处理,依据中断信号所对于的地址。去调用中断处理函数。所以。中断处理函数。是值该中断产生后,cpu应该去紧急运行的事件。
那么,这里主要解说一下中断处理函数的机制。
s5pv210是arm架构的芯片,当中断的资源很的丰富,这里有32个外部中断和其余的gpio中断。一般。实际开发中,中断主要由外设发出。所以,这里我们基本都是用的外部中断。採用外部中断的 CPU 通常为不同的中断分配不同的中断号,当检測到某中断号的中断到来后,就自己主动跳转到与该中断号相应的地址运行。
不同中断号的中断有不同的入口地址。
中断处理机制,,Linux 将中断处理程序分解为两个半部:顶半部(top half)和底半部(bottom half)。
在这两者重要的差别,顶半部,不可被中断,而底半部,能够被新的中断打开。那么,这两者之前的差别,就认为了它们各自独特的特性。顶半部,不可被打断,所以注定它的运行时间要很很的高速,所以一般它仅仅是简单的读取寄存器的中断状态并清楚中断标志,然后就把底半部处理程序挂究竟半部运行队列中。而这样,中断处理的大部分工作就落究竟半部了。由于可被打断,相对来说,时间就比較充足。运行一些耗时的任务。
底半部的三种方式:软中断、tasklet、工作队列。
这里有个博文链接。主要将三种机制以及之间的差异。http://blog.chinaunix.net/uid-20768928-id-5077401.html
中断,当中关键的一些函数?
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
irq:中断号,这里由gpio_to_irq()方法得到。
handler:发生中断时首先要运行的硬中断处理函数,这个函数能够通过返回 IRQ_WAKE_THREADED唤醒中断线程,也可返回IRQ_HANDLE不运行中断线程
thread_fn : 中断线程,类似于中断下半部,若传參为null,则和request_irq()一样
qflags:中断标志。备注:IRQF_SHARED 共享中断时,dev_id不能为空。由于释放irq时要区分哪个共享中断。
devname:中断名
dev_id: 传给中断处理函数的參数。
2.简单的实例:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <mach/gpio.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/wait.h>
#include <linux/sched.h> #include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h> static struct class *buttondrv_class;
static struct device *buttondrv_class_dev;
int major;
volatile unsigned long *GPCCON;
volatile unsigned long *GPCDAT;
//static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static unsigned char key_val;
static volatile int ev_press = 0;
struct pin_desc{
unsigned int pin;
unsigned int key_val;
};
struct pin_desc pins_desc[2] = {
{S5PV210_GPH3(7), 0x01},
};
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>buttons_irq\n");
struct pin_desc *pindesc = (struct pin_desc *)dev_id;
unsigned int pinval; pinval = gpio_get_value(pindesc->pin);
printk("irq >>>>>>>>>>>>>>>>>>>>>>>>>>>>pinval =%d \n",pinval);
if (pinval)
{
key_val = 0x80 | pindesc->key_val;
printk("1111 >>>>>>>>>>>>>>>>>>>>>>>>>>>key_val =%d \n",key_val);
}
else
{
key_val = pindesc->key_val;
printk("0000 >>>>>>>>>>>>>>>>>>>>>>>>>>>key_val =%d \n",key_val); }
ev_press = 1;
// wake_up_interruptible(&button_waitq);
return IRQ_RETVAL(IRQ_HANDLED);
} static int button_drv_open(struct inode *inode, struct file *file)
{
printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>button_drv_open\n");
int ret=-1;
s3c_gpio_setpull(S5PV210_GPH3(7), S3C_GPIO_PULL_NONE);
ret = request_threaded_irq(gpio_to_irq(S5PV210_GPH3(7)), NULL,
buttons_irq,
IRQF_TRIGGER_RISING,
"s2", &pins_desc[0]);
printk("ret=%d irq=%d >>>>>>>>>>>>>>>>>>>>>>>>>\n ",ret,gpio_to_irq(S5PV210_GPH3(7)));
return 0;
} int button_drv_close(struct inode *inode, struct file *file)
{
free_irq(gpio_to_irq(S5PV210_GPH3(7)), &pins_desc[0]);
return 0;
} static int button_drv_read(struct file *filp, char __user *buf,
size_t count, loff_t *offp)
{
printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>button_drv_read\n");
if (count != 1)
return -EINVAL;
printk("read >>>>>>>>>>>>>>>>>>>>>>>>>>>key_val =%d \n",key_val);
// wait_event_interruptible(button_waitq, ev_press);
copy_to_user(buf, &key_val, 1);
key_val=0;
ev_press = 0;
return 1; } static struct file_operations button_drv_fops = {
.owner = THIS_MODULE,
.open = button_drv_open,
.read = button_drv_read,
.release = button_drv_close,
}; static int button_drv_init(void){
printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>button_drv_init\n"); GPCCON = (volatile unsigned long *)ioremap(0xE0200C60, 8);
GPCDAT= GPCCON + 1;
if (!GPCCON) {
return -EIO;
}
major = register_chrdev(0, "button_drv", &button_drv_fops);
buttondrv_class = class_create(THIS_MODULE, "buttondrv");
buttondrv_class_dev = device_create(buttondrv_class, NULL, MKDEV(major, 0), NULL, "button");
return 0;
} static void button_drv_exit(void){
printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>button_drv_exit\n");
unregister_chrdev(major, "button_drv");
device_unregister(buttondrv_class_dev);
class_destroy(buttondrv_class);
iounmap(GPCCON); } module_init(button_drv_init);
module_exit(button_drv_exit);
MODULE_LICENSE("GPL");
关于代码一些简单的说明:
static DECLARE_WAIT_QUEUE_HEAD(button_waitq)
wake_up_interruptible(&button_waitq)
wait_event_interruptible(button_waitq, ev_press)
这个是等待队列的机制,当有中断的时候。唤醒。把事件增加工作队列中,处理完事件后。继续休眠,直到下次中断。
3.关于一些调试方法:
一般在编写中断的程序,最基本的是要看,gpio口的中断号是否申请成功。这里主要依据打印语句进行调试了。
若驱动程序不报错误了,则可进入android系统下,cat proc/interrupts ,可查看到你申请成功的中断。
初入android驱动开发之字符设备(四-中断)的更多相关文章
-
初入android驱动开发之字符设备(一)
大学毕业,初入公司,招进去的是android驱动开发工程师的岗位,那时候刚进去,首先学到的就是如何搭建kernel.android的编译环境,然后就是了解如何刷设备以及一些最基本的工具.如adb.fa ...
-
驱动开发--【字符设备、块设备简介】【sky原创】
驱动开发 字符设备,块设备,网络设备 字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问 EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是 ...
-
Linux驱动开发2——字符设备驱动
1.申请设备号 #include <linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char ...
-
Linux驱动开发之字符设备模板
/***************************** ** 驱动程序模板* 版本:V1* 使用方法(末行模式下):* :%s/xxx/"你的驱动名称"/g********* ...
-
Linux驱动开发之字符设备驱动模型之file_operations
90%的驱动模型都是按照下图开发的 下面来说下设备描述结构是什么东西 打开Linux-2.6.32.2的Source Insight 工程,搜索cdev 比如一个应用程序需要调用read和write这 ...
-
Android驱动开发5-8章读书笔记
Android驱动开发读书笔记 第五章 S5PV210是一款32位处理器,具有 ...
-
Android驱动开发前的准备
最近看了一些Android驱动开发前需要知道的资料,收获很多,接下来就谈谈我自己的一些心得体会. Android在近几年时间发展迅速,已经成为智能手机操作系统的老大.不过,因为Android原生的代码 ...
-
LCD驱动分析(一)字符设备驱动框架分析
参考:S3C2440 LCD驱动(FrameBuffer)实例开发<一> S3C2440 LCD驱动(FrameBuffer)实例开发<二> LCD驱动也是字符设备驱动,也 ...
-
Android安卓书籍推荐《Android驱动开发与移植实战详解》下载
百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与 ...
随机推荐
-
iOS中类方法的作用
类方法,这意味着你将它发送给类,而不是对象实例. 因为不是发送给一个实例,所以你不能使用任何实例变量,你只能做一些通用性的事情. 实际上类方法只用于两种情况: 1.创建事物,比如创建一个特殊格式的字符 ...
-
嵌入式 H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
一.MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二.MP4封装格式核心概念 1 MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象 ...
-
IT English Collection(16) of Message
1 前言 本文介绍了关于Objective-C中的消息机制,详情如下. 转载请注明出处:http://blog.csdn.net/developer_zhang 2 详述 2.1 原文 A messa ...
-
JMS详细的工作原理【转】
如果手机只能进行实时通话,没有留言和短信功能会怎么样?一个电话打过来,正好没有来得及接上,那么这个电话要传递的信息肯定就收不到了.为什么不能先将信息存下来,当用户需要查看信息的时候再去获得信息呢?伴随 ...
-
sql分页比较简单快捷的方法
SELECT TOP 显示数量* FROM 表 WHERE (主键id>(SELECT MAX(主键id) FROM(SELECT TOP 页码数*显示数量 主键id FROM 表 ORDER ...
-
python基础0
1.运行:D:\tools\python\python-2.7.10.amd64=>安装到c:\python 2.环境变量:path:c:\Python27 3.cmd:python回车 //s ...
-
Linux入门篇(三)——文件与目录
这一系列的Linux入门都是本人在<鸟哥的Linux私房菜>的基础上总结的基本内容,主要是记录下自己的学习过程,也方便大家简要的了解 Linux Distribution是Ubuntu而不 ...
-
asp.net MVC 5 路由 Routing
ASP.NET MVC ,一个适用于WEB应用程序的经典模型 model-view-controller 模式.相对于web forms一个单一的整块,asp.net mvc是由连接在一起的各种代码层 ...
-
css3新属性box-orient
前言 box-orient属性经常与display:box属性结合使用 div { width:350px; height:100px; border:1px solid black; /* Fire ...
-
HDU2873 Bomb Game(二维SG函数)
Bomb Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...