一、单片机下的中断处理
  
)分辨是哪一个中断
  )调用处理函数
  )清中断
二、linux下的中断处理 1)/arch/arm/kernel/irq.c
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc = irq_desc + irq; /*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (irq >= NR_IRQS)
desc = &bad_irq_desc; irq_enter(); desc_handle_irq(irq, desc); /* AT91 specific workaround */
irq_finish(irq); irq_exit();
set_irq_regs(old_regs);
} 2)/kernel/irq/handle.c
static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)
{
desc->handle_irq(irq, desc);
} 3)/kernel/irq/chip.c
__set_irq_handler{
...
desc->handle_irq = handle;
...
} 4)/include/linux/irq.h
static inline void
set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
{
__set_irq_handler(irq, handle, , NULL);
} 5)/arch/arm/plat-s3c24xx/irq.c
void __init s3c24xx_init_irq(void) 6)/arch/arm/plat-s3c24xx/irq.c
set_irq_handler(irqno, handle_edge_irq); 7)/kernel/irq/chip.c
调用4)
调用3)
8)在s3c24xx_init_irq这个函数里面,初始化irq_desc结构体
struct irq_desc {
irq_flow_handler_t handle_irq; //set_irq_handler(irqno, handle_edge_irq);
struct irq_chip *chip; //set_irq_chip(irqno, &s3c_irq_eint0t4);
struct msi_desc *msi_desc;
void *handler_data;
void *chip_data;
struct irqaction *action; /* IRQ action list */
unsigned int status; /* IRQ status */ ....
9)/kernel/irq/chip.c
分析handle_edge_irq:
void fastcall
handle_edge_irq(unsigned int irq, struct irq_desc *desc)
{
const unsigned int cpu = smp_processor_id(); spin_lock(&desc->lock); desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); /*
* If we're currently running this IRQ, or its disabled,
* we shouldn't process the IRQ. Mark it pending, handle
* the necessary masking and go out
*/
if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
!desc->action)) {
desc->status |= (IRQ_PENDING | IRQ_MASKED);
mask_ack_irq(desc, irq);
goto out_unlock;
} kstat_cpu(cpu).irqs[irq]++; //发生中断的次数 /* Start handling the irq */ //开始处理中断
desc->chip->ack(irq); //desc->chip chip是之前初始化的s3c_irqext_chip /* Mark the IRQ currently in progress.*/
desc->status |= IRQ_INPROGRESS; do {
struct irqaction *action = desc->action;
irqreturn_t action_ret; if (unlikely(!action)) { //判断链表是否为空
desc->chip->mask(irq);
goto out_unlock;
} /*
* When another irq arrived while we were handling
* one, we could have masked the irq.
* Renable it, if it was not disabled in meantime.
*/
if (unlikely((desc->status &
(IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
(IRQ_PENDING | IRQ_MASKED))) {
desc->chip->unmask(irq);
desc->status &= ~IRQ_MASKED;
} desc->status &= ~IRQ_PENDING;
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);//真正的处理过程
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
......
} 10)
/arch/arm/plat-s3c24xx/irq.c
s3c_irqext_chip中的.ack
static struct irq_chip s3c_irqext_chip = {
.name = "s3c-ext",
.mask = s3c_irqext_mask,
.unmask = s3c_irqext_unmask,
.ack = s3c_irqext_ack,
.set_type = s3c_irqext_type,
.set_wake = s3c_irqext_wake
};
s3c_irqext_ack分析:
static void
s3c_irqext_ack(unsigned int irqno)
{
unsigned long req;
unsigned long bit;
unsigned long mask; bit = 1UL << (irqno - EXTINT_OFF); mask = __raw_readl(S3C24XX_EINTMASK); __raw_writel(bit, S3C24XX_EINTPEND); req = __raw_readl(S3C24XX_EINTPEND);
req &= ~mask; /* not sure if we should be acking the parent irq... */ if (irqno <= IRQ_EINT7 ) {
if ((req & 0xf0) == )
s3c_irq_ack(IRQ_EINT4t7);
} else {
if ((req >> ) == )
s3c_irq_ack(IRQ_EINT8t23);
}
} static inline void
s3c_irq_ack(unsigned int irqno)
{
unsigned long bitval = 1UL << (irqno - IRQ_EINT0); __raw_writel(bitval, S3C2410_SRCPND);
__raw_writel(bitval, S3C2410_INTPND);
}

①desc
->chip->ack(irq);//上面是清理中断
============================================================
②handle_edge_irq取出action链表中的成员,执行action->
handler irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{
irqreturn_t ret, retval = IRQ_NONE;
unsigned int status = ; handle_dynamic_tick(action); if (!(action->flags & IRQF_DISABLED))
local_irq_enable_in_hardirq(); do {
ret = action->handler(irq, action->dev_id);
if (ret == IRQ_HANDLED)
status |= action->flags;
retval |= ret;
action = action->next;
} while (action); if (status & IRQF_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable(); return retval;
} 总结:
按下按键
1>cup进入异常处理模式
b vector_irq + ...
2>__irq_user
3>asm_do_IRQ
4>irq_des[irq]以中断号为下标取出一项 ->handle_irq
struct irq_desc {
irq_flow_handler_t handle_irq; //set_irq_handler(irqno, handle_edge_irq);
//handle_edge_irq取出action链表中的成员,
//执行action->handler(自定义实现)
struct irq_chip *chip; //set_irq_chip(irqno, &s3c_irq_eint0t4);
//芯片相关的一些操作
...
}
5>handle_irq = handle_edge_irq
6>handle_edge_irq的操作:
(1)desc->chip->ack(irq);
(2)handle_IRQ_event(irq, action);
===========================================================================================
自定义异常处理函数action->
handler,注册进内核 request_irq 1./kernel/irq/manage.c
int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
//1)分配了一个结构,结构中的成员指向传递进来的参数
action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
//2)设置irq
retval = setup_irq(irq, action);
} .setup_irq()函数分析:
)irq_des[irq] 已irq为下标找到数组项
)在irq_des[irq]链表里面加入传递进来的参数action
)desc->chip->settype()设置为中断引脚
)desc->chip->startup / desc->chip->enable 使能中断 free_irq(irq, dev_id)
1)从链表中除去
)禁止中断

字符设备驱动笔记——中断方式按键驱动之linux中断处理结构(五)的更多相关文章

  1. 字符设备驱动笔记——中断方式按键驱动之linux异常处理结构(四)

    .中断方式获取按键值 单片机: )按键按下 )cup发生中断,跳转到异常向量入口执行 )b 函数 a.保存被中断的现场 b.执行中断处理函数 c.恢复 linux: )trap_init()函数构造异 ...

  2. linux驱动之中断方式获取键值

    linux驱动之中断方式获取键值 ----------------------------------------------------------------------------------- ...

  3. linux字符驱动之poll机制按键驱动

    在上一节中,我们讲解了如何自动创建设备节点,实现一个中断方式的按键驱动.虽然中断式的驱动,效率是蛮高的,但是大家有没有发现,应用程序的死循环里的读函数是一直在读的:在实际的应用场所里,有没有那么一种情 ...

  4. linux字符设备学习笔记【原创】

    1.申请设备号 int register_chrdev_region(dev_t from, unsigned count, const char *name) 指定从设备号from开始,申请coun ...

  5. ARM Linux 驱动Input子系统之按键驱动测试

    上一篇已经谈过,在现内核的中引入设备树之后对于内核驱动的编写,主要集中在硬件接口的配置上了即xxxx.dts文件的编写. 在自己的开发板上移植按键驱动: 1.根据开发板的原理图 确定按键的硬件接口为: ...

  6. 3.字符设备驱动------Poll机制

    1.poll情景描述 以之前的按键驱动为例进行说明,用阻塞的方式打开按键驱动文件/dev/buttons,应用程序使用read()函数来读取按键的键值. ) { read(fd, &key_v ...

  7. 谈谈Linux字符设备驱动的实现

    @ 目录 字符设备驱动基础 申请设备号 创建设备节点 在驱动中实现操作方法 文件IO调用驱动中的操作 应用程序与驱动的数据交互 内核驱动如何控制外设 控制LED的简单驱动实例 驱动程序的改进 框架复盘 ...

  8. 入门级的按键驱动——按键驱动笔记之poll机制-异步通知-同步互斥阻塞-定时器防抖

    文章对应视频的第12课,第5.6.7.8节. 在这之前还有查询方式的驱动编写,中断方式的驱动编写,这篇文章中暂时没有这些类容.但这篇文章是以这些为基础写的,前面的内容有空补上. 按键驱动——按下按键, ...

  9. 驱动开发--【字符设备、块设备简介】【sky原创】

    驱动开发   字符设备,块设备,网络设备   字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问   EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是 ...

随机推荐

  1. Exif介绍

    Exif是一种图像文件格式,它的数据存储与JPEG格式是完全相同的.实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括拍摄时的光圈.快门.白平衡.ISO.焦距.日期时间等各种和拍摄条件 ...

  2. Android Bitmap与String互转(转)

    /** * 图片转成string * * @param bitmap * @return */ public static String convertIconToString(Bitmap bitm ...

  3. 配置的好的Apache和PHP语言的环境下,如何在Apache目录下htdocs/html目录下 同时部署两个项目呢

    建虚拟目录打开Apache->conf->httpd.conf在最下面粘贴NameVirtualHost 127.0.0.1 <VirtualHost 127.0.0.1> S ...

  4. 【云栖大会】阿里巴巴集团CTO张建锋:用计算和数据去改变整个世界

    摘要: 当浩瀚的数字化信息能够联网在线,在万物互联网的新世界中,所有东西都可能有感知.变智能,想象一下电表.冰箱.心电图监测仪等设备的信息都能数字化并联网,从城市管理到个人生活,都会迎来翻天覆地的变化 ...

  5. 笨鸟先飞之Java(一)--使用struts2框架实现文件上传

    无论是.net还是Java,我们最常接触到的就是文件的上传和下载功能,在Java里要实现这两个经常使用功能会有非常多种解决方案,可是struts2的框架却能给我们一个比較简单的方式,以下就一起来看吧: ...

  6. SpringMVC中的Controller默认单例

    众所周知,Servlet是单例的. 在struts中,Action是多例的,每一个请求都会new出来一个action来处理. 在Spring中,Controller默认是单例的,多个请求都会访问同一个 ...

  7. 理解Lucene中的Analyzer

    学习一个库,最好去官网.因为很多库API变动十分大,从博客上找的教程都过时了. Lucene原理就是简简单单的"索引",以空间换时间.但是Lucene将这件事做到了极致,后人再有想 ...

  8. 信号的捕捉与sigaction函数

    一.内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号.由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI ...

  9. 本地PC安装Centos 6.5 操作手册及遇到的问题

    我采取的是使用U盘安装 一.准备工作 1.下载Centos6.5 ISO文件 我在官网上下的6.5版本CentOS-6.5-x86_64-bin-DVD1.iso, 由于CentOS-6.5-x86_ ...

  10. Tree通用的系列方法列表-treepanel

    在项目中经常会用到Tree来显示数据进行操作.今天整理出来一系列操作Tree的方法.可供项目中方便调用.不用重复写代码,快速应用,通用性很强. Tree系列方法列表如下:主要针对的是ext.net中的 ...