基於JZ2440實現linux驅動非同步通訊
阿新 • • 發佈:2019-01-23
按鍵驅動
前期按鍵驅動無論是查詢、中斷、poll
都是採用應用程式主動查詢的方式,能不能有一種按鍵按下,驅動告訴應用程式該查詢的機制呢?那是肯定的,類似於系統程式設計的訊號機制。這裡需要解決核心問題:
訊號發出者
訊號接收者
訊號怎麼發
建立一個非同步通訊結構體
該結構體儲存相關資訊
static struct fasync_struct *button_fasync;
建立系統呼叫函式將函式放入系統操作結構
static int my_dev_fasync(int fd, struct file *file, int on)
{
printk("kernel:my_dev_fasync is call\n" );
//該函式初始化結構體
return fasync_helper(fd, file, on,&button_fasync);
}
static struct file_operations my_dev_fops = {
.owner = THIS_MODULE, /* 這是一個巨集,推向編譯模組時自動建立的__this_module變數 */
.open = my_dev_open,
.write = my_dev_write,
.read = my_dev_read,
.release= my_dev_close,
.fasync = my_dev_fasync,
};
驅動中斷添加發送函式
static irqreturn_t button_irq(int irq,void *dev_id)
{
struct key_info *cdev_keyinfo = (struct key_info *)dev_id;
unsigned int val; //儲存按鍵電平
val=s3c2410_gpio_getpin (cdev_keyinfo->pins); //讀管腳電平
if(val)
{
key_val[cdev_keyinfo->pin_val]='1' ; //儲存管腳電平狀態
}else
{
key_val[cdev_keyinfo->pin_val]='0';
}
//傳送函式
kill_fasync (&button_fasync, SIGIO, POLL_IN);
return IRQ_HANDLED;
}
應用程式
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<poll.h>
#include<string.h>
#include<signal.h>
int fd;
void my_signal(int signum)
{
char buf[4]={0};
read(fd,buf,4);
printf("key val is %s\n",buf);
}
int main(void)
{
int i=0,count=0;
int flags;
fd = open("/dev/button",O_RDWR);
if(fd<0)
printf("open is err\n");
//註冊訊號處理函式
signal(SIGIO,my_signal);
//任務與驅動掛接
fcntl(fd,F_SETOWN,getpid());
//獲取flag
flags=fcntl(fd,F_GETFL);
//flag新增FASYNC
fcntl(fd,F_SETFL,flags |FASYNC);
while(1)
{
sleep(1000);
}
}
全部驅動程式
/*
*晶片廠家對自家晶片對linux支援已經做好,暫存器對映也不需要,底層做的很詳細
*做中斷的時候,不用自己配置暫存器。完全用系統呼叫即可。
*中斷編號索引內容
*irqs.h F:\SourceInsightProj\JZ2440_2.6\linux-2.6.22.6\include\asm-arm\arch-s3c2410
*中斷型別檔案
*irq.c linux-2.6.22.6\arch\arm\plat-s3c24xx
*type:IRQT_NOEDGE IRQT_RISING IRQT_FALLING IRQT_BOTHEDGE IRQT_LOW IRQT_HIGH
*註冊中斷:request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void * dev_id)
*登出中斷:free_irq(unsigned int irq, void * dev_id)
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/poll.h>
#define DEVICE_NAME "mybuttons"
static struct class *my_class=NULL;
static struct class_device *my_dev=NULL;
static int major=0;
static struct fasync_struct *button_fasync;
unsigned char key_val[4]={"0000"}; //按鍵值初始化為0
//按鍵資訊結構體
struct key_info{
unsigned int eint;
unsigned int pins;
unsigned int pin_val;
char name[20];
};
//按鍵初始化資訊
struct key_info mykey[4]=
{
{IRQ_EINT0,S3C2410_GPF0,0,"S1"},
{IRQ_EINT2,S3C2410_GPF2,1,"S2"},
{IRQ_EINT11,S3C2410_GPG3,2,"S3"},
{IRQ_EINT19,S3C2410_GPG11,3,"S4"},
};
static irqreturn_t button_irq(int irq,void *dev_id)
{
struct key_info *cdev_keyinfo = (struct key_info *)dev_id;
unsigned int val; //儲存按鍵電平
val=s3c2410_gpio_getpin (cdev_keyinfo->pins); //讀管腳電平
if(val)
{
key_val[cdev_keyinfo->pin_val]='1'; //儲存管腳電平狀態
}else
{
key_val[cdev_keyinfo->pin_val]='0';
}
kill_fasync (&button_fasync, SIGIO, POLL_IN);
return IRQ_HANDLED;
}
static int my_dev_open(struct inode *inode, struct file *file)
{
printk("this func is open\n");
return 0;
}
static ssize_t my_dev_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
printk("this func is none\n");
return 0;
}
static ssize_t my_dev_read (struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
copy_to_user(buf,key_val,4);
return 4;
}
static int my_dev_close (struct inode *inod, struct file *file)
{
printk("this func is close\n");
return 0;
}
static int my_dev_fasync(int fd, struct file *file, int on)
{
printk("kernel:my_dev_fasync is call\n");
return fasync_helper(fd, file, on,&button_fasync);
}
static struct file_operations my_dev_fops = {
.owner = THIS_MODULE, /* 這是一個巨集,推向編譯模組時自動建立的__this_module變數 */
.open = my_dev_open,
.write = my_dev_write,
.read = my_dev_read,
.release= my_dev_close,
.fasync = my_dev_fasync,
};
static int my_dev_init(void)
{
unsigned char tmp=0;
major = register_chrdev(0, DEVICE_NAME,&my_dev_fops);
if(major<0)
printk("register_chrdev err\n");
my_class = class_create(THIS_MODULE, DEVICE_NAME);
if(my_class==NULL)
printk("class_create err\n");
my_dev = class_device_create(my_class, NULL, MKDEV(major,0), NULL, "button");
if(my_dev==NULL)
printk("class_device_create err \n");
for(tmp=0;tmp<4;tmp++)
{
request_irq(mykey[tmp].eint,button_irq,IRQT_BOTHEDGE,mykey[tmp].name,&mykey[tmp]);
}
printk("button class is creat success\n");
return 0;
}
static void my_dev_exit(void)
{
unsigned char tmp;
class_device_unregister(my_dev);
class_destroy(my_class);
unregister_chrdev(major,"button");
for(tmp=0;tmp<4;tmp++)
{
free_irq(mykey[tmp].eint,&mykey[tmp]);
}
printk("button devs is exit\n");
}
module_init(my_dev_init);
module_exit(my_dev_exit);
MODULE_LICENSE("GPL");