本帖最后由 dolphi 于 2013-7-12 08:15 编辑
这篇文章展示如何在BBB平台上编写LED驱动程序,本文的程序是根据国嵌S3C2440的LED驱动的例子并结合内核中OMAP系列的gpio操作来改的。本文中的程序包括驱动程序模块和用户空间程序。废话不多说,先贴程序出来吧。 /**************************************************** am3359_leds_misc.c *****************************************************/ /***************头文件也许不用包含这么多*************/ #include <linux/miscdevice.h> #include <linux/delay.h> //#include <asm/irq.h> #include <linux/gpio.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <asm/unistd.h> #include <asm/io.h> #include <asm/system.h> #include <asm/uaccess.h> //#include <mux.h> #include "memdev.h" #define DEVICE_NAME "leds" static unsigned long led_table[] = { 53, 54, 55,56, }; /*static unsigned intled_cfg_table[] = { OMAP_PIN_OUTPUT, OMAP_PIN_OUTPUT, OMAP_PIN_OUTPUT, OMAP_PIN_OUTPUT, };*/ static int sbc2440_leds_ioctl( struct file *file, unsigned int cmd, unsigned long arg) { int i = 0; /* 检测命令的有效性 */ if (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC) return -EINVAL; if (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR) return -EINVAL; printk("here in kernel ioctl\n"); /* 根据命令,执行相应的操作 */ switch (cmd) { case MEMDEV_IOCOFF: /*灯全灭*/ cmd = 0; for (i = 0; i < 4; i++) gpio_set_value(led_table, cmd); return 0; case MEMDEV_IOCON: /*灯全亮*/ cmd = 1; for (i = 0; i < 4; i++) gpio_set_value(led_table, cmd); return 0; default: return -EINVAL; } } /*文件操作结构体*/ static struct file_operations dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = sbc2440_leds_ioctl, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; int i; /*设置GPIO控制寄存器,GPIO设置为输出模式,默认下灯全灭*/ for (i = 0; i < 4; i++) { // 这四个引脚内核中已经初始化为输出了 // omap_mux_init_gpio(led_table, led_cfg_table); gpio_set_value(led_table, 1); } /*注册混杂型字符设备驱动*/ ret = misc_register(&misc); printk (DEVICE_NAME"\tinitialized\n"); return ret; } static void __exit dev_exit(void) { int i; for (i = 0; i < 4; i++) { gpio_set_value(led_table, 0); } printk(DEVICE_NAME"\tdrivermodule exit\n"); /*注销混杂型字符设备驱动*/ misc_deregister(&misc); } module_init(dev_init) ; module_exit(dev_exit) ; MODULE_AUTHOR("David Xie") ; MODULE_LICENSE("GPL") ; /***************************************************************** memdev.h *****************************************************************/ #ifndef _MEMDEV_H_ #define _MEMDEV_H_ #include <linux/ioctl.h> /* 定义幻数 */ #define MEMDEV_IOC_MAGIC 'k' /* 定义命令 */ #define MEMDEV_IOCON _IO(MEMDEV_IOC_MAGIC, 1) #define MEMDEV_IOCOFF _IO(MEMDEV_IOC_MAGIC, 2) #define MEMDEV_IOC_MAXNR 2 #endif /* _MEMDEV_H_ */ /******************************************************************* Makefile ********************************************************************/ ifneq ($(KERNELRELEASE),) obj-m := am3359_leds_misc.o else KDIR := /root/beaglebone/origin-kernel/kernel/ all: make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul* endif 以上就是内核模块的所有代码了。在Ubuntu中make一下,马上就得到了一个内核模块am3359_leds_misc.ko,用SSH把它和下面这个appled.c以及上面的memdev.h头文件COPY到板子的/home/root/drivers/led文件夹里面(user app可以直接在板子上编译)。 /******************************************************************** appled.c ********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include "memdev.h" /* 包含命令定义 */ int main(int argc, char **argv) { int on; int fd; if (argc != 2 || sscanf(argv[1],"%d", &on) != 1 ||on < 0 ||on > 1 ) { fprintf(stderr, "Usage:%s0|1\n",argv[0]); exit(1); } fd = open("/dev/leds", 0); if (fd < 0) { perror("open deviceleds"); exit(1); } /*通过ioctl来控制灯的亮、灭*/ if(on){ printf("turn on allleds!\n"); ioctl(fd, MEMDEV_IOCON,0); } else { printf("turn offall leds!\n"); ioctl(fd, MEMDEV_IOCOFF, 0); } close(fd); return 0; } 输入以下命令编译用户程序: gcc appled.c-o appled 加载led驱动模块之前运行以下命令可以关闭所有四个led: /usr/bin/led_aging.sh~ 输入以下命令加载led驱动模块: insmod am3359_leds_misc.ko 运行LED用户程序: ./appled 1 参数为1的时候所有4个LED被点亮. ./appled 0 参数为0的时候所有4个LED熄灭. |