用 ADB 去控制 GPIO

作者: SayidZhong | 来源:发表于2017-11-25 10:03 被阅读64次

    觉得为时已晚的时候,恰恰是最早的时候

    用 ADB 操作 GPIO

    转载请注明出处 https://sayid95.github.io/
    背景介绍:mt8167 安卓7.0

    我们经常会在底层驱动里面去操作gpio,进而去控制硬件。如果驱动层面去操作io出现问题的时候,我们不知道是不是硬件的问题,今天就来说下怎么用ADB去控制gpio。

    首先

    打开很难用的 Windows 的cmd.exe (推荐 一款替代品 Cmder ),adb shell连接上设备以后,输入下面的命令,

    cd /sys/devices/platform/soc/1000b000.pinctrl/
    

    进入到1000b000.pinctrl/ 的目录下,然后就可以去操作 io 口了,如下:

    echo mode 66 0 > mt_gpio   /*设置66号 io 的模式*/
    echo dir 66 1 > mt_gpio    /*设置66号 io 的输入,输出方向*/
    echo out 66 1 > mt_gpio    /*设置66号 io 为输出*/
    
    

    接着

    就可以用下面的命令去看我们上面用 ADB 设置的 gpio 状态了

    cat   /sys/devices/platform/soc/1000b000.pinctrl/mt_gpio
    

    来看下mtk 这部分操作的源码

    kernel-4.4/drivers/pinctrl/mediatek/pinctrl-mtk-common.c 这个文件里,下面代码就是adb 直接操作gpio的函数:

    static ssize_t mt_gpio_show_pin(struct device *dev, struct device_attribute *attr, char *buf)
    {
        int len = 0;
        int bufLen = PAGE_SIZE;
        struct mtk_pinctrl *pctl = dev_get_drvdata(dev);
        struct gpio_chip *chip = pctl->chip;
        unsigned        i;
        int         pull_val;
    
        len += snprintf(buf+len, bufLen-len,
            "PIN: [MODE] [DIR] [DOUT] [DIN] [PULL_EN] [PULL_SEL] [IES] [SMT] [DRIVE] ( [R1] [R0] )\n");
    
        for (i = 0; i < chip->ngpio; i++) {
            pull_val = mtk_pullsel_get(chip, i);
    
            len += snprintf(buf+len, bufLen-len, "%4d:% d% d% d% d% d% d% d% d% d",
                    i,
                    mtk_pinmux_get(chip, i),
                    mtk_gpio_get_direction(chip, i),
                    mtk_gpio_get_out(chip, i),
                    mtk_gpio_get_in(chip, i),
                    mtk_pullen_get(chip, i),
                    (pull_val >= 0) ? (pull_val&1) : -1,
                    mtk_ies_get(chip, i),
                    mtk_smt_get(chip, i),
                    mtk_driving_get(chip, i));
            if ((pull_val & 8) && (pull_val >= 0))
                len += snprintf(buf+len, bufLen-len, " %d %d", !!(pull_val&4), !!(pull_val&2));
            len += snprintf(buf+len, bufLen-len, "\n");
        }
        return len;
    }
    
    static ssize_t mt_gpio_store_pin(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
    {
        int pin, val;
        int val_set;
        struct mtk_pinctrl *pctl = dev_get_drvdata(dev);
        struct pinctrl_dev *pctldev = pctl->pctl_dev;
    
        if (!strncmp(buf, "mode", 4) && (sscanf(buf+4, "%d %d", &pin, &val) == 2)) {
            val_set = mtk_pmx_set_mode(pctldev, pin, val);
        } else if (!strncmp(buf, "dir", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
            val_set  = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, !val);
        } else if (!strncmp(buf, "out", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
            mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
            mtk_gpio_set(pctl->chip, pin, val);
        } else if (!strncmp(buf, "pullen", 6) && (sscanf(buf+6, "%d %d", &pin, &val) == 2)) {
            val_set = mtk_pconf_set_pull_select(pctl, pin, !!val,
                false, MTK_PUPD_SET_R1R0_00 + val);
        } else if (!strncmp(buf, "pullsel", 7) && (sscanf(buf+7, "%d %d", &pin, &val) == 2)) {
            val_set = mtk_pconf_set_pull_select(pctl, pin, true, !!val, MTK_PUPD_SET_R1R0_01);
        } else if (!strncmp(buf, "ies", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
            val_set = mtk_pconf_set_ies_smt(pctl, pin, val, PIN_CONFIG_INPUT_ENABLE);
        } else if (!strncmp(buf, "smt", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
            val_set = mtk_pconf_set_ies_smt(pctl, pin, val, PIN_CONFIG_INPUT_SCHMITT_ENABLE);
        }
    
        return count;
    }
    
    static DEVICE_ATTR(mt_gpio, 0664, mt_gpio_show_pin, mt_gpio_store_pin);
    
    static struct device_attribute *gpio_attr_list[] = {
        &dev_attr_mt_gpio,
    };
    
    static int mt_gpio_create_attr(struct device *dev)
    {
        int idx, err = 0;
        int num = (int)(ARRAY_SIZE(gpio_attr_list));
    
        if (!dev)
            return -EINVAL;
    
        for (idx = 0; idx < num; idx++) {
            err = device_create_file(dev, gpio_attr_list[idx]);
            if (err)
                break;
        }
    
        return err;
    }
    

    看到源码 static DEVICE_ATTR(mt_gpio, 0664, mt_gpio_show_pin, mt_gpio_store_pin);,我们就知道其实就是利用 device_create_file 函数可以在 /sys/ 下创建对应的属性文件,从而通过对该文件的读写实现特定的数据操作。

    可能不同的内核对应的节点不一样,这个例子是在 Linux 4.4下进行的,现在就去试试吧!

    相关文章

      网友评论

        本文标题:用 ADB 去控制 GPIO

        本文链接:https://www.haomeiwen.com/subject/aqnqbxtx.html