/******************************* * *雜項設備驅動: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); }