ETS板卡Linux驱动添加扩展io调试记录

本文详细介绍了如何在Linux系统中挂载扩展芯片,如TCA6424,通过修改设备树,处理I2C节点和GPIO冲突,以及检查驱动程序的probe函数来确保芯片正确挂载。此外,还阐述了如何操作GPIO,包括导出、设置方向、查看状态等步骤。在添加扩展I/O时,涉及到了硬件原理图、设备树的修改和IO复用配置,以确保GPIO功能的正确实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、挂载扩展芯片(以 TCA6424 为例)

1.1 修改设备树

首先查看芯片的电路原理图,以下图为例所示:
图1-1 芯片原理图
  可以看到扩展芯片为tca6424系列,通过I2C2 进行扩展,并且该芯片的 I2C 的十六进制地址为 0x22。则我们就可以在内核的源代码中搜索 tca6424,找到使用了该系列芯片的设备树文件,在该文件中搜索 tca6424,找到该设备树文件对于tca6424芯片的gpio的定义方法:

gpio9: gpio@22 {
    compatible = "ti,tca6424";
    reg = <0x22>;
    gpio-controller;
    #gpio-cells = <2>;
};

  然后在我们需要使用到的设备树文件中找到对应的 I2C节点,如上述芯片使用到的是 I2C2,则我们就可以在需要使用的设备树文件(OK8MP-C.dts)中找到该节点:
I2C节点
  将上述的关于对tca6424芯片的gpio的定义的相关代码粘贴到I2C2节点下面,作为该节点的子节点存在,并将地址改为板卡扩展芯片对应的地址,同时在 OK8MP-C.dts 引用的文件(imx8mp.dtsi)中可以看到,原有设备树对于 gpio 的使用已经使用到了 gpio5 了,故该节点的 gpio标号则应该大于5,从而避免冲突。
  故我们在设备树的I2C2节点下添加子节点如下:

gpio6: gpio@22 {
        compatible = "ti,tca6424";
        reg = <0x22>;
        gpio-controller;
        #gpio-cells = <2>;
};

  其他扩展芯片的挂载也类似,修改为该芯片的相应的地址之后,再把其定义在对应的 I2C节点下即可。
  对于i2c节点下的子节点存在与扩展芯片的地址有冲突的,则应把与扩展芯片地址冲突的子节点的 status改成 disabled,将该节点给关掉,不然会导致地址冲突的扩展芯片无法挂载上去。

&i2c3 {
    ...
    
    gpio8: gpio@22 {
            compatible = "ti,tca6424";
            reg = <0x22>;
            gpio-controller;
            #gpio-cells = <2>;
            status = "okay";
    };
    
    fusb302: typec-portc@22 {
            ...
            interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
            status = "disabled";
            ...
    };
    ...
};

修改完设备树之后,再在内核源代码中找到 tca6424芯片对应的驱动:
tca6424
  在该驱动程序中找到 probe函数,在该函数结束的地方用 printk打印一些日志信息,如果芯片成功挂载的话,则在板子启动的时候,系统日志就会将这些信息打印出来,如果没有挂载成功,这些信息则不会打印出来。

static int pca953x_probe(struct i2c_client *client,
                                   const struct i2c_device_id *i2c_id)
{
    ...
    if (chip == NULL){
                return -ENOMEM;
    }

    printk(KERN_INFO "tca6424 is start !!!!!!!!!!!!!!!!!!!\n");
    pdata = dev_get_platdata(&client->dev);
    ...
    
    printk(KERN_INFO "tca6424 mount success\n");
    return 0;

err_exit:
    if (chip->regulator)
            regulator_disable(chip->regulator);
    return ret;
}

  修改完代码之后,将源代码重新进行编译,将编译之后的程序烧录到板子上,板子成功启动之后,使用 dmesg命令打印日志信息,然后就可以在日志上看到我们 printk 的信息了。如下图所示,我挂载了四块拓展芯片,所以该信息就打印了四次。
日志
进入到/sys/class/gpio目录下使用 ls -l命令,即可查看到挂载的芯片的信息:
在这里插入图片描述
  使用命令 cat /sys/kernel/debug/gpio即可查看各个 gpio芯片的管脚的使用信息:
在这里插入图片描述

1.2 操作 GPIO

  查看挂载的扩展芯片的管脚的使用信息,对于要操作的 GPIO,选择一个该芯片未使用的一个管脚对应的管脚号 X,执行以下命令,如果能看到相应目录的值发生预期的改变的话,则说明该 GPIO是可操作的。

1. 导出
/sys/class/gpio# echo X> export

2. 设置方向
/sys/class/gpio/gpioX# echo out > direction

3. 查看方向
/sys/class/gpio/gpioX# cat direction

4. 设置输出
/sys/class/gpio/gpioX# echo 1 > value

5. 查看输出值
/sys/class/gpio/gpioX# cat value

6. 取消导出
/sys/class/gpio# echo X > unexport

X 导出gpio号 > 芯片基号 < 可扩展io号

在这里插入图片描述

二、添加扩展 I/O

2.1 在扩展芯片上添加扩展 IO

确认要添加的 gpioio,我的要添加的 io如下图所示:
扩展IO目录·
  在硬件原理图上找到这些 io对应的管脚,以 far_short为例,其在硬件原理图的位置如下图所示:
far_short
  我们就可以在我们要使用的设备树文件中的 leds节点中添加我们要添加的 io管脚作为 led的子节点:

far_short {
    lable = "far_short";
    gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
    default-state = "off";
};

  代码中 lable的内容即是在板卡中的文件系统中显示的该 io文件的名字,对于第三行的 gpios的赋值,&gpio6的取值要与该 io所在的芯片在系统挂载的 gpio相对应,即刚刚挂载的四个扩展芯片在设备树中对应的gpio。后面跟着的值(0) 则要与该 io在芯片上的位置相对应,如上述的 io在芯片上对应的标号为 1GPIO_ACTIVE_HIGH表示该 io为高电平有效,若取值为 GPIO_ACTIVE_LOW则表示该 io为低电平有效。
  把要添加的 io管脚全部都添加到 leds节点下的子节点之后,重新编译设备树,然后把编译后的 .dtb文件拷贝到板子上,替换掉板子原有的设备树文件,重新启动板子后,就可以在 /sys/class/leds下看到我们添加的 io的驱动目录了。

io驱动目录

  • 通过io 驱动实际空置开发板对应管脚
      在这些 io的目录下存在如下一些文件,通过修改brightness的值即可控制该 io管脚的闭合,如果是继电器类型的管脚,开闭该 io听到声音则表示该 io管脚可以控制,其他类型的 io管脚也类似。对于无法直观观察到 io的开闭的,则可以通过万用表测量通过该管脚的电平的高低来判断驱动是否可以有效控制该管脚。

2.2 GPIO 的 IO 复用

  在添加 io 的过程中可能会使用到在核心板上的管脚,这个就涉及到 io 的复用了,如上述的 kl30_on管脚,其在电路中对应的管脚如下:
kl30
  可以看到 kl30_on对应的开发板功能为 SAI3_TXC,在板卡的 GPIO使用表中找到该功能,内容如下所示:
kl30
  由此可得知该管脚复用为gpio的话,则对应为 gpio50io,同时可以在我们使用的设备树文件的 &iomuxc节点下看到类似于如下的一些代码:
在这里插入图片描述
  我们随便选取一串(以MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK为例)在内核源代码中进行搜索,找到定义它们的 .h文件:
在这里插入图片描述
  在该 .h文件中有一系列宏定义,这些宏定义了引脚的复用功能,在其中找到关于 gpio50io的定义,可以看到如下代码:

#define MX8MP_IOMUXC_SAI3_TXC__GPIO5_IO00                         0x1C8 0x428 0x000 0x5 0x0

  每一个宏定义后面都有 5个参数,再加上刚刚在&iomuxc节点下配置的参数一共是 6个参数,通过它们就可以完成一个 GPIO的配置了。在我们使用的设备树文件的 &iomuxc节点下添加一个子节点,并将上述关于 GPIO5_IO00定义的那以长串宏复制到该子节点下,同时添加配置参数,得到如下代码:

pinctrl_kl30_on: kl30ongrp {
    fsl,pins = <
        MX8MP_IOMUXC_SAI3_TXC__GPIO5_IO00                0x19
    >;
};

leds节点下添加关于 kl30_on的子节点,代码如下:

kl30_on {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_kl30_on>;
    lable = "kl30_on";
    gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;
    default-state = "off";
};

  同时还要在原设备树文件中找到其他关于 SAI3_TXC功能的宏的应用,将其对应的语句给注释掉,然后将该宏控制的节点的状态改为 disabled,这样就可以避免功能的冲突了。
注释

&sai3 {
    ...
    fsl,sai-mclk-direction-output;
    status = "disabled";
};

  将修改好的设备树重新编译之后,将对应的 .dtb文件拷贝到开发板上替换掉原来的设备树文件,重启开发板即可通过驱动来控制开发板上的 KL30 管脚了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值