设置GPIO为输入下拉模式未生效

Viewed 76

重现步骤

庐山派按键GPIO编写按钮亮灯程序;
运行代码后立即亮灯,操作按钮无反应,此时日志输出按钮为高电平;

期待结果和实际结果

GPIO读取正确

软硬件版本信息

庐山派k230
rtos

错误日志

尝试解决过程

尝试其他GPIO(15、16),当IO用作输出没有问题, 用作输入时默认都是高电平;

补充材料

庐山派按键 GPIO
庐山派LED GPIO 低电平亮灯,高电平熄灭

image.png

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include "sys/ioctl.h"

/* 这两个GPIO分别控制开发板上的,按键和LED灯 */
#define LED_PIN_NUM (62)
#define KEY_PIN_NUM (53)

#define KD_GPIO_HIGH     1
#define KD_GPIO_LOW      0

/* ioctl */
#define GPIO_DM_OUTPUT           _IOW('G', 0, int)
#define GPIO_DM_INPUT            _IOW('G', 1, int)
#define GPIO_DM_INPUT_PULL_UP    _IOW('G', 2, int)
#define GPIO_DM_INPUT_PULL_DOWN  _IOW('G', 3, int)
#define GPIO_WRITE_LOW           _IOW('G', 4, int)
#define GPIO_WRITE_HIGH          _IOW('G', 5, int)

#define GPIO_READ_VALUE         _IOW('G', 12, int)

typedef struct kd_pin_mode
{
    unsigned short pin;
    unsigned short val;
} pin_mode_t;

static bool exit_flag;

static void sig_handler(int sig_no) {

    exit_flag = true;

    printf("exit sig = %d\n", sig_no);
}

int main(void)
{

    int fd, ret = 0;;
    pin_mode_t led, key;

    signal(SIGINT, sig_handler);
    signal(SIGPIPE, SIG_IGN);

    fd = open("/dev/gpio", O_RDWR);
    if (fd < 0) {
        perror("open /dev/gpio err\n");
        return -1;
    }

    key.pin = KEY_PIN_NUM;
    ret = ioctl(fd, GPIO_DM_INPUT_PULL_DOWN, &key);
    if (ret) {
        perror("set key pin mode fail\n");
        ret = -1;
        goto out;
    }

    led.pin = LED_PIN_NUM;
    ret = ioctl(fd, GPIO_DM_OUTPUT, &led);
    if (ret) {
        perror("set led pin mode fail\n");
        ret = -1;
        goto out;
    }

    do {
        ret = ioctl(fd, GPIO_READ_VALUE, &key);
  
        printf("key read value: %hd\n", key.val); 

        if (ret || exit_flag) {
            break;
        }

        if (key.val == KD_GPIO_HIGH) {
            ret = ioctl(fd, GPIO_WRITE_LOW, &led);
            // printf("Key press -> light on\n");
        } else {
            ret = ioctl(fd, GPIO_WRITE_HIGH, &led);
        }

        usleep(100000);
    } while (1);

out:
    close(fd);

    return ret;
}

2 Answers

GPIO驱动,并未对 GPIO_DM_INPUT_PULL_DOWN & GPIO_DM_INPUT_PULL_UP 进行支持,所以还是在IOMUX中进行设置。如果输入模式未设置内部上拉下拉,外部也无上拉下拉,就是浮空状态。
image.png

写在applications内的项目代码能否直接使用src/rtsmart/rtsmart/kernel/bsp/maix3/drivers/interdrv/gpio/drv_gpio, applications的CMakeLists要做哪些调整?

drv_gpio.c 是驱动,applications里面的代码不应该直接调用里面的接口,实在要用,可以自己封装ioctl出去使用。
我们后续会考虑是否要在gpio驱动里面对 GPIO_DM_INPUT_PULL_DOWN 和 GPIO_DM_INPUT_PULL_UP 做支持,因为上下拉的动作配置的实际上是iomux模块。暂时你可以先在dts里面去配置它。

已经将GPIO_DM_INPUT_PULL_DOWN/UP的支持加上去了,同步最新代码即可

该sample在01的板子上实验是可以成功的,可是在庐山派不起作用的话,那么我们可以对比其中的按键原理图:
庐山派的如下:
image.png

01的如下:
image.png

所以问题就在于,01的按键外部有一个上拉,默认为高电平,按下按键则变为低电平。而庐山派外部没有上拉或者下拉,所以默认为浮空状态,当按下按键才为高电平,鉴于此,我们可以在使用庐山派这个按键的时候,可以配置GPIO53默认内部下拉即可。
正如文档所说,因为该sample仅是gpio功能,至于iomux选择(内部上拉下拉也在此)暂需要自行根据自身需要去src/uboot/uboot/arch/riscv/dts/xxxx.dts 上配置。

修改dts的pd后重新检测按键53、GPIO15、GPIO16默认为低电平,在不修改pd情况下通过代码设置 GPIO_DM_INPUT_PULL_DOWN 为何不起作用吗?