基于JZ2440实现linux驱动异步通信

按键驱动

前期按键驱动无论是查询、中断、poll都是采用应用程序主动查询的方式,能不能有一种按键按下,驱动告诉应用程序该查询的机制呢?那是肯定的,类似于系统编程的信号机制。这里需要解决核心问题:
信号发出者
信号接收者
信号怎么发

建立一个异步通信结构体

该结构体存储相关信息

static struct fasync_struct *button_fasync;

建立系统调用函数将函数放入系统操作结构

static int my_dev_fasync(int fd, struct file *file, int on)
{
    printk("kernel:my_dev_fasync is call\n");
    //该函数初始化结构体
    return fasync_helper(fd, file, on,&button_fasync);
}
static struct file_operations my_dev_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   my_dev_open,     
    .write  =   my_dev_write,     
    .read   =   my_dev_read,
    .release=   my_dev_close,
    .fasync =   my_dev_fasync,
};

驱动中断添加发送函数

static irqreturn_t button_irq(int irq,void *dev_id)
{
    struct key_info *cdev_keyinfo = (struct key_info *)dev_id;
    unsigned int val;                               //存储按键电平
    val=s3c2410_gpio_getpin  (cdev_keyinfo->pins);   //读管脚电平
    if(val)
    {
        key_val[cdev_keyinfo->pin_val]='1';     //存储管脚电平状态
    }else
    {
        key_val[cdev_keyinfo->pin_val]='0';
    }
    //发送函数
    kill_fasync (&button_fasync, SIGIO, POLL_IN);
    return IRQ_HANDLED;
}

应用程序

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<poll.h>
#include<string.h>
#include<signal.h>

int fd;
void my_signal(int signum)
{
    char buf[4]={0};
    read(fd,buf,4);
    printf("key val is %s\n",buf);

}
int main(void)
{
    int i=0,count=0;
    int flags;
    fd = open("/dev/button",O_RDWR);
    if(fd<0)
        printf("open is err\n");
    //注册信号处理函数
    signal(SIGIO,my_signal);

    //任务与驱动挂接
    fcntl(fd,F_SETOWN,getpid());
    //获取flag
    flags=fcntl(fd,F_GETFL);
    //flag添加FASYNC
    fcntl(fd,F_SETFL,flags |FASYNC);

    while(1)
    {
        sleep(1000);
    }

}

全部驱动程序

/*
*芯片厂家对自家芯片对linux支持已经做好,寄存器映射也不需要,底层做的很详细
*做中断的时候,不用自己配置寄存器。完全用系统调用即可。
*中断编号索引内容
*irqs.h F:\SourceInsightProj\JZ2440_2.6\linux-2.6.22.6\include\asm-arm\arch-s3c2410
*中断类型文件
*irq.c linux-2.6.22.6\arch\arm\plat-s3c24xx 
*type:IRQT_NOEDGE IRQT_RISING IRQT_FALLING IRQT_BOTHEDGE IRQT_LOW IRQT_HIGH
*注册中断:request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void * dev_id)
*注销中断:free_irq(unsigned int irq, void * dev_id)
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.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>
#include <asm/hardware.h>
#include <linux/poll.h>


#define DEVICE_NAME "mybuttons"
static struct class *my_class=NULL;
static struct class_device *my_dev=NULL;
static int major=0;

static struct fasync_struct *button_fasync;

unsigned char key_val[4]={"0000"};                   //按键值初始化为0

//按键信息结构体
struct key_info{
    unsigned int eint;
    unsigned int pins;
    unsigned int pin_val;
    char name[20];
};

//按键初始化信息
struct key_info mykey[4]=
{
    {IRQ_EINT0,S3C2410_GPF0,0,"S1"},
    {IRQ_EINT2,S3C2410_GPF2,1,"S2"},
    {IRQ_EINT11,S3C2410_GPG3,2,"S3"},
    {IRQ_EINT19,S3C2410_GPG11,3,"S4"},
};

static irqreturn_t button_irq(int irq,void *dev_id)
{
    struct key_info *cdev_keyinfo = (struct key_info *)dev_id;
    unsigned int val;                               //存储按键电平
    val=s3c2410_gpio_getpin  (cdev_keyinfo->pins);   //读管脚电平
    if(val)
    {
        key_val[cdev_keyinfo->pin_val]='1';     //存储管脚电平状态
    }else
    {
        key_val[cdev_keyinfo->pin_val]='0';
    }
    kill_fasync (&button_fasync, SIGIO, POLL_IN);
    return IRQ_HANDLED;
}

static int my_dev_open(struct inode *inode, struct file *file)
{
    printk("this func is open\n");  
    return 0;
}

static ssize_t my_dev_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
    printk("this func is none\n");  

    return 0;
}
static ssize_t  my_dev_read (struct file *file, char __user *buf, size_t count, loff_t *ppos)
{

    copy_to_user(buf,key_val,4);
    return 4;

}

static int my_dev_close (struct inode *inod, struct file *file)
{
    printk("this func is close\n");
    return 0;
}


static int my_dev_fasync(int fd, struct file *file, int on)
{
    printk("kernel:my_dev_fasync is call\n");
    return fasync_helper(fd, file, on,&button_fasync);
}
static struct file_operations my_dev_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   my_dev_open,     
    .write  =   my_dev_write,     
    .read   =   my_dev_read,
    .release=   my_dev_close,
    .fasync =   my_dev_fasync,
};

static int my_dev_init(void)
{
    unsigned char tmp=0;
    major     = register_chrdev(0, DEVICE_NAME,&my_dev_fops);
    if(major<0)
        printk("register_chrdev err\n");
    my_class = class_create(THIS_MODULE, DEVICE_NAME);
    if(my_class==NULL)
        printk("class_create err\n");
    my_dev    = class_device_create(my_class, NULL, MKDEV(major,0), NULL, "button");
    if(my_dev==NULL)
        printk("class_device_create err \n");

    for(tmp=0;tmp<4;tmp++)
    {
        request_irq(mykey[tmp].eint,button_irq,IRQT_BOTHEDGE,mykey[tmp].name,&mykey[tmp]);
    }
    printk("button class is creat success\n");
    return 0;
}

static void my_dev_exit(void)
{
    unsigned char tmp;
    class_device_unregister(my_dev);
    class_destroy(my_class);
    unregister_chrdev(major,"button");
    for(tmp=0;tmp<4;tmp++)
    {
        free_irq(mykey[tmp].eint,&mykey[tmp]);
    }

    printk("button devs is exit\n");

}

module_init(my_dev_init);
module_exit(my_dev_exit);
MODULE_LICENSE("GPL");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值