標籤:
經過幾天的學習,終於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 0int 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;}
Smart210---LED驅動