跟着韦东山老师学字符设备驱动之查询方式的按键驱动程序分析

驱动程序如下: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







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值