您的位置:首页 > 其它

内核中的 platform总线

2015-05-29 19:36 169 查看
    一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC 系统中集成的独立的外设控制器、挂接在SoC 内存空间的外设等确不依附于此类总线。基于这一背景,Linux 发明了一种虚拟的总线,称为platform 总线
    SOC系统中集成的独立外设单元(I2C,LCD,SPI,RTC等)都被当作平台设备来处理,而它们本身是字符型设备。

    从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver 。Linux
中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示;驱动用platform_driver 进行注册。

      

一.platform_device

    在2.6内核中platform设备用结构体platform_device来描述,

    该结构体定义在kernel\include\linux\platform_device.h中,

    

    struct platform_device {

     const char * name; //名

     int id;   

     struct device dev; //内嵌设备

     u32 num_resources; //资源个数

     struct resource * resource; //资源结构体

     struct platform_device_id *id_entry;

     struct pdev_archdata archdata;

    };

在使用platform设备之前需要注册和使用完之后需要注销:platform_driver 的注册与注销:
    platform_driver_register()
    platform_driver_unregister()

    device文件模块代码:

      

1 #include <linux/init.h>
2 #include <linux/thread_info.h>
3 #include <linux/module.h>
4 #include <linux/sched.h>
5 #include <linux/errno.h>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <linux/input.h>
10 #include <linux/init.h>
11 #include <linux/serio.h>
12 #include <linux/delay.h>
13 #include <linux/clk.h>
14 #include <linux/miscdevice.h>
15 #include <linux/io.h>
16 #include <linux/ioport.h>
17 #include <linux/vmalloc.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/export.h>
20 #include <linux/gfp.h>
21 #include <linux/cdev.h>
22
23 #include <asm/dma-mapping.h>
24 #include <asm/uaccess.h>
25
26 #include <linux/gpio.h>
27 #include <mach/gpio.h>
28 #include <plat/gpio-cfg.h>
29 #include <linux/completion.h>
30 #include <linux/miscdevice.h>
31 #include <linux/platform_device.h>
32
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("bunfly");
35
36 void test_release(struct device *dev)
37 {
38 }
39
40 struct platform_device  test_device = {
41     .name = "test_platform",
42     .dev = {
43         .release =  test_release,
44     },
45 };
46
47 int test_init(void)
48 {
49     printk("device had regiser!\n");
50     return platform_device_register(&test_device);
51     //注册platform设备
52 }
53
54 void test_exit(void)
55 {
56     platform_device_unregister(&test_device);
57 }
58
59 module_init(test_init);
60 module_exit(test_exit);
61
~
~
~
~
~


二.paltform_driver

     platform_driver 结构体 在 include/linux/platform_device.h目录下

    

    struct platform_driver {

     int (*probe)(struct platform_device *); //探测函数

     int (*remove)(struct platform_device *); //移除函数

     void (*shutdown)(struct platform_device *);

     int (*suspend)(struct platform_device *, pm_message_t state); //挂起

     int (*resume)(struct platform_device *); //恢复

     struct device_driver driver; //内嵌设备驱动

     struct platform_device_id *id_table; //驱动支持项

      };

    其中,比较重要的就是probe和remove函数。

    driver代码如下:

      

1 #include <linux/init.h>
2 #include <linux/thread_info.h>
3 #include <linux/module.h>
4 #include <linux/sched.h>
5 #include <linux/errno.h>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <linux/input.h>
10 #include <linux/init.h>
11 #include <linux/serio.h>
12 #include <linux/delay.h>
13 #include <linux/clk.h>
14 #include <linux/miscdevice.h>
15 #include <linux/io.h>
16 #include <linux/ioport.h>
17 #include <linux/vmalloc.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/export.h>
20 #include <linux/gfp.h>
21 #include <linux/cdev.h>
22
23 #include <asm/dma-mapping.h>
24 #include <asm/uaccess.h>
25
26 #include <linux/gpio.h>
27 #include <mach/gpio.h>
28 #include <plat/gpio-cfg.h>
29 #include <linux/completion.h>
30 #include <linux/miscdevice.h>
31 #include <linux/platform_device.h>
32
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("bunfly");
35
36
37
38 int myopen(struct inode *no, struct file *fp)
39 {
40     return 0;
41 }
42
43 int myrelease(struct inode *no, struct file *fp)
44 {
45     return 0;
46 }
47
48
49 int mywrite(struct file *fp, char *buf, int size, int *off)
50 {
51
52     printk("KERNEL: write....\n");
53
54     return 0;
55 }
56
57 int myread(struct file *fp, char *buf, int size, int *off)
58 {
59
60     return 0;
61 }
62
63 struct file_operations  myfops = {
64     .open = myopen,
65     .release = myrelease,
66     .write = mywrite,
67     .read = myread,
68 };
69
70 struct miscdevice  mymisc = {
71     .minor = 22,
72     .name = "mymisc",
73     .fops = &myfops,
74 };
75
76 int test_probe(struct platform_device *pdev)
77 {
78     int ret = 0;
79     misc_register(&mymisc);
80     printk("match sucessed!\n");
81     return 0;
82 }
83 //注册设备驱动
84 int test_remove(struct platform_device *pdev)
85 {
86     misc_deregister(&mymisc);
87     return 0;
88 }
89
90 struct platform_driver  test_driver = {
91     .driver = {
92             .owner = THIS_MODULE,
93             .name = "test_platform",
94     },
95     .probe = test_probe,
96     .remove = test_remove,
97 };
98 int test_init(void)
99 {
100     return platform_driver_register(&test_driver);
101     //驱动注册
102 }
103
104 void test_exit(void)
105 {
106     platform_driver_unregister(&test_driver);
107     //驱动注销
108 }
109
110 module_init(test_init);
111 module_exit(test_exit);
112


三.platform 匹配

    platform通过device和driver的name名字来匹配,所以,device和driver的name一定要一样才可以匹配成功,当匹配成功之后,就会到驱动的probe函数里面区探测设备;

     起到的左右大概是:

      


    在这里,我们先插入driver模块,再插入device模块,可以在

            /sys/bus/platform/devices/目录下查看到设备的插入情况:

    


        


    接下来:插入driver模块:

    


    发现,插入驱动模块的时候,自动调用了probe函数,打印出了里面的一句话;

 总结:

      platform总线是虚拟总线,通过name,起到platform_device和platform_driver的匹配工作

   ,当匹配成功之后就会调用driver里面的probe函数添加设备!          
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: