内核驱动:led驱动
作者:互联网
#include <linux/string.h> #include <linux/cdev.h> #include <linux/fs.h> #include <mach/gpio.h> //包含管脚操作的相关函数 #include <linux/device.h> //包含创建设备文件的相关函数 #define DEVICE_NAME "MYS-SAM9X5-ledtest" static int LED_Major = 0; struct cdev cdev; /** 应用程序执行 ioctl(fd, cmd, arg)时的第 2 个参数 **/ #define LED_OFF 0 #define LED_ON 1 static unsigned long led_table [] = { AT91_PIN_PB18, /**led_blue**/ AT91_PIN_PD21, /**led_red**/ }; /*应用程序对设备文件/dev/leds 执行 open()时, *就会调用MYS_SAM9X5_ledtest_open */ static int MYS_SAM9X5_ledtest_open(struct inode *inode, struct file *file) { printk("MYS-SAM9X5-ledtest Driver Open Called!\n"); return 0; } static long MYS_SAM9X5_ledtest_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if((cmd != 1 && cmd != 0) || (arg != 1 && arg != 0)) return -1; switch(cmd) { case LED_ON: if(arg) { at91_set_gpio_value(led_table[arg], 1); } else { at91_set_gpio_value(led_table[arg], 0); } break; case LED_OFF: if(arg) { at91_set_gpio_value(led_table[arg], 0); } else { at91_set_gpio_value(led_table[arg], 1); } break; default: return -EINVAL; } return 0; } static int MYS_SAM9X5_ledtest_release(struct inode *inode, struct file *file) { printk("MYS_SAM9X5_LED Driver Release Called!\n"); return 0; } /*这个结构是字符设备驱动程序的核心 *当应用程序操作设备文件时调用的 open、read等函数, *最终会调用这个结构中指定的对应函数 */ static struct file_operations MYS_SAM9X5_ledtest_fops = { .owner = THIS_MODULE, .open = MYS_SAM9X5_ledtest_open, .release = MYS_SAM9X5_ledtest_release, .unlocked_ioctl = MYS_SAM9X5_ledtest_ioctl, }; static struct class *MYS_SAM9X5_ledtest_class = NULL; /**模块的初始化函数**/ static int __init MYS_SAM9X5_ledtest_init(void) { int result,err; dev_t devno = MKDEV(LED_Major, 0); /**采用自动分配主设备号**/ if (LED_Major) { result = register_chrdev_region(devno, 1, DEVICE_NAME); printk("Got the Major number by register_chrdev_region !\n "); } else { result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME); LED_Major=MAJOR(devno); printk("Got the Major number by alloc_chrdev_region !\n"); } if (result < 0) { printk(DEVICE_NAME " can't register major number\n"); return result; } printk("register MYS_SAM9X5_ledtest Driver OK! Major = %d\n", LED_Major); /**初始化cdev结构**/ cdev_init(&cdev,&MYS_SAM9X5_ledtest_fops); cdev.owner=THIS_MODULE; cdev.ops=&MYS_SAM9X5_ledtest_fops; /**注册字符设备**/ err=cdev_add(&cdev, MKDEV(LED_Major, 0), 1); if (err) { printk("error %d adding led \n ", err); goto fail_cdev_add; } /**自动创建设备文件**/ MYS_SAM9X5_ledtest_class = class_create(THIS_MODULE, DEVICE_NAME); if(IS_ERR(MYS_SAM9X5_ledtest_class)) { printk("Err: failed in MYS_SAM9X5_ledtest class. \n"); goto fail_create_class; } device_create(MYS_SAM9X5_ledtest_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME); /**初始化PB18,PD21引脚**/ at91_set_gpio_output(AT91_PIN_PB18, 1); at91_set_gpio_output(AT91_PIN_PD21, 1); at91_set_deglitch(AT91_PIN_PB18, 1); at91_set_deglitch(AT91_PIN_PD21, 1); printk(DEVICE_NAME " initialized\n"); return 0; fail_create_class: cdev_del(&cdev); fail_cdev_add: unregister_chrdev_region(devno, 1); return -1; } /**模块的撤销函数**/ static void __exit MYS_SAM9X5_ledtest_exit(void) { printk("MYS_SAM9X5 LED DRIVER MODULE EXIT\n"); device_destroy(MYS_SAM9X5_ledtest_class, MKDEV(LED_Major, 0)); class_destroy(MYS_SAM9X5_ledtest_class); cdev_del(&cdev); unregister_chrdev(LED_Major, DEVICE_NAME); } /**指定驱动程序的初始化函数和卸载函数**/ module_init(MYS_SAM9X5_ledtest_init); module_exit(MYS_SAM9X5_ledtest_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alvin"); MODULE_DESCRIPTION("This is an example of MYS_SAM9X5_LEDTEST drivers"); MODULE_ALIAS("A simplest module.");
调用
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #define LED_DEV "/dev/MYS-SAM9X5-ledtest" int main(int argc, char **argv) { int fd, ret, led_num, led_status; if (argc!=3 || sscanf(argv[1],"%d", &led_num)!=1 || sscanf(argv[2],"%d", &led_status)!=1) { printf("\r\nPlease input correct parameters !\r\n\n"); printf("usage:\r\n%s <led_num> <led_status>\r\n", argv[0]); printf("\r\nOptions:\r\n"); printf(" led_num\t- 1 for red led, 0 for blue led.\r\n led_status\t- 1 for ON, 0 for OFF.\r\n\n"); exit(1); } if((led_status!=1 && led_status!=0) || (led_num!=0 && led_num!=1)) { printf("\r\nError: The parameter value must be '0' or '1' !\r\n"); printf("\r\nPlease try again !!! !\r\n\n"); exit(1); } fd = open(LED_DEV, 0); if (fd < 0) { printf("\r\nFail to open device '%s'!\r\n\n", LED_DEV); exit(1); } ret = ioctl(fd, led_status, led_num); if(ret < 0) { printf("\r\nFail calling ioctl !\r\n\n"); } close(fd); return 0; }
标签:led,MYS,LED,ledtest,cdev,内核,驱动,SAM9X5 来源: https://www.cnblogs.com/hshy/p/14265174.html