跟着韋東山老師學字符設備驅動之查詢方式的按鍵驅動程序分析

驅動程序如下:seconddrv.c

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<asm/uaccess.h>
#include<asm/irq.h>
#include<asm/io.h>
#include<linux/device.h>       //要是想使用 class_create 和 device_create和 class_destroy 和 device_unregister   需要添加這個頭文件

//#include<asm-generic/gpio.h>
#include<mach/regs-gpio.h>  //這兩個頭文件,在lesson3/lesson3.3/linux-ok6410/arch/arm/mach-s3c6400/include/mach目錄下存放着
#include<mach/hardware.h>   
volatile unsigned long *gpncon ;  //OK6410按鍵每個管腳佔兩位,對應的管腳爲GPN0~5是 起始地址是0x7F008830
volatile unsigned long *gpndat ; //起始地址,0x7F008834 ,當按鍵被按下時,對應的鍵值爲0,平時爲高電平
static struct class *seconddrv_class; //創建一個class 型 的類 ,這裏是先定義好
static struct class_device *seconddrv_class_dev;//創建基於上面 類的 設備,這裏也是定義

/*程序規劃:
在open函數中配置引腳
在read中返回IO值
在init中進行寄存器映射   ,映射之後,要記得在exit函數中 取消映射
*/

static int second_drv_open(struct inode *inode,struct file *file)
{
*gpncon &= ~((0x3<<2*0) | (0x3<<2*1) | (0x3<<2*2) | (0x3<<2*3) | (0x3<<2*4) | (0x3<<2*5));  //配置GPN0~5位輸入引腳,用於讀取
return 0;
}


ssize_t second_drv_read(struct file *file,char __user *buf,size_t size,loff_t *ppos)
{

/* 返回6個引腳的電平數值 */
unsigned char key_vals[6];
unsigned long regval;
if(size != sizeof(key_vals))
return -EINVAL;
regval = *gpndat; 
key_vals[0] = (regval & (1<<0)) ? 1 : 0;       //按位與   結果爲真時 取值爲1 ,爲假時取 0
key_vals[1] = (regval & (1<<1)) ? 1 : 0; 
key_vals[2] = (regval & (1<<2)) ? 1 : 0; 
key_vals[3] = (regval & (1<<3)) ? 1 : 0; 
key_vals[4] = (regval & (1<<4)) ? 1 : 0; 
key_vals[5] = (regval & (1<<5)) ? 1 : 0; 
/*for(i=0;i<6;i++)
{
key_vals[i] = ( regval & (1 << i ) ) ? 1 : 0; //括號內爲真時,輸出爲1,且賦值給 key_vals[i];
}*/
copy_to_user(buf,key_vals,sizeof(key_vals));
return sizeof(key_vals);
}

static ssize_t second_drv_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos)
{

return 0;
}

static struct file_operations second_drv_fops = {
.owner = THIS_MODULE,
.open  = second_drv_open,
.read  = second_drv_read,
.write = second_drv_write,
};                                                                            //結構體中 ,使用的 逗號 “ , ”    而在結束後要加個 分號“ ; ”

int major;  // 用於存儲自動創建的設備號
static int second_drv_init(void)
{
major = register_chrdev(0,"seconddrv",&second_drv_fops);//註冊將open和read和write函數告訴內核,通過cat proc/devices查看


seconddrv_class = class_create(THIS_MODULE,"second_drv");//創建類,類名爲 second_drv   通過 cd /sys/class 查看


seconddrv_class_dev = device_create(seconddrv_class,NULL,MKDEV(major,0),NULL,"buttons");
 //創建類的設備,設備名爲buttons      通過cd /dev/查看                           

gpncon = (volatile unsigned long *)ioremap(0x7F008830,16);  //用函數ioremap進行虛擬地址重映射到物理地址。
gpndat = gpncon + 1;   //這裏的 +1,是加unsigned long 的大小
return 0;
}


static void second_drv_exit(void)
{
unregister_chrdev(major,"seconddrv");                                        //卸載
device_unregister(seconddrv_class_dev);                             //先卸載設備
class_destroy(seconddrv_class);                                //在刪除所創建的 類
iounmap(gpncon);
}
module_init(second_drv_init);
module_exit(second_drv_exit);
MODULE_LICENSE("GPL");



應用程序如下:secondtest.

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main(int argc,char **argv)
{
int fd;
unsigned char key_vals[6];
int cnt = 0;

fd = open("/dev/buttons",O_RDWR);   //這裏打開的設備名字,/dev/buttons要和 驅動程序中一致。與類的設備名一致,通過 cd /dev查看。
if(fd<0)
printf("can not open file!\n");

while(1)
{
read(fd,key_vals,sizeof(key_vals));
if(!key_vals[0]|| !key_vals[1] || !key_vals[2] || !key_vals[3] || !key_vals[4] || !key_vals[5])
{
printf("%06d key pressed: %d %d %d %d %d %d\n", cnt++, key_vals[0], key_vals[1], key_vals[2], key_vals[3], key_vals[4], key_vals[5]);
}
}
return 0;
}


Makefie程序如下:
obj-m := seconddrv.o    //生成的設備文件名

KDIR := /home/S4-ARM/lesson3/lesson3.3/linux-ok6410  
 //內核所在目錄

all:
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm

 //make會先進入KDIR目錄執行此目錄下的Makfefile程序,然後在返回PWD目錄下執行自己的Makefile函數,交叉編譯工具爲arm-linux-。。。後面的值系統會自動的補全。。架構爲arm架構

clean:
rm -f *.o *.ko *.order *.symvers







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章