LED驱动总线设备驱动模型

匹配规则

 最先比较:platform_device. driver_override和platform_driver.driver.name

可以设置platform_device的driver_override,强制选择某个platform_driver。

 然后比较:platform_device. name和platform_driver.id_table[i].name

Platform_driver.id_table是“platform_device_id”指针,表示该drv支持若干个device,它里面列出了各个device的{.name, .driver_data},其中的“name”表示该drv支持的设备的名字,driver_data是些提供给该device的私有数据。

最后比较:platform_device.name和platform_driver.driver.name

platform_driver.id_table可能为空,

这时可以根据platform_driver.driver.name来寻找同名的platform_device。

怎么写程序

分配/设置/注册platform_device结构体 board文件

在里面定义所用资源,指定设备名字。

分配/设置/注册platform_driver结构体

在其中的probe函数里,分配/设置/注册file_operations结构体,

并从platform_device中确实所用硬件资源。

指定platform_driver的名字。

leddrv为驱动上层文件。其实中有几个函数可以导出来,供其他文件使用。只需要包含相应的h文件就好了。

复制代码
  1 #include <linux/module.h>
  2 
  3 #include <linux/fs.h>
  4 #include <linux/errno.h>
  5 #include <linux/miscdevice.h>
  6 #include <linux/kernel.h>
  7 #include <linux/major.h>
  8 #include <linux/mutex.h>
  9 #include <linux/proc_fs.h>
 10 #include <linux/seq_file.h>
 11 #include <linux/stat.h>
 12 #include <linux/init.h>
 13 #include <linux/device.h>
 14 #include <linux/tty.h>
 15 #include <linux/kmod.h>
 16 #include <linux/gfp.h>
 17 
 18 #include "led_opr.h"
 19 
 20 
 21 /* 1. 确定主设备号                                                                 */
 22 static int major = 0;
 23 static struct class *led_class;
 24 struct led_operations *p_led_opr;
 25 
 26 
 27 #define MIN(a, b) (a < b ? a : b)
 28 
 29 /* 2. 定义自己的file_operations结构体                                              */
 30 static struct file_operations led_drv = {
 31     .owner     = THIS_MODULE,
 32     .open    = led_drv_open,
 33     .read    = led_drv_read,
 34     .write   = led_drv_write,
 35     .release = led_drv_close,
 36 };
 37 /* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
 38 static int led_drv_open (struct inode *node, struct file *file)
 39 {
 40     int minor = iminor(node);
 41     
 42     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
 43     /* 根据次设备号初始化LED */
 44     p_led_opr->init(minor);
 45     
 46     return 0;
 47 }
 48 static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
 49 {
 50     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
 51     return 0;
 52 }
 53 
 54 /* write(fd, &val, 1); */
 55 static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
 56 {
 57     int err;
 58     char status;
 59     struct inode *inode = file_inode(file);
 60     int minor = iminor(inode);
 61     
 62     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
 63     err = copy_from_user(&status, buf, 1);
 64 
 65     /* 根据次设备号和status控制LED */
 66     p_led_opr->ctl(minor, status);
 67     
 68     return 1;
 69 }
 70 static int led_drv_close (struct inode *node, struct file *file)
 71 {
 72     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
 73     return 0;
 74 }
 75 
 76 void led_class_create_device(int minor)
 77 {
 78     device_create(led_class, NULL, MKDEV(major, minor), NULL, "100ask_led%d", minor); /* /dev/100ask_led0,1,... */
 79 }
 80 
 81 void led_class_destroy_device(int minor)
 82 {
 83     device_destroy(led_class, MKDEV(major, minor));
 84 }
 85 
 86 void register_led_operations(struct led_operations *opr)
 87 {
 88     p_led_opr = opr;
 89 }
 90 
 91 EXPORT_SYMBOL(led_class_create_device);
 92 EXPORT_SYMBOL(led_class_destroy_device);
 93 EXPORT_SYMBOL(register_led_operations);
 94 
 95 
 96 /* 4. 把file_operations结构体告诉内核:注册驱动程序                                */
 97 /* 5. 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数 */
 98 static int __init led_init(void)
 99 {
100     int err;
101     
102     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
103     major = register_chrdev(0, "100ask_led", &led_drv);  /* /dev/led */
104 
105 
106     led_class = class_create(THIS_MODULE, "100ask_led_class");
107     err = PTR_ERR(led_class);
108     if (IS_ERR(led_class)) {
109         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
110         unregister_chrdev(major, "led");
111         return -1;
112     }
113     
114     return 0;
115 }
116 
117 /* 6. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数           */
118 static void __exit led_exit(void)
119 {
120     printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
121 
122     class_destroy(led_class);
123     unregister_chrdev(major, "100ask_led");
124 }
125 
126 
127 /* 7. 其他完善:提供设备信息,自动创建设备节点                                     */
128 
129 module_init(led_init);
130 module_exit(led_exit);
131 
132 MODULE_LICENSE("GPL");
复制代码
复制代码
 1 #ifndef _LEDDRV_H
 2 #define _LEDDRV_H
 3 
 4 #include "led_opr.h"
 5 
 6 void led_class_create_device(int minor);
 7 void led_class_destroy_device(int minor);
 8 void register_led_operations(struct led_operations *opr);
 9 
10 #endif /* _LEDDRV_H */
复制代码

接下来我们在board文件中指定资源,并对platform_device进行分配,设置,注册。

复制代码
 1 #include <linux/module.h>
 2 
 3 #include <linux/fs.h>
 4 #include <linux/errno.h>
 5 #include <linux/miscdevice.h>
 6 #include <linux/kernel.h>
 7 #include <linux/major.h>
 8 #include <linux/mutex.h>
 9 #include <linux/proc_fs.h>
10 #include <linux/seq_file.h>
11 #include <linux/stat.h>
12 #include <linux/init.h>
13 #include <linux/device.h>
14 #include <linux/tty.h>
15 #include <linux/kmod.h>
16 #include <linux/gfp.h>
17 #include <linux/platform_device.h>
18 
19 #include "led_resource.h"
20 
21 
22 static void led_dev_release(struct device *dev)
23 {
24 }
25 
26 static struct resource resources[] = {
27         {
28                 .start = GROUP_PIN(3,1),
29                 .flags = IORESOURCE_IRQ,
30                 .name = "100ask_led_pin",
31         },
32         {
33                 .start = GROUP_PIN(5,8),
34                 .flags = IORESOURCE_IRQ,
35                 .name = "100ask_led_pin",
36         },
37 };
38 
39 
40 static struct platform_device board_A_led_dev = {
41         .name = "100ask_led",
42         .num_resources = ARRAY_SIZE(resources),
43         .resource = resources,
44         .dev = {
45                 .release = led_dev_release,
46          },
47 };
48 
49 static int __init led_dev_init(void)
50 {
51     int err;
52     
53     err = platform_device_register(&board_A_led_dev);   
54     
55     return 0;
56 }
57 
58 static void __exit led_dev_exit(void)
59 {
60     platform_device_unregister(&board_A_led_dev);
61 }
62 
63 module_init(led_dev_init);
64 module_exit(led_dev_exit);
65 
66 MODULE_LICENSE("GPL");
复制代码

接下来我们在芯片相关的文件中提供led的操作方法给上层,并对platform_driver进行分配,设置,注册。

复制代码
  1 #include <linux/module.h>
  2 
  3 #include <linux/fs.h>
  4 #include <linux/errno.h>
  5 #include <linux/miscdevice.h>
  6 #include <linux/kernel.h>
  7 #include <linux/major.h>
  8 #include <linux/mutex.h>
  9 #include <linux/proc_fs.h>
 10 #include <linux/seq_file.h>
 11 #include <linux/stat.h>
 12 #include <linux/init.h>
 13 #include <linux/device.h>
 14 #include <linux/tty.h>
 15 #include <linux/kmod.h>
 16 #include <linux/gfp.h>
 17 #include <linux/platform_device.h>
 18 
 19 #include "led_opr.h"
 20 #include "leddrv.h"
 21 #include "led_resource.h"
 22 
 23 static int g_ledpins[100];
 24 static int g_ledcnt = 0;
 25 
 26 static int board_demo_led_init (int which) /* 初始化LED, which-哪个LED */       
 27 {   
 28     //printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);
 29     
 30     printk("init gpio: group %d, pin %d\n", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));
 31     switch(GROUP(g_ledpins[which]))
 32     {
 33         case 0:
 34         {
 35             printk("init pin of group 0 ...\n");
 36             break;
 37         }
 38         case 1:
 39         {
 40             printk("init pin of group 1 ...\n");
 41             break;
 42         }
 43         case 2:
 44         {
 45             printk("init pin of group 2 ...\n");
 46             break;
 47         }
 48         case 3:
 49         {
 50             printk("init pin of group 3 ...\n");
 51             break;
 52         }
 53     }
 54     
 55     return 0;
 56 }
 57 
 58 static int board_demo_led_ctl (int which, char status) /* 控制LED, which-哪个LED, status:1-亮,0-灭 */
 59 {
 60     //printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");
 61     printk("set led %s: group %d, pin %d\n", status ? "on" : "off", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));
 62 
 63     switch(GROUP(g_ledpins[which]))
 64     {
 65         case 0:
 66         {
 67             printk("set pin of group 0 ...\n");
 68             break;
 69         }
 70         case 1:
 71         {
 72             printk("set pin of group 1 ...\n");
 73             break;
 74         }
 75         case 2:
 76         {
 77             printk("set pin of group 2 ...\n");
 78             break;
 79         }
 80         case 3:
 81         {
 82             printk("set pin of group 3 ...\n");
 83             break;
 84         }
 85     }
 86 
 87     return 0;
 88 }
 89 
 90 static struct led_operations board_demo_led_opr = {
 91     .init = board_demo_led_init,
 92     .ctl  = board_demo_led_ctl,
 93 };
 94 
 95 struct led_operations *get_board_led_opr(void)
 96 {
 97     return &board_demo_led_opr;
 98 }
 99 
100 static int chip_demo_gpio_probe(struct platform_device *pdev)
101 {
102     struct resource *res;
103     int i = 0;
104 
105     while (1)
106     {
107         res = platform_get_resource(pdev, IORESOURCE_IRQ, i++);
108         if (!res)
109             break;
110         
111         g_ledpins[g_ledcnt] = res->start;
112         led_class_create_device(g_ledcnt);
113         g_ledcnt++;
114     }
115     return 0;
116     
117 }
118 
119 static int chip_demo_gpio_remove(struct platform_device *pdev)
120 {
121     struct resource *res;
122     int i = 0;
123 
124     while (1)
125     {
126         res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
127         if (!res)
128             break;
129         
130         led_class_destroy_device(i);
131         i++;
132         g_ledcnt--;
133     }
134     return 0;
135 }
136 
137 
138 static struct platform_driver chip_demo_gpio_driver = {
139     .probe      = chip_demo_gpio_probe,
140     .remove     = chip_demo_gpio_remove,
141     .driver     = {
142         .name   = "100ask_led",
143     },
144 };
145 
146 static int __init chip_demo_gpio_drv_init(void)
147 {
148     int err;
149     
150     err = platform_driver_register(&chip_demo_gpio_driver); 
151     register_led_operations(&board_demo_led_opr);
152     
153     return 0;
154 }
155 
156 static void __exit lchip_demo_gpio_drv_exit(void)
157 {
158     platform_driver_unregister(&chip_demo_gpio_driver);
159 }
160 
161 module_init(chip_demo_gpio_drv_init);
162 module_exit(lchip_demo_gpio_drv_exit);
163 
164 MODULE_LICENSE("GPL");
复制代码

opr文件不变

复制代码
 1 #ifndef _LED_OPR_H
 2 #define _LED_OPR_H
 3 
 4 struct led_operations {
 5     int (*init) (int which); /* 初始化LED, which-哪个LED */       
 6     int (*ctl) (int which, char status); /* 控制LED, which-哪个LED, status:1-亮,0-灭 */
 7 };
 8 
 9 struct led_operations *get_board_led_opr(void);
10 
11 
12 #endif
复制代码

资源文件不变

复制代码
 1 #ifndef _LED_RESOURCE_H
 2 #define _LED_RESOURCE_H
 3 
 4 /* GPIO3_0 */
 5 /* bit[31:16] = group */
 6 /* bit[15:0]  = which pin */
 7 #define GROUP(x) (x>>16)
 8 #define PIN(x)   (x&0xFFFF)
 9 #define GROUP_PIN(g,p) ((g<<16) | (p))
10 
11 
12 #endif
复制代码

文件包含关系图:

 

posted @   咸阳梁硕  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示