看了这么多的资料,现在决定上手了,下面将用两种方式来实现对GPIO 117的控制
1,用直接添加到内核的方式,实现MISC的驱动(misc_register)
2,用手工安装的方式,实现简单字符设备驱动(register_chrdev)
实现前提:当前所用的GPIO没有被其它设备所使用,大家可以用我前面BLOG说的方式查看GPIO的使用情况,当前我所用的GPIO本来是bluetooth的开关,需要屏蔽一个函数。不然后面的驱动申请IO都会失败。
函数为Board-am335xevm.c 中的wl12xx_bluetooth_enable();
一,MISC驱动的实现
1,参考linux SDK for AM335x Ver 1.1.pdf P28,添加kernel 配置选项
打开/driver/input/misc/Kconfig并添加:
config INPUT_GPIOTEST bool "Gpio 117 test" help Just test the Gpio 117 status
打开/driver/input/misc/Makefile并添加:
obj-$(CONFIG_INPUT_GPIOTEST)+=GpioTestDriver.o
2,实现GpioTestDriver.c
#include <linux/gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/types.h> #include <linux/miscdevice.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/init.h> #define TEST_IO_NUM(117) #define NAME_MISC"GpioTest" #define NAME_MOUDULE"GpioTest1" #define USE_MISC_MODE1 static int major = 251; void GpioTest(void); static long GpioIOctl(struct file *filp, unsigned cmd, unsigned long arg) { GpioTest(); return 1; } void GpioTest(void) { int iCount = 0; for(iCount = 0; iCount <=20; iCount++ ) { if(iCount%2 == 0) { gpio_direction_output(TEST_IO_NUM, 1); printk(KERN_INFO"#######IO117 statu is high.\r\n"); } else { gpio_direction_output(TEST_IO_NUM, 0); printk(KERN_INFO"#######IO117 statu is low.\r\n"); } mdelay(3000); } printk(KERN_INFO"#######App run over!"); } static int GpioOpen(struct inode *inode, struct file *file) { int iRen = -1; iRen = gpio_request(TEST_IO_NUM, "IO117"); if(iRen < 0) { printk(KERN_INFO"#######Failed to request the IO117!"); }else { printk(KERN_INFO"#######Success to request the IO117"); } return iRen; } static int GpioClose(struct inode *inode, struct file *file) { printk(KERN_INFO"#######Free the IO117"); gpio_free(TEST_IO_NUM); return 1; } //****entry point for TEST GPIO module static const struct file_operations gpio_test_driver = { .owner = THIS_MODULE, .unlocked_ioctl= GpioIOctl, .llseek = no_llseek, .open = GpioOpen, .release = GpioClose, }; #if USE_MISC_MODE static struct miscdevice gpiotest_misc_device = { .minor = MISC_DYNAMIC_MINOR, .name = NAME_MISC, .fops = &gpio_test_driver, }; #endif static int __init GpioTestInit(void) { int iRet; printk(KERN_INFO"#######GpioTest modules is install!\r\n"); #if USE_MISC_MODE iRet = misc_register(&gpiotest_misc_device); if (iRet) { printk(KERN_INFO"#######unable to register a misc device\r\n"); return iRet; } #else iRet = register_chrdev(major, NAME_MOUDULE, &gpio_test_driver); if (iRet < 0) { printk(KERN_INFO"#######unable to register a chr device\r\n"); return iRet; } #endif return iRet; } static void __exit GpioTestExit(void) { #if USE_MISC_MODE misc_deregister(&gpiotest_misc_device); #else unregister_chrdev(major, NAME_MOUDULE); #endif printk(KERN_INFO"#######GpioTest modules is exit!\r\n"); } module_init(GpioTestInit); module_exit(GpioTestExit); MODULE_AUTHOR("david.hu<343556608@qq.com>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Gpio117 Test driver");
3,直接编译:
make uImage
拷到小板上升级运行
注意启动的过程有打印:
[ 3.730712] #######GpioTest modules is install!
这里表示我们的驱动已经合入NK里去了,当然我们也可以命令:ls /dev,可以看到有GpioTest这个存在
4,写测试APP
#include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> #include <unistd.h> #include <sys/stat.h> #include <linux/input.h> #include <fcntl.h> int main(int argc, char *argv) { int fd; fd = open("/dev/GpioTest", O_RDWR); if(fd < 0) { printf("***Can't open the gpiotest!\r\n"); return -1; } ioctl(fd, 0, 0); close(fd); printf("***App run over!\r\n"); return 1; }
将编译的.out文件拷到小机上面运行,看是不是会打印正确的结果。
二,字符设备驱动的实现
1,代码的实现,请将上面MISC的代码里#define USE_MISC_MODE1改成0
2,makefile的实现
KERNEL_DIR := /home/ding/workdir/david/EVMBoard/board-support/linux-3.2 PLATFORM := "am335x-evm" MACHINE_NAME := "am335x" # If CROSS_COMPILE is not set by Rules.make then set a sane default CROSS_COMPILE ?= arm-arago-linux-gnueabi- export CROSS_COMPILE obj-m := GpioTestDriver.o MAKE_ENV = ARCH=arm PWD := $(shell pwd) all: $(MAKE) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" -C $(KERNEL_DIR) $(MAKE_ENV) \ M=$(PWD) modules clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers
3,将编译的ko拷入小机,然后命令:
insmod ./GpioTestDriver.ko lsmod mknod /dev/GpioTestDriver c 251 0
4,实现APP的代码
将上面MISC的代码作如下修改:
fd = open("/dev/GpioTestDriver", O_RDWR);
5,运行APP查看结果
总结:两个驱动代码实现差不多,但是步骤不一样,主要体现在模块需要安装。MISC会自动创建设备文件,它的主设备号是10,字符设备需要我们来指定。
可安装的字符设备对驱动的编写测试是非常有帮助的。