您的位置:首页 > 运维架构 > Linux

arm驱动程序——按键程序5_异步通信(韦东山的视频总结及针对linux-2.6.30)

2013-06-11 12:47 453 查看
[b]相关代码在资源中下载。

[/b]

目的:

应用程序睡眠,当按下键时驱动程序 通知 应用程序去读取,

异步通知: 1.谁注册信号处理函数,怎么注册

2.谁发信号 怎么发

3.发给谁

1.应用程序 注册信号处理函数 定义信号处理函数例如定义了my_signal_fun,

signal(SIGIO,my_signal_fun) //SIGIO此信号指示异步I/O信号

2.驱动程序 用函数kill_fasync发送


3.应用程序

驱动的步骤:

1.fasync的函数,利用[b]fasync_helper函数初始化。[/b]

[b]2.kill_fasync函数在中断处理函数中向应用程序发信号。[/b]

用到的函数,结构及其他:

/*异步操作的文件指针结构*/

struct fasync_struct {

int magic;

int fa_fd;

struct fasync_struct *fa_next;

struct file *fa_file;

};



/*异步通知函数,在file_operations结构中*/

int (*fasync) (int, struct file *, int);



/*初始化异步通知的队列*/

int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)



/*向应用程序发送信号*/

void kill_fasync(struct fasync_struct **fp, int sig, int band)



驱动程序:

#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 <linux/device.h>

#include <linux/poll.h>

#include <linux/irq.h>

#include <linux/interrupt.h>

#include <asm/uaccess.h>

#include <asm/irq.h>

#include <asm/io.h>

#include <mach/irqs.h>

#include <mach/regs-gpio.h>

/*不同的linux版本,头文件会有所不同*/




static int major;

/*定义一个类*/

static struct class *second_key_class;

/*定义一个设备*/

static struct device *second_key_device;

/*定义一个等待的头文件*/

static DECLARE_WAIT_QUEUE_HEAD(button_wait_head);

/*定义一个定时器*/

struct timer_list second_key_timer;

/*中断事件标志*/

static int ev_press=0;

static unsigned int key_val;

static struct fasync_struct *fasync_q;

/*定义一个引脚描述的结构体*/

struct pindec

{

unsigned int pin;

unsigned int val;

};

/*定义引脚描述的数组,

*松开按键时,值为;0x01,0x02,0x03,0x04

*按下按键时,值为; 0x81,0x82,0x83,0x84


*/

static struct pindec pin_dec[4]={

{S3C2410_GPF1,0x01},

{S3C2410_GPF4,0x02},

{S3C2410_GPF2,0x03},

{S3C2410_GPF0,0x04},

};

static struct pindec *irq_dec;

static irqreturn_t button_irq(int irq,void *dev)

{

irq_dec = (struct pindec*)dev;

/*修改定时器的超时时间*/ mod_timer(&second_key_timer,jiffies+HZ/100);

return IRQ_RETVAL(IRQ_HANDLED);

}

static int second_key_fasync_open(struct inode *inode, struct file *file)

{

/*注册中断*/

request_irq(IRQ_EINT1,button_irq,IRQ_TYPE_EDGE_BOTH,"s1",&pin_dec[0]);

request_irq(IRQ_EINT4,button_irq,IRQ_TYPE_EDGE_BOTH,"s2",&pin_dec[1]);


request_irq(IRQ_EINT2,button_irq,IRQ_TYPE_EDGE_BOTH,"s3",&pin_dec[2]);

request_irq(IRQ_EINT0,button_irq,IRQ_TYPE_EDGE_BOTH,"s4",&pin_dec[3]);

return 0;

}




static ssize_t second_key_fasync_read(struct file *file, char __user *user_buffer,

size_t count, loff_t *ppos)

{

if(count != 1)

return -EINVAL;

/*ev_press中断标志为0,休眠,即未发生中断时,休眠*/

wait_event_interruptible(button_wait_head,ev_press);

/*传数据到用户空间*/

copy_to_user(user_buffer,&key_val,1);

/*中断结束,中断标志置0,休眠*/

ev_press = 0;

return 1;

}

static unsigned int second_key_poll(struct file *file,

struct poll_table_struct*wait)

{

unsigned int mask = 0;

/*挂载到队列中去*/

poll_wait(file, &button_wait_head, wait);

if(ev_press)

mask = POLLIN; /*普通或优先级带数据可读*/

return mask;

}

static int second_key_fasync(int fd, struct file * file, int on)

{

int result;

result = fasync_helper(fd, file, on, &fasync_q);

return (result);

}

static int second_key_fasync_close(struct inode *inode, struct file *file)

{

free_irq(IRQ_EINT1,&pin_dec[0]);

free_irq(IRQ_EINT4,&pin_dec[1]);

free_irq(IRQ_EINT2,&pin_dec[2]);

free_irq(IRQ_EINT0,&pin_dec[3]);

return 0;

}

void second_timer_function(unsigned long data)

{

unsigned int pinval;

struct pindec *pin_desc =irq_dec;

/*获得引脚状态*/

pinval=s3c2410_gpio_getpin(pin_desc->pin);

if(pinval)

key_val = pin_desc->val;

else

key_val = pin_desc->val|0x80;

/*唤醒*/

ev_press = 1;

wake_up_interruptible(&button_wait_head);

kill_fasync(&fasync_q, SIGIO, POLL_IN);

}

/*定义一个file_operations结构*/

static struct file_operations second_key_fasync_fops = {

.owner = THIS_MODULE,

.open = second_key_fasync_open,


.read = second_key_fasync_read,

.poll = second_key_poll,

.release = second_key_fasync_close,

.fasync= second_key_fasync,

};




static int second_key_init(void)

{

/*注册*/

major = register_chrdev(0,"second_key",&second_key_fasync_fops);

/*创建类在/sys/class可以查找到*/

second_key_class = class_create(THIS_MODULE,"second_key_class");

/*类下创建设备可以在/sys/class/second_key_class可以查找到*/

second_key_device =

device_create(second_key_class,NULL,MKDEV(major,0),NULL,"second_key_device");

/*初始化定时器*/

init_timer(&second_key_timer);

second_key_timer.function = second_timer_function;

/*启动定时器*/

add_timer(&second_key_timer);

return 0;

}

static void second_key_exit(void)

{

/*注销*/

unregister_chrdev(major,"second_key");

/*删除定时器*/

del_timer(&second_key_timer);

/*注销类*/

device_unregister(second_key_device);

/*销毁定义的类*/

class_destroy(second_key_class);

}

/*修饰*/

module_init(second_key_init);

module_exit(second_key_exit);

MODULE_LICENSE("GPL");



测试程序:

#include<stdio.h>

#include<fcntl.h>

#include<unistd.h>

#include<signal.h>

int fd;

/*接到信号调用的函数*/

void my_signal_fun(int signum)

{

static char key_val;

read(fd,&key_val,1);

printf("key_val: 0x%x\n",key_val);

}

int main(int argc,char **argv){

int oflags;

fd=open("/dev/second_key_device",O_RDWR);

if(fd<0)

printf("can't open!\n");

/*void (*signal)(int signo,void(*func)(int))(int )

*signo : 信号名,func;信号处理程序

*/

signal(SIGIO,my_signal_fun);

/*F_SETOWN设置接收SIGIO和SIGURG信号的进程ID*/

fcntl(fd,F_SETOWN,getpid());

/*F_GETFL 获得文件状态标志 */

oflags = fcntl(fd,F_GETFL);

/*F_SETFL设置文件状态标志*/

fcntl(fd,F_SETFL,oflags | FASYNC);

while(1){

sleep(1000);

}

return 0;

}



测试:

1.insmod加载驱动程序。

2.运行测试程序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐