天天看点

基于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.c

(1)头文件

(2)open、write等函数

(3)file_operation结构体

(4)驱动函数初始化函数和卸载函数

流程:

(1)在/opt /shiyan目录下创建lesson5_fasync文件夹

①在/opt/shiyan目录下右击鼠标打开终端;

②输入“mkdir lesson5_fasync”,创建一个名为lesson5_fasync的文件夹;

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

(2)输入“cd lesson5_fasync”命令,进入lesson5_fasync目录下

(3)运行#gedit fasync.c

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

(4)编写fasync.c代码(源代码见附录1)

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

2. 进入lesson5_fasync目录下执行gedit Makefile命令编写Makefile文件

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

3. 在lesson5_fasync目录执行#make命令,生成fasync.ko文件

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

4.将生成的fasync.ko文件发送到开发板上(注:fasync.ko文件要复制到Windows上)

①打开window上的secureCRT软件

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

②插上开发板,与secureCRT连接(连接过程如图所示)

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

③输入“rz”命令,添加fasync.ko文件

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

5. 在lesson5_fasync文件夹下编写测试应用程序(包括头文件、打开设备、操作设备等函数),命名为fasync_test.c(源代码见附录2)

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

6.运行#arm-linux-gcc fasync_test.c -o fasync_test生成名为fasync_test的文件

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

7.将编译生成的文件fasync_test发送到开发板上(流程与步骤4一样)

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

8.在secureCRT上执行#chmod 777 fasync_test命令

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

9.加载驱动和卸载驱动

(1)加载驱动,运行#insmod fasync.ko

(2)查看主设备号 #cat /proc/devices

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

(3)创立节点 #mknod /dev/button_fasync c 253 0

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

10.执行./fasync_test命令,按下K5键,观察实验现象

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

三、操作过程中遇到的异常问题与解决方案

异常问题:在secureCRT上执行测试程序(./fasync_test)时,显示该文件无法找到,但是用ls命令可以看到该文件存在。

解决方法:3.4.1的交叉编译环境有问题,所以生成的test文件是一个异常文件,无法正常使用,我安装了一个新的交叉编译环境4.4.3后,所生成的test文件就可以正常使用了,测试程序也可以正常执行。

异常问题:当执行./fasync_test命令之后,显示“open error”(如图所示),并没有出现预期的效果。

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

解决方法:创立节点,执行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>

#include<linux/sched.h>

#define DEVICE_NAME “button_fasync”

#define BUTTON_MAJOR 0

static 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);

ret=request_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_t

button_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 file filp, 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.h>

int 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;

}