linux按键驱动中断函数参数分析,字符设备驱动笔记——中断方式按键驱动之linux中断处理结构(五)...

一、单片机下的中断处理)分辨是哪一个中断

)调用处理函数

)清中断

二、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_irq1./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异常处理结构(四)

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

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

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

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

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

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

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

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

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

3&period;字符设备驱动------Poll机制

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

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

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

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

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

手把手教Linux驱动3-之字符设备架构详解,有这篇就够了

一.Linux设备分类 Linux系统为了管理方便,将设备分成三种基本类型: 字符设备 块设备 网络设备 字符设备: 字符(char)设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程 ...

随机推荐

Ubuntu 使用笔记

持续更新 从前使用sudo apt update更新时, 发现软件源是cn.archive.ubuntu.com. 最近在system setting 中将软件源改成了archive.ubuntu.c ...

Spring 的优秀工具类盘点

文件资源操作 文件资源的操作是应用程序中常见的功能,如当上传一个文件后将其保存在特定目录下,从指定地址加载一个配置文件等等.我们一般使用 JDK 的 I/O 处理类完成这些操作,但对于一般的应用程序来 ...

backup site collection

http://stackoverflow.com/questions/5376380/sharepoint-2010-change-sitecollection-urlstsadm -o backup ...

iOS数据存储之对象归档

iOS数据存储之对象归档 对象归档 对象归档是iOS中数据持久化的一种方式. 归档是指另一种形式的序列化,但它是任何对象都可以实现的更常规的类型.使用对模型对象进行归档的技术可以轻松将复杂的对象写入文 ...

Java中 hashCode()方法详解

先来看下Object源码里hashcode方法: /**     * Returns a hash code value for the object. This method is      * s ...

【DP专辑】ACM动态规划总结

转载请注明出处,谢谢.   http://blog.csdn.net/cc_again?viewmode=list          ----------  Accagain  2014年5月15日 ...

ReenTrantLock可重入锁(和synchronized的区别)总结

ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...

git下载&sol;上传文件提示:git did not exit cleanly

问题:git操作下载/上传文件,提示信息如下 TortoiseGit-git did not exit cleanly (exit code 1) TortoiseGit-git did not ex ...

Game Engine Architecture 8

[Game Engine Architecture 8] 1.Differences across Operating Systems • UNIX uses a forward slash (/) ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值