驱动第一天 之 第一个驱动.LED
lcled_drv.c
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 <asm/uaccess.h> 7 #include <asm/irq.h> 8 #include <asm/io.h> 9 #include <asm/arch/regs-gpio.h> 10 #include <asm/hardware.h> 11 12 int major; 13 volatile unsigned long *gpbcon = NULL; 14 volatile unsigned long *gpbdat = NULL; 15 16 static int lcled_drv_open(struct inode *inode, struct file *file) 17 { 18 *gpbcon &= ~((0x3<<(5*2)) | (0x3<<(6*2)) | (0x3<<(7*2)) | (0x3<<(8*2))); 19 *gpbcon |= ((0x1<<(5*2)) | (0x1<<(6*2)) | (0x1<<(7*2)) | (0x1<<(8*2))); 20 return 0; 21 } 22 23 static ssize_t lcled_drv_write(struct file *file, const char *buf, size_t count, loff_t *ppos) 24 { 25 int val; 26 copy_from_user(&val, buf, count); 27 if(val == 1){ 28 *gpbdat &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8)); 29 }else{ 30 *gpbdat |= (1<<5) | (1<<6) | (1<<7) | (1<<8); 31 } 32 33 } 34 35 static struct file_operations lcled_drv_fops = { 36 .owner = THIS_MODULE, 37 .open = lcled_drv_open, 38 .write = lcled_drv_write, 39 }; 40 41 static int lcled_drv_init(void) 42 { 43 major = register_chrdev(0, "lcled_drv", &lcled_drv_fops); 44 gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16); 45 gpbdat = gpbcon + 1; 46 47 return 0; 48 } 49 50 static void lcled_drv_exit(void) 51 { 52 unregister_chrdev(major, "lcled_drv"); 53 iounmap(gpbcon); 54 } 55 56 57 58 module_init(lcled_drv_init); 59 module_exit(lcled_drv_exit); 60 61 MODULE_LICENSE("GPL");
Makefile
1 KERN_DIR = /home/book/linux-2.6.25.8 2 3 all: 4 make -C $(KERN_DIR) M=`pwd` modules 5 6 clean: 7 make -C $(KERN_DIR) M=`pwd` modules clean 8 rm -rf modules.order 9 10 obj-m += lcled_drv.o
test
1 #include <stdio.h> 2 #include <fcntl.h> 3 4 int main(int argc, char **argv) 5 { 6 int fd; 7 int val = 1; 8 fd = open("/dev/lcled", O_RDWR); 9 if (fd < 0) 10 { 11 printf("can't open!\n"); 12 } 13 if (argc != 2) 14 { 15 printf("Usage :\n"); 16 printf("%s <on|off>\n", argv[0]); 17 return 0; 18 } 19 20 if (strcmp(argv[1], "on") == 0) 21 { 22 val = 1; 23 } 24 else 25 { 26 val = 0; 27 } 28 29 write(fd, &val, 4); 30 return 0; 31 }
函数原型:
int (*open)(struct inode *inode, struct file *filp);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
module_init(lcled_drv_init);
module_exit(lcled_drv_exit);是用于注册和删除驱动程序
这个比较简单,网上有很多分析的文章,这里只是作为自己简单的记录,这个驱动是韦东山《嵌入式linux应用开发完全手册》配套光盘里的first_drv精简的。但是未精简之前的代码在编译的时候会有这个问题:用2.6.22.6内核编译可以顺利通过,但用TQ光盘提供的2.6.25.8内核却会报错,要添加一个头文件:
#include <linux/device.h>,这样就能编译成功了。(就这个昨天倒腾到今天,主要还是方法欠佳,经验教训!!- -!)再续!!!