AM335x内核模块驱动之LED
在Ubuntu的任意可操作的文件才建立text目录
在text中建立zyr-hello.c:
#include<linux/kernel.h> #include<linux/module.h> #include<linux/init.h> #include <linux/miscdevice.h> #include <linux/types.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/delay.h> #include <linux/gpio.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/init.h> #define CORE_LED (1*32 + 7) //硬件上的一个led灯为goip1_7 #define DEVICE "led_core" #define MAGIC_NUM 0xDB #define MAGIC_SET_LOW _IO(MAGIC_NUM,0) #define MAGIC_SET_HIGH _IO(MAGIC_NUM,1) int led_open(struct inode *inode, struct file *file) { int ret; ret = gpio_request_one(CORE_LED, (GPIOF_DIR_OUT|GPIOF_OUT_INIT_HIGH),"core_led"); if(ret) { printk("Error: cannot request gpio CORE_LED. \n"); printk("Error ret = %d but still can be manipulated. \n", ret); } gpio_set_value(CORE_LED,1); return 0; } int led_release(struct inode *inode, struct file *filp) { gpio_free(CORE_LED); printk("GPIO LED dev release. \n"); return 0; } long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case MAGIC_SET_LOW: printk("GPIO LED set low.\n"); gpio_set_value(CORE_LED,0); break; case MAGIC_SET_HIGH: printk("GPIO LED set high.\n"); gpio_set_value(CORE_LED,1); break; default: printk("ERROR unvalid cmd.\n"); break; } return 0; } struct file_operations led_fops ={ .owner = THIS_MODULE, .open = led_open, .release = led_release, .unlocked_ioctl = led_ioctl, }; struct miscdevice led_dev ={ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE, .fops = &led_fops, }; static int led_init(void) { int ret; ret = misc_register(&led_dev); if (ret) { printk("Error: cannot register misc. \n"); return ret; } printk("misc-register %s\n",DEVICE); return 0; } static void led_exit(void) { misc_deregister(&led_dev); printk("misc-deregister %s\n",DEVICE); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("zyr<yr736002477@qq.com>");
在该目录下建立Makefile文件:
ifneq ($(KERNELRELEASE),) obj-m := zyr-hello.o else KDIR :=/home/zyr/Source_code/linux-3.14.65/ all: make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8 clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order endif
其中KDIR为内核的路径,要想编译arm可运行的驱动,一定要指定交叉编译器
在该目录下执行make,会编译器出zyr-hello.ko文件,此文件为可加载于内核的.ko模块的文件。
然后编写这个led驱动的的测试文件(运行在文件系统中):
同样在任意的可执行处建立一个目录放测试文件比如aa:
在该目录下建立led_test.c:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<errno.h> #include<string.h> #include<asm-generic/ioctl.h> #define DEVICE "/dev/led_core" #define MAGIC_NUM 0xDB #define MAGIC_SET_LOW _IO(MAGIC_NUM, 0) #define MAGIC_SET_HIGH _IO(MAGIC_NUM, 1) int main(int argc, char *argv[]) { int fd; printf("Start led test.\n"); fd = open(DEVICE, O_RDWR); if (fd < 2) { printf("Cannot open device %s\n", DEVICE); return -EFAULT; } while (1) { ioctl(fd, MAGIC_SET_LOW, 0); sleep(1); ioctl(fd, MAGIC_SET_HIGH, 0); sleep(1); } return 0; }
在该目录下建立Makefile文件:
#---------------------------- CC = arm-linux-gnueabihf-gcc CFLAGS = main : led_test.c $(CC) $(CFLAGS) led_test.c -o led_test
在该目录下执行make:生成led_test可执行文件。
将led_test可执行文件和zyr-hello.ko模块文件copy到建立好的NFS共享文件夹下敲击命令(在arm板的终端中):
[root@zyr-am335x ]#mount -t nfs -o nolock 192.168.200.123:/home/zyr/Source_code/text/nfs /mnt [root@zyr-am335x ]#cd /mnt [root@zyr-am335x mnt]#ls led_test zyr-hello.ko [root@zyr-am335x mnt]#insmod zyr-hello.ko [ 5299.759382] misc-register led_core [root@zyr-am335x mnt]#./led_test Start led test. [ 5309.324907] GPIO LED set low. [ 5310.338522] GPIO LED set high. [ 5311.342169] GPIO LED set low. [ 5312.345413] GPIO LED set high.
参考博客:
http://www.eefocus.com/marianna/blog/15-02/310302_72e75.html