S5PV210在Linux下如何编写中断驱动

发布者:SereneDreamer最新更新时间:2024-12-27 来源: cnblogs关键字:S5PV210  Linux  中断驱动 手机看文章 扫描二维码
随时随地手机看文章

我使用了两种驱动开发的模型来写了smart210上的按键驱动程序,这里做一下总结以及提供他人参考以及建议和改进,最后一个原因是自己很久没有写过博客了,现在想分享一下linux驱动开发程序的编写。


首先是Linux的中断处理机制。裸机开发中,通过中断标识一个函数指明该函数是中断处理函数,在编译器处理时候,也会对该函数的指针保存或特殊处理,当把该程序烧写到板子的时候,会把这个中断函数的地址加载到指定的地址,当中断发生时,通过寄存器保存的该函数的指针,进行中断函数地处理。但是在Linux中采用了类似信号处理这一种机制,在Linux的底层,当有中断发生时,就会有板级的代码产生一个指定的中断号,我们的中断驱动就是在内核中注册当接收的该中断信号后的处理函数,具体函数如下:


int request_irq(irq,func, trigger_type, name, dev_id );

  这里我是用伪代码描述:


    irq: 需要接受或检测的中断号


    func: 中断处理函数


    trigger_type: 中断触发模式


    name: 中断名称


    dev_id: 这个参数是void类型的指针,最终传递给中断处理函数的第二个参数


中断的处理分为Top-part,和 Bottom-part,可以使用多种处理方式进行处理,比如:tasklet, queue等等。这部分内容请查阅相关书籍


1. tasklet处理中断的Top-part和Bottom-part

这里直接使用了字符驱动模型,问题在于比较麻烦,尤其是驱动本身的注册,但是这种模型的驱动比较自由的。(头文件未补全,并且只是副本--真确的版本在虚拟机中,编译可能有点问题,可以私聊要完全的代码),主要参考驱动编写流程和框架。


#include

#include

#include

#include

#include

#include

#include




/* In this program, We using Top-Bottom mechinenism to

 * handle the interrupt, we can use tasklet to resolve

 * the interrupt.

 */


#define DEVICE_NAME        'interruptv1'

#define CLASS_NAME        'interrupts'


struct key_device

{

    cdev cdev;

    unsigned int count;

    unsigned int flags;

};


static struct tasklet key_tasklet;

static dev_t major;

static struct class *key_class;

static struct key_device *key_devp;



static void interrupt_handle(unsigned long data)

{

    printk('-: Welcome to Interrupt-B, The count = %d .n', data);

}


static irqreturn_t interrupt_tasklet(int irq, void *dev_id)

{

    printk('-: Welcome to Interrupt-Top, The irq = %d .n', irq);

    key_devp->count++;

    tasklet_schedule(&key_tasklet);


    return IRQ_HANDLED;

}



static int interrupt_open(struct inode *inode, struct file *filep)

{

    int ret;


    filep->private_data =key_devp;


    //request a interrupt number

    ret = request_irq(IRQ_EINT(16), interrupt_tasklet, IRQF_TRIGGER_FALLING, DEVICE_NAME, (void *) NULL);

    if(ret < 0){

        printk(': Fail to request interrupt number, We stay in open !n');

        free_irq(IRQ_EINT(16), NULL);


        return -EAGAIN;

    }


    printk(': Success request interrupt number! n');


    return 0;

}


static int interrupt_close(struct inode *inode, struct file *filep)

{

    free_irq(IRQ_EINT(16), NULL);

    tasklet_kill(&key_tasklet);

    printk(': Success Release IRQ !n');


    return 0;

}


static int interrupt_write(struct file *filep, char __user *buf, size_t size, loff_t *ppos)

{

    pirntk(': Fail to write data to Interrupt driver !n');


    return 0;

}


static int interrupt_read(struct file *filep, char __user *buf, size_t size, loff_t *ppos)

{

    printk(': Fail to read data from Interrupt driver !n');


    return 0;

}


DECLARE_TASKLET(key_tasklet, interrupt_handle, key_dev->count);



struct file_operations interrupt_fops = {

        .owner = THIS_MODULE,

        .open = interrupt_open,

        .release = interrupt_close,

        .read = interrupt_read,

        .write = interrupt_write,

};



static void device_setup(struct cdev *devp, int minor)

{

    int err;

    dev_t devno = MKDEV(major, minor);


    //add a char driver to kernel

    cdev_init(devp, &interrupt_fops);

    devp->owner = THIS_MODULE;

    err = cdev_add(devp, devno, 1);

    if(err)

        printk(' : Fail to add cdev to kernel !n');


    //add device driver to file-system

    key_class = class_create(THIS_MODULE, CLASS_NAME);

    if(IS_ERR(key_class)){

        printk(': Fail to create a class in the filesystem !n');

        return -EINVAL;

    }


    device_create(key_class, NULL, devno, NULL, DEVICE_NAME);

}



static int __init interrupt_init(void)

{

    int ret;

    dev_t devno;


    if((ret = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME)) < 0){

        printk(': Fail to alloc a char-dev number !n');


        return -EINVAL;

    }

    major = MAJOR(devno);


    key_devp = kmalloc(sizeof(struct key_device), GPF_KERNLE);

    if(!key_devp){

        printk(': Fail to malloc a mem region !n');


        goto fail1;

    }

    memset(key_devp, 0, sizeof(struct key_device));


    //set_irq_type(IRQ_EINT(16), IRQF_TRIGGER_FALLING);  no header file

    device_setup(&key_devp->cdev, 0);


    return 0;



fail1:

    unregister_chrdev_region(MKDEV(major, 0), 1);

    return -ENOMEM;

}



static void __exit interrupt_exit(void)

{

    cdev_del(&key_devp->cdev);

    kfree(key_devp);

    unregister_chrdev_region(MKDEV(major, 0), 1);

    device_destroy(key_class, MKDEV(major, 0));

    class_destroy(key_class);

}


module_init(interrupt_init);

module_exit(interrupt_exit);


MODULE_LICENSE('GPL');

MODULE_AUTHOR('weirdo');

MODULE_DESCRIPTION('This module using for smart210 interrupts');


2. 普通中断驱动模型---miscdevice


#include

#include

#include

#include

#include

#include

#include     //contain gpio_to_irq() func


#define INT_NAME        'key1'

#define DEVICE_NAME        'interruptv1'

#define DEVICE_MINOR    12



static irqreturn_t interrupt_handle(int irq, void *dev_id)

{

    printk(': I'm in kernel! You had beat my heart !n');


    return IRQ_HANDLED;

}


static int interrupt_open(struct inode *inode, struct file *filep)

{

    int irq, ret;


    irq = gpio_to_irq(S5PV210_GPH2(0));

    ret = request_irq(irq, interrupt_handle, IRQF_TRIGGER_FALLING, INT_NAME, 0);

    if(ret < 0){

        printk(': Fail to request irq number ----- 16 !n');

        return -EFAULT;

    }

    printk(': Success register interrupt handle function --- 16! n');


    return 0;


}


static int interrupt_close(struct inode *inode, struct file *filep)

{

    int irq;


    irq = gpio_to_irq(S5PV210_GPH2(0));

    free_irq(irq, NULL);

    printk(': We will close interrupt file !n');



    return 0;

}



static int interrupt_read(struct file *filep, char __user *buf, size_t size, loff_t *ppos)

{

    printk(': You can't read data from the device! (-_-)n');


    return 0;

}


static int interrupt_write(struct file *filep, const char __user *buf, size_t size, loff_t *ppos)

{

    printk(': You can't write data to the device! (-_-)n');


    return 0;

}


static struct file_operations interrupt_fops = {

        .owner = THIS_MODULE,

        .open = interrupt_open,

        .release = interrupt_close,

        .read = interrupt_read,

        .write = interrupt_write

};


static struct miscdevice int_misc = {

        .minor = DEVICE_MINOR,

        .name = DEVICE_NAME,

        .fops = &interrupt_fops,

};



static int __init interrupt_init(void)

{

    int ret;


    ret = misc_register(&int_misc);

    if(ret != 0)

    {

        print(': Fail to register interrupt driver! n');

        retur -EFAULT;

    }

    printk(': Success to register interrupt driver! n');


    return 0;

}



static void __exit interrupt_exit(void)

{

    misc_deregister(&int_misc);

}


module_init(interrupt_init);

module_exit(interrupt_exit);


MODULE_AUTHOR('weirdo');

MODULE_LICENSE('GPL');

MODULE_DESCRIPTION('This driver write for smart210 8 keys interrupts');


3. 驱动测试文件


由于驱动测试文件在虚拟机中,个人比较lazy,但简要叙述一些驱动中的关键点:


#include <>

#include <>

#include <>

#include <>



#define DEVICE_NAME '/dev/interruptv1'



int main(void)

{

    int fd;

   char input;

      


    fd = open(DEVICE_NAME);

    if(irq){

       ....

     }


   for( ; input != 'e'      


}


关键字:S5PV210  Linux  中断驱动 引用地址:S5PV210在Linux下如何编写中断驱动

上一篇:S5PV210开发板 VGA测试
下一篇:基于S5pv210流媒体server的实现之网络摄像头

推荐阅读最新更新时间:2026-03-25 12:08

arm驱动linux内核中断编程
第一部分获取中断(开启硬件中断) 一、中断的申请注销: 1)中断的申请 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) 2)中断的注销 void free_irq(unsigned int irq, void *dev_id) 3)中断处理函数 static irqreturn_t irq_handle(int irq, void *dev__id); 参数:irq:表示中断号,这个参数还保留由于历史遗留问题,往后可能越来越没用了。由于
[单片机]
S5PV210版本NDT嵌入式Linux主机目录分布及开发流程简要说明
开发才用win10宿主机+VMWare12.5+Ubuntu14.04 LTS虚拟机环境。 1、文件目录介绍 开发机器所建用户名为administrator,机器密码为******。 嵌入式QT目录:/home/administrator/linuxtools/armqt/ tftp共享目录:/home/administrator/tftp 根文件系统: /home/administrator/rootfs 内核目录: /home/administrator/kernel/linux-2.6.35.7 工程目录: /home/administrator/NDT-2015/NDT-F 2、
[单片机]
S5pv210 之sate210 android4.0 linux kernel 触摸屏通道选择
sate210 用的是触摸屏通道1,看一下数据手册有说明 TSSEL Touch screen selection 0 = Touch screen 0 (AIN2~AIN5) 1 = Touch screen 1 (AIN6~AIN9) This bit exists only in TSADCCON0. Note: An access to TSADCCON1 bits is prohibited when TSSEL bit is 0, and an access to TSADCCON0 bits except TSSEL is prohibited when TSSEL bit is 1. An access to T
[单片机]
ARM-Linux S5PV210 UART驱动(5)----串口的open操作(tty_open、uart_open)
串口驱动初始化后,串口作为字符驱动也已经注册到系统了,/dev目录下也有设备文件节点了。 那接下来uart的操作是如何进行的呢? 操作硬件之前都是要先open设备,先来分析下这里的open函数具体做了那些工作。 s3c24xx_serial_modinit -- uart_register_driver -- tty_register_driver 中有如下语句: cdev_init(&driver- cdev, &tty_fops); 此处将 driver- cdev- ops=&tty_fops 而tty_fops如下: static const struct file_operations tty_f
[单片机]
S5PV210开发 -- Linux dd命令
昨天群里有人询问,为什么破坏 BootLoader 破坏不掉。 出现错误:dd: writing '/dev/mtdblock0': Operation not permitted 我说需要插着 SD卡才可以。(这个也不对,不插SD卡也可以,那这个错误还是没有搞清楚) 然后我们来看一下它操作指令: busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync 为了确保执行数据有效,再执行 sync 同步一下,即可破坏掉前一个块的数据。 进而引出了我们今天要讲的 dd命令。 参看:Linux dd命令
[单片机]
<font color='red'>S5PV210</font>开发 -- <font color='red'>Linux</font> dd命令
IMX257实现GPIO-IRQ中断按键驱动程序
昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有按键,应用程序while循环中的read函数也不断的在运行,严重的导致了CPU资源的浪费。 本文中,我们在前面按键查询驱动程序的基础上来修改。 大概介绍一下设计思路吧: 和前面的差不多,当我们加载驱动时,首先在init函数中,对GPIO功能进行模式设置,都设置为GPIO模式,然后申请GPIO引脚的内存, 接着,当我们应用程序使用ioctl函数的gpio_input命令时,将所有的GPIO引脚设置为输入,并且22K上拉模式,当应用程序使用read函数读取时,如果按键没有按下,则会在r
[单片机]
IMX257实现GPIO-IRQ<font color='red'>中断</font>按键<font color='red'>驱动</font>程序
【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用Poll函数,来控制一定时间内,如果有按键发生,则立即返回键值。 同时,poll也可以同时监控多个(比如说按键,鼠标,等)一旦发生事件则立即返回。 我们在linux查看帮助: 从帮助中的说明得知, poll, ppoll - wait for some event on a file descriptor poll就是监控某个设备的事件。 修改驱动程序 1.增加头文件 #include linux/poll.h 2.增加key_poll 方法 static unsigned key_poll(struct file *fil
[单片机]
【改进Poll定时查询】IMX257实现GPIO-IRQ<font color='red'>中断</font>按键获取键值<font color='red'>驱动</font>程序
s3c2440之按键中断驱动
前言 本文记录的是S3C2440按键中断驱动程序,在查询方式按键驱动程序基础下修改。 一、代码 1.按键中断驱动程序 key_drv.c代码如下(示例): #include linux/module.h #include linux/kernel.h #include linux/fs.h #include linux/init.h #include linux/delay.h #include linux/irq.h #include asm/uaccess.h #include asm/irq.h #include asm/io.h #include asm/arch/regs-gpio.h #in
[单片机]
s3c2440之按键<font color='red'>中断</font><font color='red'>驱动</font>
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved