解决一个驱动代码解耦合问题

嵌入式Linux

共 3601字,需浏览 8分钟

 ·

2021-01-27 05:37

之前解决的项目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_LK
 PRINTFx("[Kernel/LCM] lcm_init() enter\n");
#endif
}



推荐阅读:
专辑|Linux文章汇总
专辑|程序人生
专辑|C语言
我的知识小密圈



浏览 39
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报