查询的方式获取按键值驱动的步骤大致如下:
一、框架
1.file_operations的填充
2.入口函数注册register_chrdev
3.修饰入口函数/出口函数
4.自动创建设备节点
测试程序:
一、框架
1.file_operations的填充
2.入口函数注册register_chrdev
3.修饰入口函数/出口函数
4.自动创建设备节点
二、硬件操作
一、框架:
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
#include <linux/notifier.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/uaccess.h>
struct class *buttons_class;
struct device *buttons_dev;
static int buttons_drv_open(struct inode *inode, struct file *file)
{
printk("buttons_drv_open \n");
return 0;
}
static ssize_t buttons_drv_read( struct file *file,
char __user *buffer,
size_t len,
loff_t *offset )
{
printk("buttons_drv_read \n");
}
static struct file_operations buttons_fops = {
.owner = THIS_MODULE,
.open = buttons_drv_open,
.read = buttons_drv_read,
};
int major;
static int __init buttons_drv_init(void)
{
major = register_chrdev(0,"buttons",&buttons_fops);
buttons_class = class_create(THIS_MODULE,"buttons");
buttons_dev = device_create(buttons_class,NULL,MKDEV(major,0),NULL,"buttons");
return 0;
}
static void __exit buttons_drv_exit(void)
{
device_destroy(buttons_class,MKDEV(major,0));
class_destroy(buttons_class);
unregister_chrdev(major,"buttons");
}
module_init(buttons_drv_init);
module_exit(buttons_drv_exit);
MODULE_LICENSE("GPL");
二、硬件操作:
查看SCH按键引脚对应的gpio如下:
KEYINT1----》GPN0
KEYINT2----》GPN1
KEYINT3----》GPN2
KEYINT4----》GPN3
KEYINT5----》GPN4
KEYINT6----》GPN5
物理地址:GPNCON 0x7F008830
对物理地址进行映射:ioremap
open中配置为输入引脚:GPNCON &= ~0xfff
没有按下时为高电平,按下后是低电平
read中读取引脚的状态: state = (GPNDAT | 1 << x) ? 1 : 0;
驱动代码如下:
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
#include <linux/notifier.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/uaccess.h>
struct class *buttons_class;
struct device *buttons_dev;
volatile unsigned long *gpncon = NULL;
volatile unsigned long *gpndat = NULL;
static int buttons_drv_open(struct inode *inode, struct file *file)
{
printk("buttons_drv_open \n");
//配置按键gpio引脚为输入引脚
*gpncon &= ~0xfff;
return 0;
}
static ssize_t buttons_drv_read( struct file *file,
char __user *buffer,
size_t len,
loff_t *offset )
{
// printk("buttons_drv_read \n");
char reg_val[6];
if(len != sizeof(reg_val)){
return -EINVAL;
}
int i;
for(i = 0 ; i < 6 ; i++){
reg_val[i] = (*gpndat & 1 << i ) ? 1 : 0;
}
copy_to_user(buffer,reg_val,sizeof(reg_val));
return sizeof(reg_val);
}
static struct file_operations buttons_fops = {
.owner = THIS_MODULE,
.open = buttons_drv_open,
.read = buttons_drv_read,
};
int major;
static int __init buttons_drv_init(void)
{
major = register_chrdev(0,"buttons",&buttons_fops);
buttons_class = class_create(THIS_MODULE,"buttons");
buttons_dev = device_create(buttons_class,NULL,MKDEV(major,0),NULL,"buttons");
gpncon = (volatile unsigned long *)ioremap(0x7F008830 ,16);
gpndat = gpncon + 1;
return 0;
}
static void __exit buttons_drv_exit(void)
{
device_destroy(buttons_class,MKDEV(major,0));
class_destroy(buttons_class);
unregister_chrdev(major,"buttons");
iounmap(gpncon);
}
module_init(buttons_drv_init);
module_exit(buttons_drv_exit);
MODULE_LICENSE("GPL");
测试程序:
#include <stdio.h>
#include <fcntl.h>
int main(int argc ,char **argv)
{
int fd ;
int val;
int cnt = 0;
char key_val[6];
char *filename = "/dev/buttons";
fd = open(filename,O_RDWR);
if(fd < 0){
printf("Can not open devices\n");
return -1;
}
while(1){
read(fd,key_val,sizeof(key_val));
if(!key_val[0] || !key_val[1] || !key_val[2] || !key_val[3] || !key_val[4] || !key_val[5]){
printf(" %d cnts Keypad are pressed %d %d %d %d %d %d \n",cnt++,!key_val[0],!key_val[1],!key_val[2],!key_val[3],!key_val[4],!key_val[5]);
}
}
return 0;
}
这个是使用while循环的查询方式进行读取按键的值,
在驱动中的读操作也一直处于一直读的状态,这样会导致系统占用资源很多。
如下所示: