3 linux bus-drv-dev模型 LED驱动实验

1 bus-drv-dev模型简介

前面的输入子系统,采用了分层设计,今天就引入驱动设计的分层分离的概念,linux系统中bus-drv-dev模型正是基于这种思想设计的。

总线bus

总线就是处理器与设备之间的一个通道,所有的设备通过总线和处理器连接,是一个虚拟的概念。在linux内核中被抽象为bus_type结构体,在include/linux/device.h文件中定义,代码如下图,其中成员match函数主要用于平台注册device和driver的时候,进行匹配用的。

设备device

device与硬件相关,被抽象为一个结构体。通过调用platform_device_add函数,将device放入到bus的dev链表中;再从bus的drv链表中取出每一个drv,通过bus的match函数判断drv是否支持dev;若支持,则可以调用drv的probe函数。

驱动driver

driver是关于操作硬件设备的稳定的代码,被抽象为一个结构体。同样的道理,调用platform_driver_register将drv放入到bus的drv链表中;在取出dev链表中的dev,通过bus的match函数比较;若有匹配的dev,则可以调用dev的probe函数。

2 编写LED驱动

(1)创建两个驱动文件led_dev.c和led_drv.c文件。

(2)在led_dev.c文件中定义led_device结构体,在入口函数中调用platform_device_register函数注册设备,在出口函数中调用platform_device_unregister函数卸载设备。

  1. /* 分配/设置/注册一个platform_device */  
  2.     
  3. #include <linux/kernel.h>  
  4. #include <linux/types.h>  
  5. #include <linux/interrupt.h>  
  6. #include <linux/list.h>  
  7. #include <linux/timer.h>  
  8. #include <linux/init.h>  
  9. #include <linux/serial_core.h>  
  10. #include <linux/platform_device.h>  
  11.     
  12. static struct resource led_resource[] = {  
  13.     [0] = {  
  14.         .start = 0x56000050,  
  15.         .end   = 0x56000050 + 8 - 1,  
  16.         .flags = IORESOURCE_MEM,  
  17.     },  
  18.     [1] = {  
  19.         .start = 4,  
  20.         .end   = 4,  
  21.         .flags = IORESOURCE_IRQ,  
  22.     }  
  23.     
  24. };  
  25.     
  26. static void led_device_release(struct device * pdev)  
  27. {  
  28.     
  29. }  
  30.     
  31. static struct platform_device led_device = {  
  32.     .name               = "myled",  
  33.     .id                 = -1,  
  34.     .num_resources      = ARRAY_SIZE(led_resource),  
  35.     .resource           = led_resource,  
  36.     .dev = {  
  37.             .release = led_device_release,  
  38.     },  
  39. };  
  40.     
  41. int led_dev_init(void)  
  42. {  
  43.     platform_device_register(&led_device);  
  44.         
  45.     return 0;  
  46. }  
  47.     
  48.     
  49. void led_dev_exit()  
  50. {  
  51.     platform_device_unregister(&led_device);  
  52. }  
  53.     
  54.     
  55. module_init(led_dev_init);  
  56. module_exit(led_dev_exit);  
  57.     
  58. MODULE_LICENSE("GPL");  
    1. (3)led_drv.c文件中,首先定义结构体led_drv,主要实现led_drv_probe函数和led_drv_remove函数。在入口处调用platform_driver_register注册driver驱动,出口处调用platform_driver_unregister卸载驱动。
  59. /* 分配/设置/注册一个platform_drv */  
  60.     
  61. #include <linux/delay.h>  
  62. #include <linux/module.h>  
  63. #include <linux/kernel.h>  
  64. #include <linux/fs.h>  
  65. #include <linux/moduleparam.h>  
  66. #include <linux/interrupt.h>  
  67. #include <linux/ioport.h>  
  68. #include <linux/init.h>  
  69. #include <linux/serio.h>  
  70. #include <linux/err.h>  
  71. #include <linux/rcupdate.h>  
  72. #include <linux/platform_device.h>  
  73. #include <asm/uaccess.h>  
  74. #include <asm/irq.h>  
  75. #include <asm/io.h>  
  76. #include <asm/arch/regs-gpio.h>  
  77. #include <asm/hardware.h>  
  78.     
  79. int major = 0;  
  80. static struct class *cls;  
  81. static struct class_device *led_class_dev;  
  82. volatile unsigned long *gpfcon = NULL;  
  83. volatile unsigned long *gpfdat = NULL;  
  84. static int pin;  
  85.     
  86. static int led_drv_probe(struct platform_device *pdev);  
  87. static int led_drv_remove(struct platform_device *pdev);  
  88.     
  89. struct platform_driver led_drv = {  
  90.     .probe      = led_drv_probe,  
  91.     .remove     = led_drv_remove,  
  92.     .driver     = {  
  93.         .name   = "myled",  
  94.     }  
  95. };  
  96.     
  97. static int led_open(struct inode *inode, struct file *file)  
  98. {  
  99.     //printk("first_drv_open ");  
  100.     
  101.     /* 配置GPF456位输出 */  
  102.     *gpfcon &= ~(0x3<<(pin*2));  
  103.     *gpfcon |= (0x1<<(pin*2));  
  104.     return 0;  
  105. }  
  106.     
  107. static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)  
  108. {  
  109.     int val;  
  110.     //printk("first_drv_wrie ");  
  111.     
  112.     copy_from_user(&val, buf, count);       //  
  113.         
  114.     if(val == 1)  
  115.     {  
  116.         //亮灯  
  117.         *gpfdat &= ~(1<<pin);  
  118.     }  
  119.     else  
  120.     {  
  121.         //灭灯  
  122.         *gpfdat |= (1<<pin);  
  123.     }  
  124.     return 0;  
  125. }  
  126.     
  127. static struct file_operations led_drv_fops = {  
  128.     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */  
  129.     .open   =   led_open,       
  130.     .write  =   led_write,  
  131. };  
  132.     
  133. static int led_drv_probe(struct platform_device *pdev)  
  134. {  
  135.     struct resource *res;  
  136.         
  137.     /* 根据platform_device的资源进行ioremap */  
  138.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  139.     gpfcon = (volatile unsigned long *)ioremap(res->start, res->end - res->start +1);  
  140.     gpfdat = gpfcon + 1;  
  141.     
  142.     res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  
  143.     pin = res->start;  
  144.         
  145.     /* 注册一个字符设备 */  
  146.     major = register_chrdev(0, "led", &led_drv_fops);  
  147.     
  148.     cls = class_create(THIS_MODULE, "leddrv");  
  149.     led_class_dev = class_device_create(cls, NULL, MKDEV(major, 0), NULL,"led");  
  150.     
  151.         
  152.     printk("led_drv_probe, found led ");  
  153.     return 0;  
  154. }  
  155.     
  156.     
  157. static int led_drv_remove(struct platform_device *pdev)  
  158. {  
  159.     /* 根据platform_device的资源进行iounmap */  
  160.     
  161.     /* 卸载一个字符设备 */  
  162.     class_device_unregister(led_class_dev);  
  163.     class_destroy(cls);  
  164.     unregister_chrdev(major, "myled");  
  165.     
  166.     iounmap(gpfcon);  
  167.         
  168.     printk("led_drv_remove, remove led ");  
  169.     return 0;  
  170. }  
  171.     
  172. int led_drv_init(void)  
  173. {  
  174.     platform_driver_register(&led_drv);  
  175.         
  176.     return 0;  
  177. }  
  178.     
  179.     
  180. void led_drv_exit()  
  181. {  
  182.     platform_driver_unregister(&led_drv);  
  183. }  
  184.     
  185.     
  186. module_init(led_drv_init);  
  187. module_exit(led_drv_exit);  
  188.     
  189. MODULE_LICENSE("GPL");  
原文地址:https://www.cnblogs.com/beijiqie1104/p/11434707.html