linux设备驱动中断程序深度完全解析

1.ARM裸机中断程序流程分析

1.1.中断统一入口
1.2.事先注册中断处理程序
1.3.根据中断源的编号处理程序

2.linux系统中断处理流程分析

2.1中断流程概述

linux系统irq.svc中断入口获得中断源的编号,根据中断号找到irq_desc结构,在irq_desc结构中找到action结构,执行用户注册中断处理函数
驱动程序支持中断应该做什么?
驱动程序实现中断处理程序,注册到中断号所对应irq_desc中
linux设备驱动程序中包含中断处理程序中断注册,中断处理函数实现,注销处理

2.2linux系统中断处理实现

2.2.1中断注册使用request_irq函数用于中断注册
int request_irq(unsigned int irq,void (handler)(int, void, structpt_regs *),unsigned long flags,const char *devname,void *dev_id)
返回0表示成功,或者返回一个错误码
参数:
unsigned int irq
中断号。
void (handler)(int,void )
中断处理函数。
unsigned long flags
与中断管理有关的各种选项。
const char * devname
设备名
void *dev_id
共享中断时使用
在flags参数中,可以选择一些与中断管理有关的选项,如:
IRQF_DISABLED(SA_INTERRUPT)
如果设置该位,表示是一个“快速”中断处理程序;如果没有设置这位,那么是一个“慢速”中断处理程
序。
IRQF_SHARED(SA_SHIRQ)
该位表明该中断号是多个设备共享的。
也可选择为中断触发标志:IRQF_TRIGGER_FALLING(下降沿)
快/慢速中断的主要区别在于:快速中断保证中断处理的原子性(不被打断),而慢速中断则不保证。换句话说,也就是“开启中断”标志位(处理器IF)
在运行快速中断处理程序时是关闭的,因此在服务该中断时,不会被其他类型的中断打断;而调用慢速中断处理时,其它类型的中断仍可以得到服务。
2.2.2中断处理程序
中断处理程序的特别之处是在中断上下文中运行的,它的行为受到某些限制:1.不能使用可能引起阻塞的函数,2.不能使用肯呢过引起调度的函数
中断处理程序流程
1.检查设备是否产生了中断
2.清除中断产生标志
3.相应的硬件操作
2.2.3.注销中断
void free_irq(unsigned int irq,void *dev_id)

3.按键中断处理框架代码实现

#include<linux/module.h>
#include<linux/init.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>
#include<linux/interrupt.h>
#include<linux/irq.h>
#include<linux/io.h>
#include<linux/slab.h>
#include<linux/vmalloc.h>
MODULE_LICENSE("GPL");

#define GPX1CON 0x11000C20
//home按键的物理基地址
unsigned int *gpx1con;
irqreturn_t key_int(int irq,void *dev_id)
{
        //检测是否发生了按键中断



        //清除按键中断


        //打印键值
          printk("press the key\n");
         return 0;
}
void keyinit()
{
    gpx1con = ioremap(GPX1CON,4);//物理地址映射为虚拟地址
    writel(readl(gpx1con)&~(0xf<<4)|(0xf<<4),gpx1con);//将GPIO功能设置为输入
}
int key_open(struct inode *node,struct file *filp)
{
    return 0;   
}
struct file_operations key_fops = 
{
    .open = key_open,   
};
struct miscdevice key_miscdev = {

    .minor = 200,
    .name = "mykey",
    .fops = &key_fops,
};
static int key_init()
{

    misc_register(&key_miscdev);//注册杂项设备
    keyinit();按键的硬件初始化
    request_irq(IRQ_EINT(9),key_int,IRQF_TRIGGER_FALLING,"mykey",0);//注册中断
    return 0;
}

static void key_exit()
{
    misc_deregister(&key_miscdev);//注销杂项设备
    free_irq(IRQ_EINT(9),0);//释放中断
}

module_init(key_init);
module_exit(key_exit);  

4.中断分层

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值