linux平台总线驱动设备模型之点亮LED
来源:互联网 发布:上瘾网络剧见面会视频 编辑:程序博客网 时间:2024/05/01 04:53
上一节中,我们详细分析了平台驱动设备模型的源码,懂得了框架是如何构成的。
上一节文章链接:http://blog.csdn.net/lwj103862095/article/details/17957637
这一节里,我们来使用平台驱动设备这一套架构来实现我们之前使用简单的字符设备驱动点亮LED,这里并无实际意义,只是告诉大家如果编写平台总线驱动设备。
问:如何编写平台总线驱动设备这一套架构的设备驱动?
答:分为两个.c文件,一个是drv.c,另一个是dev.c;前者实现平台驱动,后者实现平台设备,平台总线不用我们自己实现。
问:编写平台驱动的核心内容有哪些?
答:分配、设置、注册一个platform_driver
问:如何注册平台驱动?
答:使用platform_driver_register(struct platform_driver *drv)函数,该函数的参数为platform_driver
问:如何定义platform_driver?
答:简单示例
static struct platform_driver led_driver = {.probe= led_probe,.remove= led_remove,.driver= {.name= "myled",.owner= THIS_MODULE,}};问:probe函数什么时候被调用?
答:当系统中有同名的平台设备和平台驱动时,就会调用probe函数。
问:probe函数有什么作用?
答:该函数可以做什么由你决定,你可以只打印一条语句,也可以做很复杂的事情。例如,led_probe函数就做了获取资源,映射IO,注册字符设备。
led_drv.c源码参考:
#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/sched.h>#include <linux/pm.h>#include <linux/sysctl.h>#include <linux/proc_fs.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/input.h>#include <linux/gpio_keys.h>#include <asm/uaccess.h> // copy_from_user#include <asm/io.h> // ioremapstatic struct class *led_cls;static volatile unsigned long *gpio_con;static volatile unsigned long *gpio_dat;static int pin;static int major;static int led_open(struct inode * inode, struct file * filp){*gpio_con &= ~(0x3<<(pin*2));*gpio_con |= (0x1<<(pin*2));return 0;}static ssize_tled_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){int val;copy_from_user(&val, buf, count);if(val == 1){/* 点灯 */*gpio_dat &= ~(1<<pin); }else{/* 灭灯 */*gpio_dat |= (1<<pin); }return 0;}/* File operations struct for character device */static const struct file_operations led_fops = {.owner= THIS_MODULE,.open= led_open,.write = led_write,};static int __devinit led_probe(struct platform_device *pdev){struct resource *res;printk("led_probe, found led\n");/* 根据platform_device的资源进行ioremap */res = platform_get_resource(pdev, IORESOURCE_MEM, 0);gpio_con = ioremap(res->start, res->end - res->start + 1);gpio_dat = gpio_con + 1;res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);pin = res->start;/* 注册字符设备 */major = register_chrdev(0, "myled", &led_fops);led_cls = class_create(THIS_MODULE,"myled");device_create(led_cls, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led */return 0;}static int __devexit led_remove(struct platform_device *pdev){printk("led_remove, remove led\n");device_destroy(led_cls, MKDEV(major, 0));class_destroy(led_cls);unregister_chrdev(major, "myled");iounmap(gpio_con);return 0;}static struct platform_driver led_driver = {.probe= led_probe,.remove= led_remove,.driver= {.name= "myled",.owner= THIS_MODULE,}};/* 分配/设置/注册一个platform_driver */static int led_drv_init(void){return platform_driver_register(&led_driver);}static void led_drv_exit(void){platform_driver_unregister(&led_driver);}module_init(led_drv_init);module_exit(led_drv_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("LWJ");MODULE_DESCRIPTION("Just for Demo");
答:分配、设置、注册一个platform_device
问:如何注册平台设备?
答:使用platform_device_register(struct platform_device *pdev)函数,该函数的参数为platform_device
问:如何定义platform_device?
答:简单示例:led_device
static struct platform_device led_device = { .id= -1, .name= "myled", /* 与led_driver的name一致 */ .resource= led_resources, .num_resources= ARRAY_SIZE(led_resources), .dev ={ .release = led_release, },};问:如何定义resource?
答:简单示例:
static struct resource led_resources[] = {[0] = {.start= 0x56000010, /* TQ2440的LED是GPB5,6,7,8, GPBCON地址是0x56000010 */.end= 0x56000010 + 8 -1,.flags= IORESOURCE_MEM,},[1] = {.start= 5,/* LED1 */.end= 5,.flags= IORESOURCE_IRQ,},};led_dev.c源码参考:
#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/interrupt.h>#include <linux/list.h>#include <linux/timer.h>#include <linux/init.h>#include <linux/serial_core.h>#include <linux/platform_device.h>static struct resource led_resources[] = {[0] = {.start= 0x56000010, /* TQ2440的LED是GPB5,6,7,8, GPBCON地址是0x56000010 */.end= 0x56000010 + 8 -1,.flags= IORESOURCE_MEM,},[1] = {.start= 5,/* LED1 */.end= 5,.flags= IORESOURCE_IRQ,},};static void led_release(struct device * dev){}static struct platform_device led_device = { .id= -1, .name= "myled", /* 与led_driver的name一致 */ .resource= led_resources, .num_resources= ARRAY_SIZE(led_resources), .dev ={ .release = led_release, },};/* 分配/设置/注册一个platform_device */static int led_dev_init(void){return platform_device_register(&led_device);}static void led_dev_exit(void){platform_device_unregister(&led_device);}module_init(led_dev_init);module_exit(led_dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("LWJ");MODULE_DESCRIPTION("Just for Demo");应用测试程序源码:
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>/* 9th_led_test on * 9th_led_test off */int main(int argc, char **argv){int fd;int val = 1;fd = open("/dev/led", O_RDWR);if (fd < 0){printf("can't open!\n");}if (argc != 2){printf("Usage :\n");printf("%s <on|off>\n", argv[0]);return 0;}if (strcmp(argv[1], "on") == 0){val = 1;}else{val = 0;}write(fd, &val, 4);return 0;}测试步骤:
9th_led_test first_drv.ko sddiskQt first_test second_drv.koTQLedtest fourth_drv.ko second_testapp_test fourth_test sixth_drv.kobin home sixth_testbusybox led_dev.ko sixthdrvtestbuttons_all_drv.ko led_drv.ko sysbuttons_all_test lib third_drv.kobuttons_input.ko linuxrc third_testdev mnt tmpdriver_test opt udisketc proc usrfifth_drv.ko root varfifth_test sbin web[WJ2440]# insmod led_drv.ko [WJ2440]# insmod led_dev.ko led_probe, found led[WJ2440]# rmmod led_devled_remove, remove ledrmmod: module 'led_dev' not found[WJ2440]# lsmodled_drv 2800 0 - Live 0xbf003000[WJ2440]# insmod led_dev.ko led_probe, found led[WJ2440]# lsmodled_dev 1444 0 - Live 0xbf009000led_drv 2800 0 - Live 0xbf003000[WJ2440]# ls /dev/led -l crw-rw---- 1 root root 252, 0 Jan 2 07:44 /dev/led[WJ2440]# ./9th_led_test Usage :./9th_led_test <on|off>[WJ2440]# ./9th_led_test off[WJ2440]# ./9th_led_test on当执行./9th_led_test off时,led1被熄灭;当执行./9th_led_test on时 led1被点亮。如果你需要点亮led2,那么只需要修改led_dev的led_resources改为:
static struct resource led_resources[] = {[0] = {.start= 0x56000010, /* TQ2440的LED是GPB5,6,7,8, GPBCON地址是0x56000010 */.end= 0x56000010 + 8 -1,.flags= IORESOURCE_MEM,},[1] = {.start= 6,/* LED2 */.end= 6,.flags= IORESOURCE_IRQ,},};这样,应用程序不用更改,即可点亮led2,这样一来就实现了,稳定部分不用修改,只需要修改硬件易变部分,并且应用程序不需要任何更改。
- linux平台总线驱动设备模型之点亮LED
- linux平台总线驱动设备模型之点亮LED
- linux平台总线驱动设备模型之点亮LED
- ok6410学习笔记(15.platform平台总线驱动模型之混杂设备驱动led)
- 总线设备模型-LED驱动
- LINUX设备驱动模型之PLATFORM(平台)总线详解
- Linux设备驱动模型之platform(平台)总线详解
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- Linux平台总线驱动设备模型
- 标准库vector类型简介
- mobiscroll 触屏日期插件
- Android中Bitmap, Drawable, Byte,ID之间的转化
- 关于读取工程根目录下的文件的方法
- 在Mac中显示隐藏文件
- linux平台总线驱动设备模型之点亮LED
- Vmware虚拟机进入BIOS方法
- 帝国cms选取两个表的集合,按某字段排序
- 0020 Java中equals()和hashCode()详解【基础】
- XAMPP下的phpMyAdmin默认登陆不需要验证的解决方法
- K60的计时器/定时器的简单介绍
- Mac中常用的快捷键
- 一篇文章搞定JSON
- 开始