platform设备驱动框架

我们两清 提交于 2019-12-04 18:40:50

驱动框架

通过使用platform设备驱动框架,实现led驱动与设备操作的分离。

   

我们关注led_drv里面的 struct platform_driver led_drv里面的.probe函数,当有同名的device注册到内核,将运行这个driver的probe函数(同名的:led_dev里面的struct platform_device led_dev里面的.name与 struct platform_driver led_drv里面的.name一一对应)。

   

led_dev.c

1 /* 分配/设置/注册一个platform_device */
2 #include <linux/module.h>
3 #include <linux/version.h>
4
5 #include <linux/init.h>
6 #include <linux/fs.h>
7 #include <linux/interrupt.h>
8 #include <linux/irq.h>
9 #include <linux/sched.h>
10 #include <linux/pm.h>
11 #include <linux/sysctl.h>
12 #include <linux/proc_fs.h>
13 #include <linux/delay.h>
14 #include <linux/platform_device.h>
15 #include <linux/input.h>
16 #include <linux/irq.h>
17 #include <asm/uaccess.h>
18 #include <asm/io.h>
19
20
21 static struct resource led_resource[] = {
22         [0] = {
23                 .start         = 0x56000050,                
24                 .end         = 0x56000050 + 8 - 1,        
25                 .flags        = IORESOURCE_MEM,        //标记资源类型
26         },
27
28         [1] = {                                                
29                 .start         = 4,                                        
30                 .end         = 4,                                        
31                 .flags        = IORESOURCE_IRQ,                
32         }
33 };
34
35 static void led_release(struct device *dev)
36 {
37
38 }
39
40 static struct platform_device led_dev = {
41         .name                         = "myled",        //与drv保持一致
42         .id                         = -1,
43         .num_resources         = ARRAY_SIZE(led_resource),
44         .resource                = led_resource,
45         .dev = {
46                 .release = led_release,
47         }
48 };
49
50
51 static int led_dev_init(void)
52 {
53         platform_device_register(&led_dev);
54         return 0;
55 }
56
57
58 static void led_dev_exit(void)
59 {
60         platform_device_unregister(&led_dev);
61         return;
62 }
63
64 module_init(led_dev_init);
65 module_exit(led_dev_exit);
66 MODULE_LICENSE("GPL");

   

   

led_drv.c

1 /* 分配/设置/注册一个platform_driver */
2 #include <linux/module.h>
3 #include <linux/version.h>
4
5 #include <linux/init.h>
6 #include <linux/fs.h>
7 #include <linux/interrupt.h>
8 #include <linux/irq.h>
9 #include <linux/sched.h>
10 #include <linux/pm.h>
11 #include <linux/sysctl.h>
12 #include <linux/proc_fs.h>
13 #include <linux/delay.h>
14 #include <linux/platform_device.h>
15 #include <linux/input.h>
16 #include <linux/irq.h>
17 #include <asm/uaccess.h>
18 #include <asm/io.h>
19
20
21
22 static int major;
23
24 static struct class *led_class;
25 static struct class_device *led_class_dev;
26
27 static unsigned long *gpioctl;
28 static unsigned long *gpiodat;
29
30 static int led_pin;
31
32
33 static int led_open(struct inode *inode, struct file *file)
34 {
35         /* 初始化LED硬件 ―― GPF4、GPF5、GPF6设置为输出 */
36         *gpioctl &= ~(0x3<<(led_pin*2));
37         *gpioctl |= (0x1<<(led_pin*2));
38         return 0;
39 }
40
41 static ssize_t led_write(struct file *file, const char __user *buf,
42 size_t count, loff_t *ppos)
43 {
44         int val;
45
46         copy_from_user(&val, buf, count);
47         if (1 == val)
48         {
49                 *gpiodat &= ~(1<<led_pin);
50         }
51         else {
52                 *gpiodat |= 1<<led_pin;
53         }
54         return 0;
55 }
56
57 static struct file_operations led_fops = {
58         .owner         = THIS_MODULE,
59         .open         = led_open,
60         .write        = led_write,
61 };
62
63 static int led_probe(struct platform_device *pdev)
64 {
65         struct resource *res;
66
67         printk("led_probe, found led\n");
68         
69         /* 根据platform_device(led_dev)里面的资源,进行ioremap */
70         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
71         gpioctl = ioremap(res->start, res->end - res->start + 1);
72         gpiodat = gpioctl + 1;
73
74         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
75         led_pin = res->start;
76
77         /* 注册字符设备驱动 */
78         major = register_chrdev(0, "myled", &led_fops);
79
80         led_class = class_create(THIS_MODULE, "myled");
81
82         /* 创建有主设备号和次设备号的设备节点系统信息 */
83         led_class_dev = class_device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
84
85         return 0;
86 }
87
88 static int led_remove(struct platform_device *pdev)
89 {
90         printk("led_remove\n");
91         /* 根据platform_device(led_dev)里面的资源,进行iounmap */
92
93         /* 卸载字符设备驱动 */
94         unregister_chrdev(major, "myled");
95         class_device_unregister(led_class_dev);
96         class_destroy(led_class);
97
98         /* 释放虚拟地址映射 */
99         iounmap(gpioctl);
100
101         return 0;
102 }
103
104 struct platform_driver led_drv = {
105         .probe         = led_probe,
106         .remove = led_remove,
107         .driver = {
108                 .name         = "myled",//与dev保持一致
109         }
110 };
111
112 static int led_drv_init(void)
113 {
114         platform_driver_register(&led_drv);
115         return 0;
116 }
117
118 static void led_drv_exit(void)
119 {
120         platform_driver_unregister(&led_drv);
121         return;
122 }
123
124 module_init(led_drv_init);
125 module_exit(led_drv_exit);
126 MODULE_LICENSE("GPL");

   

app.c

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5
6 int main (int argc, char **argv)
7 {
8         int fd;
9         int val = 1;
10         char *filename;
11         
12         printf("test app!\n");
13         if (argc != 3)
14         {
15                 printf("Usage: led<on|off>\n");
16                 return -1;
17         }
18         
19         filename = argv[1];
20         
21         printf("filename: %s\n", filename);
22         
23         fd = open(filename, O_RDWR);
24         if(fd < 0)
25         {
26                 printf("open failed!---%d---\n", fd);
27                 return -1;
28         }
29         
30         //if (argv[2] == "on")
31         if (!strcmp("on", argv[2]))
32         {
33                 val = 1;
34                 write(fd, &val, 4);
35         }
36         //else if(argv[2] == "off")
37         else if(!strcmp("off", argv[2]))
38         {        
39                 val = 0;
40                 write(fd, &val, 4);
41         }
42         return 0;        
43 }

   

Makefile

1 KERN_DIR = /work/system/linux-2.6.22.6
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 += led_drv.o
11 obj-m += led_dev.o

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!