led驱动程序编写
本文主要包含三部分,led驱动程序led.c编写,编译驱动程序的makefile的编写,以及使用驱动程序的应用程序led_app的编写
一、led.c编写
1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/cdev.h> 4 #include <linux/fs.h> 5 #include <linux/io.h> 6 #include "led.h" 7 #define GPMCON 0x7f008820 8 #define GPMDAT 0x7f008824 9 10 unsigned int *led_config; 11 unsigned int *led_data; 12 13 struct cdev cdev; //静态分配描述符 14 dev_t devno; 15 16 int led_open (struct inode *node, struct file *filp) 17 { 18 led_config = ioremap(GPMCON,4); //地址转化为虚拟地址 19 writel(0x1111,led_config); //为虚拟地址写入值 20 21 led_data = ioremap(GPMDAT,4); //物理地址转化为虚拟地址 22 return 0; 23 } 24 25 //响应系统调用函数的驱动函数 26 long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 27 { 28 switch (cmd) //通过不同命令执行控制命令 29 { 30 case LED_ON: 31 writel(0x00,led_data); 32 return 0; 33 34 case LED_OFF: 35 writel(0xff,led_data); 36 return 0; 37 38 default: 39 return -EINVAL; 40 } 41 } 42 43 static struct file_operations led_fops = 44 { 45 .open = led_open, 46 .unlocked_ioctl = led_ioctl, 47 }; 48 49 static int led_init() 50 { 51 cdev_init(&cdev,&led_fops); //初始化设备描述 52 alloc_chrdev_region(&devno, 0 , 1 , "myled"); //设备号分配 53 cdev_add(&cdev, devno, 1); //注册字符设备 54 return 0; 55 } 56 57 static void led_exit() 58 { 59 cdev_del(&cdev); //驱动注销 60 unregister_chrdev_region(devno,1); //设备号释放 61 } 62 63 module_init(led_init); 64 module_exit(led_exit);
1.1控制led命令的编写---->led.h
1 #define LED_MAGIC 'L' 2 #define LED_ON _IO(LED_MAGIC,0) 3 #define LED_OFF _IO(LED_MAGIC,1)
二、编译led.c的Makefile的编写
obj-m := led.o KDIR :=/home/kernel/kernel/linux-ok6410 all: make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm clean: rm -f *.ko *.o *.order *.symvers *.mod.c *~
三、应用程序的编写
1 #include "led.h" 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include <string.h> 7 8 int main(int argc,char *argv[]) 9 { 10 int fd; 11 int cmd; 12 if(argc<2) 13 { 14 printf("please enter the secnod para! "); 15 } 16 cmd = atoi(argv[1]); //字符参数转化为整形 17 fd = open("/dev/myled",O_RDWR); 18 if(cmd==1) 19 { 20 ioctl(fd,LED_ON); 21 printf ("led on!!! "); 22 } 23 else 24 ioctl(fd,LED_OFF); 25 }
在完成以上步骤之后就可以安装内核模块并且运行应用程序了
运行过程如下:
首先安装内核模块:insmod led.ko
接着查看注册的设备号:cat /proc/devices
可以看出我注册的led驱动对应的设备号是252
所以接着创建字符设备文件:mknod /dev/myled c 252 0
紧接着运行应用程序:
可以看到开发板上面的所有灯都亮了!!!!!!!
四、出现的问题解决
在运行时候莫名奇妙的出现了一个Segmentation fault,后来查找了很久居然发现是应为在编写led.c的代码时候在
1 int led_open (struct inode *node, struct file *filp) 2 { 3 led_config = ioremap(GPMCON,4); //地址转化为虚拟地址 4 writel(0x1111,led_config); //为虚拟地址写入值 5 6 led_data = ioremap(GPMDAT,4); //物理地址转化为虚拟地址 7 return 0; 8 }
这个函数里面缺少了return 0这句差点酿成大祸了。。。。。。。。。。