基于FriendlyARM开发板mini2440的异步通知

基于FriendlyARM开发板mini2440的异步通知 了解Linux设备驱动程序异步通知应用和驱动的编程方法优化按键中断方式使用异步通知方式编写按键驱动程序。一、实验设备与软件环境1、操作系统Linux虚拟机、Red Hat Enterprise Linux 6.3。2、硬件平台FriendlyARM开发板mini2440。3、软件SecureCRT 8.1。4、内核版本linux 2.6.32.2。二、具体操作过程1.编写代码分析代码:button_fasync.c1头文件2open、write等函数3file_operation结构体4驱动函数初始化函数和卸载函数流程1在/opt /shiyan目录下创建lesson5_fasync文件夹①在/opt/shiyan目录下右击鼠标打开终端②输入“mkdir lesson5_fasync”创建一个名为lesson5_fasync的文件夹2输入“cd lesson5_fasync”命令进入lesson5_fasync目录下3运行#gedit fasync.c4编写fasync.c代码源代码见附录12. 进入lesson5_fasync目录下执行gedit Makefile命令编写Makefile文件3. 在lesson5_fasync目录执行#make命令生成fasync.ko文件4将生成的fasync.ko文件发送到开发板上注fasync.ko文件要复制到Windows上①打开window上的secureCRT软件②插上开发板与secureCRT连接连接过程如图所示③输入“rz”命令添加fasync.ko文件5. 在lesson5_fasync文件夹下编写测试应用程序(包括头文件、打开设备、操作设备等函数),命名为fasync_test.c源代码见附录26.运行#arm-linux-gcc fasync_test.c -o fasync_test生成名为fasync_test的文件7.将编译生成的文件fasync_test发送到开发板上流程与步骤4一样8.在secureCRT上执行#chmod 777 fasync_test命令9加载驱动和卸载驱动1加载驱动运行#insmod fasync.ko2查看主设备号 #cat /proc/devices3创立节点 #mknod /dev/button_fasync c 253 010.执行./fasync_test命令按下K5键观察实验现象三、操作过程中遇到的异常问题与解决方案异常问题在secureCRT上执行测试程序./fasync_test时显示该文件无法找到但是用ls命令可以看到该文件存在。解决方法3.4.1的交叉编译环境有问题所以生成的test文件是一个异常文件无法正常使用我安装了一个新的交叉编译环境4.4.3后所生成的test文件就可以正常使用了测试程序也可以正常执行。异常问题当执行./fasync_test命令之后显示“open error”如图所示并没有出现预期的效果。解决方法创立节点执行mknod /dev/button_fasync c 253 0命令创立节点即可。四、附录附录1#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 linux/module.h#include linux/device.h#include mach/regs-gpio.h#include mach/hardware.h#include linux/interrupt.h#include linux/poll.h#include linux/fcntl.h#include mach/gpio-fns.h#include mach/gpio-nrs.h#includelinux/sched.h#define DEVICE_NAME “button_fasync”#define BUTTON_MAJOR 0static DECLARE_WAIT_QUEUE_HEAD(button_waitq);static int press_cnt 0;static int ev_press 0;//static unsigned char key_val;int major;static struct fasync_struct *button_fasync;/* 用户中断处理函数 */static irqreturn_t button_interrupt(int irq, void *dev_id){volatile int *press_cnt (volatile int *)dev_id;*press_cnt *press_cnt 1;ev_press 1;wake_up_interruptible(button_waitq);kill_fasync(button_fasync, SIGIO, POLL_IN); //发送信号SIGIO信号给fasync_struct 结构体所描述的PID触发应用程序的SIGIO信号处理函数return IRQ_RETVAL(IRQ_HANDLED);}struct button_irq_desc {int irq;unsigned long flags;char *name;};static struct button_irq_desc button_irqs {IRQ_EINT15, IRQF_TRIGGER_FALLING, “KEY5”};static int button_open(struct inode *inode, struct file *file){int ret;//request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char * name,void * dev);retrequest_irq(button_irqs.irq,button_interrupt,button_irqs.flags,button_irqs.name,press_cnt);//if(ret)if (ret){free_irq(button_irqs.irq, press_cnt);return -EBUSY;}return 0;}static ssize_tbutton_read(struct file *file, char __user *buf, size_t bytes, loff_t *off){unsigned long err;wait_event_interruptible(button_waitq, ev_press);ev_press 0;err copy_to_user(buf, press_cnt,1);memset(press_cnt, 0, sizeof(press_cnt));return err ? -EFAULT : 0;//return 0;}static int button_close(struct inode *inode, struct file *file){free_irq(button_irqs.irq, press_cnt);return 0;}static unsigned button_poll(struct file *file, poll_table *wait){unsigned int mask 0;poll_wait(file, button_waitq, wait);if (ev_press)mask | POLLIN | POLLRDNORM;return mask;}static int button_fasync_function(int fd, struct filefilp, int on){return fasync_helper(fd, filp, on, button_fasync);}/File operations struct for character device */static const struct file_operations buttons_fops {.owner THIS_MODULE,.open button_open,.read button_read,.release button_close,.poll button_poll,.fasync button_fasync_function,};static int __init buttons_init(void){int ret;ret register_chrdev(BUTTON_MAJOR, DEVICE_NAME, buttons_fops);if (ret 0) {printk(DEVICE_NAME can’t register major number\n);return ret;}printk(DEVICE_NAME initialized\n);return 0;}static void __exit buttons_exit(void){unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);}module_init(buttons_init);module_exit(buttons_exit);MODULE_LICENSE(“GPL”);附录2#include stdio.h#include sys/types.h#include sys/stat.h#include fcntl.h#include unistd.h#include poll.h#include signal.h#include fcntl.hint fd;void mysignal_fun(int signum){unsigned char key_val;read(fd,key_val,1);if(key_val)printf(“K5 %d\n”,key_val);}int main(int argc ,char *argv[]){int flag;signal(SIGIO,mysignal_fun);fd open(/dev/button_fasync,O_RDWR);if (fd 0){printf(“open error\n”);}fcntl(fd, F_SETOWN, getpid());flag fcntl(fd,F_GETFL);fcntl(fd,F_SETFL,flag | FASYNC);while(1){sleep(1000);}return 0;}