/******************************* * *杂项设备驱动:miscdevice *majior=10; * * *****************************/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/init.h> //#include <linux/moduleparam.h> //#include <linux/slab.h>//kcalloc,kzalloc等内存分配函数 //---------ioctl------------ #include <linux/ioctl.h> //---------misc_register---- #include <linux/miscdevice.h> //----------cdev-------------- #include <linux/cdev.h> //----------delay------------- #include <linux/delay.h> //----------GPIO--------------- #include <mach/gpio.h> #include <mach/regs-gpio.h> #include <plat/gpio-cfg.h> #define DEVICE_NAME "leds" static int led_gpios[] = { S5PV210_MP04(4), S5PV210_MP04(5), S5PV210_MP04(6), S5PV210_MP04(7), };//4个LED #define LED_NUM ARRAY_SIZE(led_gpios) static long fl210_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case 0: case 1: if (arg > LED_NUM) { return -EINVAL; } gpio_set_value(led_gpios[arg], !cmd);//根据cmd设置LED的暗灭 printk(DEVICE_NAME": %ld %d\n", arg, cmd); break; default: return -EINVAL; } return 0; } static struct file_operations fl210_led_dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = fl210_leds_ioctl, }; //----------------miscdevice------------------ static struct miscdevice fl210_led_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &fl210_led_dev_fops, }; //-------------------------------------------- static int __init fl210_led_dev_init(void) { int ret; int i; for (i = 0; i < LED_NUM; i++) { ret = gpio_request(led_gpios[i], "LED");//申请GPIO口 if (ret) { printk("%s: request GPIO %d for LED failed, ret = %d\n", DEVICE_NAME, led_gpios[i], ret); return ret; } s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);//设置GPIO口为输出 gpio_set_value(led_gpios[i], 1);//初始化GPIO口的值 } ret = misc_register(&fl210_led_dev);//注册杂项设备 printk(DEVICE_NAME"\tinitialized\n"); printk("led num is: %d\n",LED_NUM); return ret; } static void __exit fl210_led_dev_exit(void) { int i; for (i = 0; i < LED_NUM; i++) { gpio_free(led_gpios[i]);//释放GPIO口 } misc_deregister(&fl210_led_dev);//注销设备 } module_init(fl210_led_dev_init); module_exit(fl210_led_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("");
S5PV210_MP04宏定义在linux/arch/arm/mach-s5pv210/include/mach/gpio.h
#define S5PV210_MP04(_nr) (S5PV210_GPIO_MP04_START + (_nr))
S5PV210_GPIO_MP04_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP03),
#define S5PV210_GPIO_NEXT(__gpio) \ ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
//这里的CONFIG_S3C_GPIO_SPAC是内核配置选项,在.config中可以找到,我的配置为: CONFIG_S3C_GPIO_SPACE = 0
上述代码用到以下几个函数:
gpio_set_value();
s3c_gpio_cfgpin();
gpio_request();
gpio_free();
misc_register();
misc_deregister();
后面会逐个分析。
测试程序如下:
#include <stdio.h> //#include "sys/types.h" #include <sys/ioctl.h> #include <stdlib.h> #include <unistd.h>//read,write等等 //#include "termios.h" //#include "sys/stat.h" #include <fcntl.h> #define LED2_ON 0x1 #define LED2_OFF 0x0 main(int argc,char *argv[]) { int fd; if ((fd=open("/dev/leds",O_RDWR /*| O_NDELAY | O_NOCTTY*/)) < 0) { printf("Open Device failed.\r\n"); exit(1); } else { printf("Open Device successed.\r\n"); } if (argc<3) { /* code */ printf("Usage: %s <on|off num>\n",argv[0]); exit(1); } if(!strcmp(argv[1],"on")) { printf("led1 will on!!\n"); if(ioctl(fd,LED2_ON,atoi(argv[2]))<0) { printf("ioctl err!!\n"); } } if(!strcmp(argv[1],"off")) { printf("led1 will off!!\n"); if(ioctl(fd,LED2_OFF,atoi(argv[2]))<0) { printf("ioctl err!!\n"); } } close(fd); }