硬件:TQ2440
开发环境:Fedora 10
1、首先参考网上的资料,把按键驱动架构先搭建起来,实现打开和读操作。
key_driver.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#define DEVICE_NUM_NAME "TQ2440_BUTTON"
#define DEVICE_COUNT 1
#define DEVICE_CLASS "tq2440_button_class"
#define DEVICE_NAME "tq2440_button_device"
dev_t devnum;
static struct cdev *cdev_button;
static struct class *button_class;
static struct device *button_device;
static volatile int press_cnt[] = {0, 0, 0, 0};
static int button_open(struct inode *inode,struct file *file)
{
printk("button_open succeed\n");
return 0;
}
static int button_close(struct inode *inode,struct file *file)
{
printk("button_close succeed\n");
return 0;
}
static int button_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
printk("button_read succeed\n");
return 0;
}
static struct file_operations button_op = {
.owner = THIS_MODULE,
.open = button_open,
.release = button_close,
.read = button_read,
};
static int __init button_init(void)
{
int ret;
ret = alloc_chrdev_region(&devnum, 0, DEVICE_COUNT, DEVICE_NUM_NAME);
if (ret < 0) {
printk("%s\t" DEVICE_NAME "\tmajor number can't register\n", __func__);
return ret;
}
printk("%s\t" DEVICE_NAME "\tmajor number:%u:%u registered\n", \
__func__, MAJOR(devnum), MINOR(devnum));
cdev_button = kzalloc(sizeof(struct cdev), GFP_KERNEL);
if (!cdev_button) {
ret = -ENOMEM;
goto fail_kmalloc;
}
cdev_init(cdev_button, &button_op);
cdev_button->owner = THIS_MODULE;
ret = cdev_add(cdev_button, devnum, 1);
if (IS_ERR(&ret)) {
printk("%s\t" "add cdev err!\n", __func__);
goto fail_cdev_add;
}
button_class = class_create(THIS_MODULE, DEVICE_CLASS);
if (IS_ERR(button_class)) {
printk("%s\t" "class create err!\n", __func__);
goto fail_class_create;
}
button_device = device_create(button_class, NULL, devnum, NULL, DEVICE_NAME);
if (IS_ERR(button_device)) {
printk("%s\t" "device create err!\n", __func__);
goto fail_device_create;
}
printk("device_create succeed!\n");
return 0;
fail_device_create:
class_destroy(button_class);
fail_class_create:
cdev_del(cdev_button);
fail_cdev_add:
kfree(cdev_button);
fail_kmalloc:
unregister_chrdev_region(devnum, DEVICE_COUNT);
return ret;
}
static void __exit button_exit(void)
{
device_destroy(button_class, devnum);
class_destroy(button_class);
cdev_del(cdev_button);
kfree(cdev_button);
unregister_chrdev_region(devnum, DEVICE_COUNT);
}
module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE("GPL");
Makefile:
KERN_DIR=/opt/EmbedSky/linux-2.6.30.4
all:
make -C $(KERN_DIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.c *.markers *.order *.symvers
obj-m += key_driver.o
编译:
[root@EmbedSky key]# make
make -C /opt/EmbedSky/linux-2.6.30.4 M=/opt/tq2440_key/TQ2440_key_jiagou/key modules
make[1]: Entering directory `/opt/EmbedSky/linux-2.6.30.4'
CC [M] /opt/tq2440_key/TQ2440_key_jiagou/key/key_driver.o
Building modules, stage 2.
MODPOST 1 modules
LD [M] /opt/tq2440_key/TQ2440_key_jiagou/key/key_driver.ko
make[1]: Leaving directory `/opt/EmbedSky/linux-2.6.30.4'
[root@EmbedSky key]#
测试程序key_app.c:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
int main(int argc, char *argv)
{
int fd;
int ret;
int press_cnt[4];
int i;
fd = open("/dev/tq2440_button_device", O_RDWR);
if (fd < 0) {
printf("can't open!\n");
return 0;
} else
printf("open successed!\n");
ret = read(fd, press_cnt, sizeof(press_cnt));
if (ret < 0){
printf("read err\n");
}
return 0;
}
编译测试程序:
[root@EmbedSky key]# arm-linux-gcc -o key_app key_app.c
[root@EmbedSky key]#
在TQ2440开发板上测试:
[root@EmbedSky /opt]# insmod key_driver.ko
button_init tq2440_button_device major number:252:0 registered
device_create succeed!
[root@EmbedSky /opt]# chmod 777 key_app
[root@EmbedSky /opt]# ./key_app
button_open succeed
open successed!
button_read succeed
button_close succeed
[root@EmbedSky /opt]#