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

本文介绍了如何在Linux环境下,利用FriendlyARM mini2440开发板实现按键驱动程序的异步通知功能。通过编写button_fasync.c驱动代码,设置中断处理函数,实现按键按下时的异步通知,并通过测试应用程序fasync_test进行验证。
摘要由CSDN通过智能技术生成

了解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的文件夹;
创建lesson5_fasync文件夹
(2)输入“cd lesson5_fasync”命令,进入lesson5_fasync目录下
(3)运行#gedit fasync.c

执行命令
(4)编写fasync.c代码(源代码见附录1)
fasync.c的部分代码截图
2. 进入lesson5_fasync目录下执行gedit Makefile命令编写Makefile文件
编写Makefile代码
3. 在lesson5_fasync目录执行#make命令,生成fasync.ko文件
生成fasync.ko文件
4.将生成的fasync.ko文件发送到开发板上(注:fasync.ko文件要复制到Windows上)
①打开window上的secureCRT软件
打开secureCRT软件
②插上开发板,与secureCRT连接(连接过程如图所示)
连接过程
③输入“rz”命令,添加fasync.ko文件
成功添加fasync.ko文件
5. 在lesson5_fasync文件夹下编写测试应用程序(包括头文件、打开设备、操作设备等函数),命名为fasync_test.c(源代码见附录2)
创建了fasync_test.c文件
fasync_test.c的部分代码截图
6.运行#arm-linux-gcc fasync_test.c -o fasync_test生成名为fasync_test的文件
生成fasync_test文件
7.将编译生成的文件fasync_test发送到开发板上(流程与步骤4一样)
成功发送到开发板上的文件
8.在secureCRT上执行#chmod 777 fasync_test命令
执行#chmod 777 fasync_test命令
9.加载驱动和卸载驱动
(1)加载驱动,运行#insmod fasync.ko
(2)查看主设备号 #cat /proc/devices
加载驱动
查看主设备号
(3)创立节点 #mknod /dev/button_fasync c 253 0
创立节点
10.执行./fasync_test命令,按下K5键,观察实验现象
按下开发板上的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>
#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值