天天看點

基于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;

}