之前解决的项目LCD设备兼容问题,在 a.c 文件里面定义了一个变量,然后在 b.c 里面使用 extern
声明引用这个变量,通过这种方法可以在b.c中使用在a.c 里面初始化的变量。
但是这中情况就会引起一个问题,就是驱动代码之间耦合了,这也违背了驱动代码 高内聚、低耦合的思想。
所以,这篇文章就是讨论解决这个问题的。
之前写的文章
LCD驱动兼容
1、先说说问题产生的本质
在 a.c 驱动文件中,我会根据 dts 文件的配置挂载一个platform 驱动,这个驱动获取dts文件的 gpio口信息,申请gpio口,并赋值给 g_lcm_power
变量。
代码如下
dts文件
panel: panel@0 {compatible = "hx8279d";gpio_lcd_pwr_en = <&pio 47 0>;status = "okay";};
驱动文件
static const struct of_device_id lcm_platform_of_match[] = {{.compatible = "hx8279d",.data = 0,}, {/* sentinel */}
};MODULE_DEVICE_TABLE(of, platform_of_match);static int lcm_platform_probe(struct platform_device *pdev)
{const struct of_device_id *id;enum of_gpio_flags flags;int ret;struct device_node *node = pdev->dev.of_node;PRINTFx("[Kernel/LCM] lcm_platform_probe() enter\n");id = of_match_node(lcm_platform_of_match, pdev->dev.of_node);if (!id)return -ENODEV;g_lcm_power = of_get_named_gpio_flags(node, "gpio_lcd_pwr_en", 0, &flags);if (!gpio_is_valid(g_lcm_power)) {dev_err(&pdev->dev, "invalid en gpio%d\n", g_lcm_power);}ret = devm_gpio_request(&pdev->dev, g_lcm_power, "gpio_lcd_pwr_en");if (ret) {dev_err(&pdev->dev,"failed to request GPIO%d for relay-en-gpio\n",g_lcm_power);return -EINVAL;}return 0;
}static struct platform_driver lcm_driver = {.probe = lcm_platform_probe,.driver = {.name = "hx8279d",.owner = THIS_MODULE,.of_match_table = lcm_platform_of_match,},
};static int __init lcm_init(void)
{PRINTFx("[Kernel/LCM] lcm_init() probe enter\n");/*if (platform_driver_register(&lcm_driver)) {PRINTFx("LCM: failed to register this driver!\n");return -ENODEV;}*/return 0;
}static void __exit lcm_exit(void)
{platform_driver_unregister(&lcm_driver);
}late_initcall(lcm_init);
module_exit(lcm_exit);
MODULE_AUTHOR("mediatek");
MODULE_DESCRIPTION("LCM display subsystem driver");
MODULE_LICENSE("GPL");
a.c 文件 和 b.c 文件的只能执行一个lcm 驱动,具体执行哪个驱动是在lk判断硬件接了哪一个硬件模组,所以我们在实现驱动代码的时候,a.c驱动文件和b.c驱动文件都需要具备注册上述说的那个 power gpio代码,用来控制模组的电源。
我的解决办法是
在 a.c 驱动文件中,我会根据 dts 文件的配置挂载一个platform 驱动,这个驱动获取dts文件的 gpio口信息,申请gpio口,并赋值给 g_lcm_power
变量。
因为a.c的platform驱动我是默认每次开机都会加载。
在b.c驱动文件中,我使用 extern int g_lcm_power;
来声明这个变量,这样做之后,如果在lk识别到b.c的驱动,这个变量也可以正常使用。
2、什么是高内聚、低耦合?
什么是高内聚、低耦合?
这是之前写的一篇文章,我觉得解释的比较不错了。
3、如何解决这样的问题?
如何解决,也就是说我们要对驱动代码进行解耦合。
因为我们代码中就只对一个对GPIO口的控制,如果脱离DTS的注册,直接在驱动文件里面对这个GPIO口进行操作的话,理论上就可以解决耦合的问题了。
这部分可以去查一下下面这个函数
gpio_direction_output
测试看看如果在不申请的情况下是否可以使用。
第二种情况就还是使用dts来匹配
dts改成如下
panel: panel@0 {/*compatible = "hx8279d";*/gpio_lcd_pwr_en = <&pio 47 0>;status = "okay";};
在 a.c 和 b.c 驱动中,同时使用如下代码申请gpio口,linux的dts是一个很不错组织结构,也有很多函数来获取dts中的文件。
想研究dts的同学,可以看看这个目录下的内容,对大家调试非常有帮助。
static void lcm_init_power(void)
{struct device_node *panel_nd;int ret;enum of_gpio_flags flags;PRINTFx("[Kernel/LCM] lcm_init_power() enter\n");/*查找整个dts文件,找到panel,前面是NULL就是让这个函数查找整个dts*/panel_nd = of_find_node_by_name(NULL, "panel");if(!panel_nd){PRINTFx("Can't file panel_nd node\n");return;}/*获取gpio_lcd_pwr_en属性信息*/g_lcm_power = of_get_named_gpio_flags(panel_nd, "gpio_lcd_pwr_en", 0, &flags);PRINTFx("1212121g_lcm_power=%d\n", g_lcm_power);if (!gpio_is_valid(g_lcm_power)) {PRINTFx("invalid en gpio%d\n", g_lcm_power);return;}ret = gpio_request( g_lcm_power, "gpio_lcd_pwr_en");if (ret) {PRINTFx("failed to request GPIO%d for relay-en-gpio\n",g_lcm_power);return;}PRINTFx("[Kernel/LCM] lcm_init_power() end\n");return;
#ifndef BUILD_LKPRINTFx("[Kernel/LCM] lcm_init() enter\n");
#endif
}
推荐阅读:
专辑|Linux文章汇总
专辑|程序人生
专辑|C语言
我的知识小密圈