用 ADB 去控制 GPIO

c/c++

浏览数:424

2019-3-30

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

用 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下进行的,现在就去试试吧!