linux驱动中一个驱动代码如何与多个设备之间进行绑定

Linux驱动开发:设备区分与优化策略
本文探讨了在Linux驱动开发中遇到的问题及解决方案,重点阐述了如何通过平台_driver中的id_table和platform_device中的id来区分兼容设备,以避免冗余代码并遵循软件工程原则。

             今天调试linux驱动时遇到了一些问题,现记录下来以便以后查阅和与大家分享我的心得。

              我们在做linux驱动开发时往往会遇到这样的一个问题,即多个兼容的设备需要一个相同的驱动,此时我们可以复制两份驱动以供两个设备分别使用,但显然这样做是违背软件工程原则的,linux驱动的开发者已经为我们想到了这一点,linux内核的解决方式如下。

             1.第一种情况是两个兼容的设备挂接在同一个总线上,如mcp2515和mcp2510,这种情况下linux中是通过platform_driver中的id_table中的name来区分的。

             2.第二种情况是两个完全相同的设备,需要挂接在同一个总线上,如两个完全相同的e2prom,这种情况下是通过platform_device中的id来区分的。

Linux内核中,Platform驱动模型允许一个驱动程序支持多个设备。这通常是通过在驱动中匹配多个`compatible`字符串来实现的。每个设备设备树中定义,并具有一个`compatible`属性,驱动程序通过这个属性来识别并绑定设备。 以下是一个示例代码,展示如何编写一个支持多个设备的Platform驱动程序: ### Platform驱动支持多个设备的示例 ```c #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/io.h> #include <linux/slab.h> /* 定义设备的私有数据结构 */ struct my_device_data { void __iomem *regs; int irq; }; /* 支持的设备匹配表 */ static const struct of_device_id my_device_of_match[] = { { .compatible = "vendor,device1" }, { .compatible = "vendor,device2" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, my_device_of_match); /* Probe函数,当设备驱动匹配时调用 */ static int my_device_probe(struct platform_device *pdev) { struct my_device_data *data; struct resource *res; int ret; /* 分配私有数据结构 */ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; /* 获取设备寄存器资源 */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "No memory resource\n"); return -ENODEV; } /* 映射寄存器 */ data->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->regs)) { ret = PTR_ERR(data->regs); dev_err(&pdev->dev, "Failed to map registers: %d\n", ret); return ret; } /* 获取中断资源 */ data->irq = platform_get_irq(pdev, 0); if (data->irq < 0) { dev_err(&pdev->dev, "No IRQ resource\n"); return -ENODEV; } /* 初始化设备(示例代码) */ writel(0x1, data->regs); // 示例:向寄存器写入数据 dev_info(&pdev->dev, "Device probed successfully\n"); /* 保存私有数据 */ platform_set_drvdata(pdev, data); return 0; } /* Remove函数,当设备被移除时调用 */ static int my_device_remove(struct platform_device *pdev) { dev_info(&pdev->dev, "Device removed\n"); return 0; } /* Platform驱动结构体 */ static struct platform_driver my_device_driver = { .probe = my_device_probe, .remove = my_device_remove, .driver = { .name = "my_device_driver", .of_match_table = my_device_of_match, }, }; /* 注册Platform驱动 */ module_platform_driver(my_device_driver); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Platform driver for multiple devices"); MODULE_LICENSE("GPL"); ``` ### 设备树配置示例 ```dts /* 设备树中的设备定义 */ device1@10000000 { compatible = "vendor,device1"; reg = <0x10000000 0x1000>; interrupts = <0x5A 0x4>; }; device2@20000000 { compatible = "vendor,device2"; reg = <0x20000000 0x1000>; interrupts = <0x5B 0x4>; }; ``` ### 说明 - **`of_match_table`**:驱动程序通过`of_match_table`匹配设备树中的`compatible`字符串。可以列出多个`compatible`值,以支持多个设备。 - **`probe`函数**:当设备驱动匹配时,`probe`函数被调用。在这个函数中,通常会获取设备的资源(如寄存器、中断等),并进行初始化。 - **`remove`函数**:当设备被移除时,`remove`函数被调用。通常在这里释放资源或进行清理操作。 通过这种方式,一个Platform驱动可以支持多个不同的设备,只要它们在设备树中定义了对应的`compatible`字符串,并且驱动程序能够处理它们的硬件特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值