LINUX驱动中断GPIO 中断

一个驱动中断处理比较好的网页

中断上下文

GPIO 驱动分析

linux 驱动之input子系统(gpio-keys)实现

linux 驱动之input子系统(gpio-keys)实现
野火相关input 子系统说明

中断说明

中断最重要属性就是响应必须及时,而实际实现中中断处理过程往往比较费事,这将会影响后续中断响应。为了解决这个问题,因此提出中断上下部的概念,将中断处理过程分为两部分:

上部分:处理过程比较快。不会占用很长时间的放在上半部。
下半部:处理过程比较耗时操作放在下半部。
1、中断上下部设计思路

2、如果要处理的内容不希望被其他中断打断,那么可以放到上半部。

3、如果要处理的任务对时间敏感,可以放到上半部。

4、如果要处理的任务与硬件有关,可以放到上半部。

5、除了上述三点以外的其他任务,优先考虑放到下半部。

6、中断上下部设计
中断处理函数可以作为中断上半部,而下半部 Liunx 内核提供多种机制:

软中断

tasklet

中断和应用层沟通

内核空间和用户空间数据的交互主要有三种方式
1、copy_to_user()
2、信号
3、netlink
4、Linux内核中断引入用户空间(异步通知机制)

异步通知

异步通知驱动说明

驱动处理

fasync函数
1.如果要使用异步通知,需要在设备驱动中实现fops中的fasync函数
2.当设备可以访问的时候,驱动程序需要向应用程序发出信号,相当于产生”中断“。kill_fastync函数负责发送指定的信号,kill_fastync函数。

应用处理

1、注册信号处理函数
2、将本应用程序的进程号告诉内核
3、开启异步通知

	flags = fcntl(fd,F_GETEL);//获取当前的进程状态
	fcntl(fd,F_SETEL,flags | FASYNC);//开启当前进程异步通知功能

重点就是通过fcntl函数设置进程状态为FASYNC,经过这一步,驱动程序中的fasync函数就会执行

例子

驱动代码

struct irqkey_dev
{
    dev_t devid;
	...
    struct fasync_struct *async_queue;
};

void timer_function(unsigned long arg)
{
    unsigned char value;
	...
    //一次完成的按键过程
    if(atomic_read(&dev->releasekey))
    {
        if(dev->async_queue)
            kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
    }
}
static int key_fasync(int fd, struct file *filp, int on)
{
    printk(KERN_EMERG "key_fasync enter!\n");
    struct irqkey_dev *dev = (struct irqkey_dev *)filp->private_data;

    return fasync_helper(fd, filp, on, &dev->async_queue);
}

static int key_release(struct inode *inode,struct file *filp)
{
    printk(KERN_EMERG "key_release enter!\n");
    return key_fasync(-1, filp, 0);
}
————————————————
版权声明:本文为CSDN博主「爱吃肉的大高个」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a568713197/article/details/103145834

应用代码

static void sigio_signal_func(int signum)
{
    int err = 0;
    unsigned int keyvalue = 0;

    err = read(fd, &keyvalue, sizeof(keyvalue));
    if(err < 0)
    {

    }
    else
    {
        printf("SIGIO signal! key value = %d\r\n",keyvalue);
    }
    
}

const char default_path[] = "/dev/input/by-path/platform-gpio-keys-event";
int main(int argc, char *argv[])
{
...
 /*open device*/
 fd = open(filename, O_RDWR);
 if(fd < 0)
 {
     printf("Can't open file %s\r\n", filename);
     return -1;
 }
 printf("Open file %s OK!\r\n", filename);
 
 signal(SIGIO, sigio_signal_func);

 fcntl(fd, F_SETOWN, getpid());
 flags = fcntl(fd, F_GETFD);
 fcntl(fd, F_SETFL, flags | FASYNC);

 while(1)
 {
     sleep(2);
 }
 }
————————————————
版权声明:本文为CSDN博主「爱吃肉的大高个」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a568713197/article/details/103145834
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值