s3c24xx_leds驱动
参考嵌入式Linux应用开发完全手册,出现一些问题并加以修改。用的版本是linux-2.6.32.2。
1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/delay.h> 6 #include <linux/device.h> 7 #include <linux/gpio.h> 8 #include <asm/irq.h> 9 //#include <asm/arch/regs-gpio.h> 10 #include <mach/regs-gpio.h> //此处头文件修改 11 //#include <asm/hardware.h> 12 #include <mach/hardware.h> //修改 13 14 #define DEVICE_NAME "leds" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */ 15 #define LED_MAJOR 231 /* 主设备号 */ 16 17 /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */ 18 #define IOCTL_LED_ON 0 19 #define IOCTL_LED_OFF 1 20 21 /* 用来指定LED所用的GPIO引脚 */ 22 static unsigned long led_table [] = 23 { 24 S3C2410_GPB(5), //修改 25 S3C2410_GPB(6), 26 S3C2410_GPB(7), 27 S3C2410_GPB(8), 28 }; 29 30 /* 用来指定GPIO引脚的功能:输出 */ 31 static unsigned int led_cfg_table [] = 32 { 33 S3C2410_GPIO_OUTPUT, //修改 34 S3C2410_GPIO_OUTPUT, 35 S3C2410_GPIO_OUTPUT, 36 S3C2410_GPIO_OUTPUT, 37 }; 38 39 /* 应用程序对设备文件/dev/leds执行open(...)时, 40 * 就会调用s3c24xx_leds_open函数 41 */ 42 static int s3c24xx_leds_open(struct inode *inode, struct file *file) 43 { 44 int i; 45 46 for (i = 0; i < 4; i++) { 47 // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能 48 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); 49 } 50 return 0; 51 } 52 53 /* 应用程序对设备文件/dev/leds执行ioclt(...)时, 54 * 就会调用s3c24xx_leds_ioctl函数 55 */ 56 static int s3c24xx_leds_ioctl( 57 struct inode *inode, 58 struct file *file, 59 unsigned int cmd, 60 unsigned long arg) 61 { 62 if (arg > 4) { 63 return -EINVAL; 64 } 65 66 switch(cmd) { 67 case IOCTL_LED_ON: 68 // 设置指定引脚的输出电平为0 69 s3c2410_gpio_setpin(led_table[arg], 0); 70 return 0; 71 72 case IOCTL_LED_OFF: 73 // 设置指定引脚的输出电平为1 74 s3c2410_gpio_setpin(led_table[arg], 1); 75 return 0; 76 77 default: 78 return -EINVAL; 79 } 80 } 81 82 /* 这个结构是字符设备驱动程序的核心 83 * 当应用程序操作设备文件时所调用的open、read、write等函数, 84 * 最终会调用这个结构中指定的对应函数 85 */ 86 static struct file_operations s3c24xx_leds_fops = { 87 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ 88 .open = s3c24xx_leds_open, 89 .ioctl = s3c24xx_leds_ioctl, 90 }; 91 92 /* 93 * 执行“insmod s3c24xx_leds.ko”命令时就会调用这个函数 94 */ 95 static int __init s3c24xx_leds_init(void) 96 { 97 int ret; 98 99 /* 注册字符设备驱动程序 100 * 参数为主设备号、设备名字、file_operations结构; 101 * 这样,主设备号就和具体的file_operations结构联系起来了, 102 * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数 103 * LED_MAJOR可以设为0,表示由内核自动分配主设备号 104 */ 105 ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops); 106 if (ret < 0) { 107 printk(DEVICE_NAME " can't register major number\n"); 108 return ret; 109 } 110 111 printk(DEVICE_NAME " initialized\n"); 112 return 0; 113 } 114 115 /* 116 * 执行”rmmod s3c24xx_leds.ko”命令时就会调用这个函数 117 */ 118 static void __exit s3c24xx_leds_exit(void) 119 { 120 /* 卸载驱动程序 */ 121 unregister_chrdev(LED_MAJOR, DEVICE_NAME); 122 } 123 124 /* 这两行指定驱动程序的初始化函数和卸载函数 */ 125 module_init(s3c24xx_leds_init); 126 module_exit(s3c24xx_leds_exit); 127 128 /* 描述驱动程序的一些信息,不是必须的 */ 129 MODULE_AUTHOR("Huang"); // 驱动程序的作者 130 MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver"); // 一些描述信息 131 MODULE_LICENSE("GPL"); // 遵循的协议
将修改好的该文件放到编译好的 linux-2.6.32.2/drivers/char 目录下,修改该目录下的Makefile,增加 obj-m +=s3c24xx_leds.o
返回该内核根目录执行make modules:
观察到生成了s3c24xx_leds,ko模块。