经过几天的学习,终于linux驱动的基本框架弄清楚了。。。真的很艰辛,,,不过终于还是熬过来了,虽然还是最基础的,,,
今晚也完成了我第一个linux驱动,,,心里还是有点小兴奋的,哈哈O(∩_∩)O
直接上驱动源程序吧:::
我的开发板是Smart210,根据原理图,IO口输出0 led亮,输出1 led灭
#include <linux/kernel.h> #include <linux/module.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/delay.h> #include <mach/gpio.h> #include <mach/regs-gpio.h> #include <plat/gpio-cfg.h> #define DEVICE_NAME "leds" /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */ /*the second parameter that application program execute*/ #define IOCTL_GPIO_ON 1 #define IOCTL_GPIO_OFF 0 /* 用来指定LED所用的GPIO引脚 */ /*appoint the pin the LED will use*/ static unsigned long leds_table [] = { S5PV210_GPJ2(0), S5PV210_GPJ2(1), S5PV210_GPJ2(2), S5PV210_GPJ2(3), //arch\arm\mach-s5pv210\include\mach\gpio.h }; static char leds_name[][4]={{"LED1"},{"LED2"},{"LED2"},{"LED3"}}; #define LED_NUM ARRAY_SIZE(leds_table) /** *函数功能:打开/dev/led设备 *fuction:open /dev/leds device *设备名是:/dev/leds *devce name: /dev/leds **/ static int my_led_open(struct inode *inode, struct file *file) { int i; int err; for (i = 0; i < LED_NUM; i++) { err = gpio_request(leds_table[i], leds_name[i]); //drivers/gpio/gpiolib.c if(err) { printk(KERN_ERR "failed to request S5PV210_GPH2(%d) for LED%d \n",i-1,i); return err; } } for (i = 0; i < LED_NUM; i++) { s3c_gpio_cfgpin(leds_table[i], S3C_GPIO_OUTPUT);//Configuration pin function:input output multiplex gpio_set_value(leds_table[i], 1);//Set the pin level //arch\arm\plat-samsung\gpio-config.c // gpio_direction_output(leds_table[i], 0);//write a value to GPIO port ,also set the port to output mode // gpio_set_value(leds_table[i], 0); //drivers/gpio/gpiolib.c } printk(KERN_INFO "LEDs driver successfully close\n"); return 0; } static long my_led_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { arg -= 1; if(arg > LED_NUM) { return -EINVAL; } switch(cmd) { case IOCTL_GPIO_ON: printk("led light\n"); gpio_set_value(leds_table[arg], 0); break; case IOCTL_GPIO_OFF: printk("led no light\n"); gpio_set_value(leds_table[arg], 1); break; default: printk("led failed\n"); return -EINVAL; } return 0; } static int my_led_close(struct inode * inode,struct file * file) { int i; for(i= 0; i < LED_NUM; i++) gpio_free(leds_table[i]); printk(KERN_EMERG"close success\n"); return 0; } struct file_operations my_led_ops = { .owner = THIS_MODULE, .open = my_led_open, .unlocked_ioctl = my_led_ioctl, .release = my_led_close, }; static struct miscdevice led_misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &my_led_ops, }; static int __init my_led_init(void) { int ret; ret = misc_register(&led_misc); if(ret) { printk(KERN_INFO"misc_register failed\n"); } printk(KERN_INFO"misc_register sucessed\n"); return 0; } static void __exit my_led_exit(void) { int i; misc_deregister(&led_misc); for(i= 0; i < LED_NUM; i++) gpio_free(leds_table[i]); printk(KERN_INFO "LEDs driver successfully exit\n"); } module_init(my_led_init); module_exit(my_led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("qigaohua");
应用程序:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/time.h> #define IOCTL_GPIO_ON 1 #define IOCTL_GPIO_OFF 0 int main(int argc, char **argv) { int fd; fd = open("/dev/leds",0); if(fd < 0) { printf("/dev/leds open failed\n"); exit(1); } do { printf("/dev/leds open sucessed\n"); ioctl(fd, IOCTL_GPIO_ON, 1); ioctl(fd, IOCTL_GPIO_OFF, 2); ioctl(fd, IOCTL_GPIO_OFF, 3); ioctl(fd, IOCTL_GPIO_OFF, 4); sleep(1); ioctl(fd, IOCTL_GPIO_ON, 1); ioctl(fd, IOCTL_GPIO_ON, 2); ioctl(fd, IOCTL_GPIO_OFF, 3); ioctl(fd, IOCTL_GPIO_OFF, 4); sleep(1); ioctl(fd, IOCTL_GPIO_ON, 1); ioctl(fd, IOCTL_GPIO_ON, 2); ioctl(fd, IOCTL_GPIO_ON, 3); ioctl(fd, IOCTL_GPIO_OFF, 4); sleep(1); ioctl(fd, IOCTL_GPIO_ON, 1); ioctl(fd, IOCTL_GPIO_ON, 2); ioctl(fd, IOCTL_GPIO_ON, 3); ioctl(fd, IOCTL_GPIO_ON, 4); sleep(1); ioctl(fd, IOCTL_GPIO_OFF, 1); ioctl(fd, IOCTL_GPIO_OFF, 2); ioctl(fd, IOCTL_GPIO_OFF, 3); ioctl(fd, IOCTL_GPIO_OFF, 4); }while(0); close(fd); return 0; }