OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4439|回复: 12

gpio_get_value总是返回0,配置的pinctrl节点没起作用

[复制链接]

37

主题

595

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1572
金钱
1572
注册时间
2017-7-17
在线时间
308 小时
发表于 2022-7-19 21:33:32 | 显示全部楼层 |阅读模式
IMX6ULL, alpha开发板,这几天在做内核控制器空置LED灯闪烁(GPIO1_IO03)的实现,想通过读取LED引脚电平,然后翻转来实现LED灯闪烁,使用的是pinctrl和gpio子系统来设置LED灯引脚。但是遇到了一个很基本,但是又很头疼的问题。使用 gpio_get_value()函数来读取LED引脚电平的时候,总是读取到0,不管引脚是高电平还是低电平。
经过查阅资料,发现需要开启MUX寄存器的SION位,使能输入回环,方法是在设备树里面,将config寄存器的值,第30位置1,这样pinctrl子系统驱动会自动检测这个位,检测到了就会将MUX寄存器的SION位设置为1.  我试了,还是没用。
然后我直接在imx6ul-pinfunc.h里面,将MUX寄存器的0x5改成0x15,直接设置SION位,还是没用
我就去NXP官网提问,为啥SION置1了,gpio_get_value还是返回0啊。。。
直到我用ioremap的方法,映射了MUX寄存器,然后将寄存器的值读出来,发现居然是默认的0x5,注意,这个值是上电默认就是0x5.  然后不管我在设备树里面将GPIO1_IO03复用为啥功能,MUX寄存器读出来都是0x5,雷打不动,感觉pinctrl的配置根本就没起作用一样。
然后我使用writel的方法,把MUX寄存器设置为0x15, gpio_get_value果然就能读到正确的电平了。。。。

顺便说一句,虽然读电平有问题,但是输出电平没有问题哦,可以正常开关LED灯。而且,当把引脚设置为输入功能时,gpio_get_value()也是可以正确返回电平值的。所以,问题总结如下:
当一个引脚被用作GPIO输出引脚时,gpio_get_value()不能正确返回引脚电平值,表层原因是设备树里面的pinctrl节点参数没有被写到MUX寄存器里面。

另外,我还用蜂鸣器引脚(GPIO5_IO01)也试过了,MUX读出来也是默认的0x0,而不是在pinctrl节点里面配置的值。

下面是我的设备树配置截图,以及驱动代码,有兴趣的可以试试。我不知道深层次原因是什么,肯定是原子修改过的内核代码问题,用vscode读源码太费劲,跳转功能不好用,所以我放弃了找原因,毕竟能力有限,如果有人找到原因了,记得告诉我。

1)pinctrl节点
pinctrl节点.PNG

2)led节点

led节点

led节点


3)驱动代码
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/ide.h>


#define REG_MUX_GPIO5_IO01         0x0229000C
static void __iomem *mux_gpio5_io01;

static int gpio;

static int __init led_init(void)
{
        const char *status;
        int ret, value;
        struct device_node *node = NULL;
       
        node = of_find_compatible_node(NULL, NULL, "alientek-alpha,leds");
        if(!node) {
                printk("error: of_find_compatible_node\n");
                return -ENODEV;
        }
       
        ret = of_property_read_string(node, "status", &status);
        if((ret != 0) || (strcmp(status, "okay") != 0)) {
                printk("error: of_property_read_string\n");
                return -ENODEV;
        }

        gpio = of_get_named_gpio(node, "led-gpios", 0);
        if(gpio < 0) {
                printk("error: of_get_named_gpio\n");
                return -ENODEV;
        }
       
        ret = gpio_request(gpio, "led-pin");
        if(ret) {
                printk("error: gpio_request\n");
                return -ENODEV;
        }

        ret = gpio_direction_output(gpio, 1);
        if(ret) {
                printk("error: gpio_direction_output\n");
                goto error;
        }

        value = gpio_get_value(gpio);
        printk("gpio value = %d\n", value);

        mux_gpio5_io01 = ioremap(REG_MUX_GPIO5_IO01, 4);
        if(mux_gpio5_io01) {
                value = readl(mux_gpio5_io01);
                printk("reg value = %08X\n", value);
        }
       
        return 0;

error:
        gpio_free(gpio);

        return -1;
}

static void __exit led_exit(void)
{
        int value;

        value = gpio_get_value(gpio);
        printk("gpio value = %d\n", value);

        if(mux_gpio5_io01) {
                value = readl(mux_gpio5_io01);
                printk("reg value = %08X\n", value);
        }

        gpio_free(gpio);
        if(mux_gpio5_io01) iounmap(mux_gpio5_io01);
}

module_init(led_init);
module_exit(led_exit);

MODULE_AUTHOR("David");
MODULE_LICENSE("GPL");




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

96

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
426
金钱
426
注册时间
2021-3-9
在线时间
56 小时
发表于 2022-7-20 12:01:18 | 显示全部楼层
普通的字符驱动是不是去使能pinctrl的管脚,你可以试试转化成平台驱动试一下
回复 支持 0 反对 1

使用道具 举报

37

主题

595

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1572
金钱
1572
注册时间
2017-7-17
在线时间
308 小时
 楼主| 发表于 2022-7-24 18:08:24 | 显示全部楼层
经过验证,如果只是使用 字符设备+gpio子系统调用的方法,是没法使用pinctrl子系统的,所以pinctrl节点里面的配置并不会生效。貌似pinctrl是专门配合平台驱动一起使用的,当我们使用platform driver的时候,平台驱动会帮我们去获取pinctrl节点里面的配置,并且将配置写入寄存器中。大家如果想使用pinctrl子系统,是要使用平台驱动的。我为什么会遇到这个问题,就是因为正点原子的教程讲解顺序安排的不合理,他把平台驱动放到很后面去了,导致我在做到内核定时器控制LED灯闪烁的实验时,根本就还没学到平台驱动,所以我就直接用字符设备驱动+gpio子系统,还一厢情愿地认为gpio子系统会自动去调用pinctrl子系统的接口来设置寄存器,在这里浪费了很多时间。
回复 支持 反对

使用道具 举报

37

主题

595

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1572
金钱
1572
注册时间
2017-7-17
在线时间
308 小时
 楼主| 发表于 2022-7-24 18:10:02 | 显示全部楼层
xiaoxiao315 发表于 2022-7-20 12:01
普通的字符驱动是不是去使能pinctrl的管脚,你可以试试转化成平台驱动试一下

使用平台驱动就可以了,看来gpio子系统并不会自动去调用pinctrl接口。
回复 支持 反对

使用道具 举报

1

主题

96

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
426
金钱
426
注册时间
2021-3-9
在线时间
56 小时
发表于 2022-8-2 10:01:15 | 显示全部楼层
candylife9 发表于 2022-7-24 18:10
使用平台驱动就可以了,看来gpio子系统并不会自动去调用pinctrl接口。

字符驱动需要使用api函数手动调用pinctrl,平台驱动会自己去操作
回复 支持 反对

使用道具 举报

13

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2018-1-25
在线时间
38 小时
发表于 2022-9-2 16:08:55 | 显示全部楼层
很详细,厉害了
我也遇到了同样的问题,gpio_get_value无法获取输出引脚的值,使用的是字符设备驱动。
如果只是使用 字符设备+gpio子系统调用的方法,是没法使用pinctrl子系统的,所以pinctrl节点里面的配置并不会生效

没太明白这句话的意思,我现在连接了6个输入和8个输出,都是通过设备树里的pinctrl节点配置的GPIO,基本功能是对的呀,为什么说pinctrl节点里的配置并不会生效呢?
回复 支持 反对

使用道具 举报

13

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2018-1-25
在线时间
38 小时
发表于 2022-9-2 17:11:56 | 显示全部楼层
从原理上理解的话,字符设备驱动确实不应该会调用设备树里的pinctrl配置。
我尝试把自己新增节点里的pinctrl删掉,功能还是正常的,说明pinctrl的配置根本不是我这个节点起的作用。
然后我把用到的6个输入和8个输出的pinctrl配置节点都屏蔽了,重新编译设备树,重启系统,驱动仍然可以检测到6个输入,也可以驱动8个LED。
这就诡异了,啥都没了,是怎么配置的GPIO呢?
回复 支持 反对

使用道具 举报

13

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2018-1-25
在线时间
38 小时
发表于 2022-9-2 17:39:04 | 显示全部楼层
我使用的6个输入引脚都在IOMUX域,这些引脚复位之后的功能就是GPIO,因此不需要pinctrl的配置也可以正常工作。
而另外8个输出,其中4个位于IOMUX域,复位之后也是GPIO功能,同理,没有pinctrl配置也可以正常工作;而另外4个位于IOMUX_SNVS域,上电复位之后的默认功能并不是GPIO功能,但是输出给LED也没什么问题。
根据目前的测试,我遇到的问题其实是:虽然使用了pinctrl,实际上pinctrl完全没有起任何配置作用,靠的是芯片复位之后的默认配置。
那么问题来了,在字符设备驱动中怎么配置pinctrl呢?(平台驱动另说)
回复 支持 反对

使用道具 举报

13

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2018-1-25
在线时间
38 小时
发表于 2022-9-2 18:29:24 | 显示全部楼层
按这个理解的话,正点原子IMX6LL视频教程第8.4讲、第8.5讲、第9讲中涉及的pinctrl是不是也没有真正起到作用呢?
可能也是使用了芯片默认的复用配置功能,刚好是GPIOx_IOy,pinctrl并没有起作用。
希望官方技术支持确认一下这个问题。
回复 支持 反对

使用道具 举报

37

主题

595

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1572
金钱
1572
注册时间
2017-7-17
在线时间
308 小时
 楼主| 发表于 2022-9-3 11:02:55 | 显示全部楼层
tovax 发表于 2022-9-2 17:39
我使用的6个输入引脚都在IOMUX域,这些引脚复位之后的功能就是GPIO,因此不需要pinctrl的配置也可以正常工 ...

我找资料得到的答案是,字符设备要使用pinctrl的话,需要自己手动调用一些pinctrl子系统提供的接口。但是我并没有找到哪些pinctrl的接口是提供给字符设备调用的,因为我发现pinctrl的接口都带有一个struct device的结构体参数,很明显是配合平台驱动一起使用的,而不是纯字符设备驱动可以调用的。如果非要调用就要自己构建struct device参数了
回复 支持 反对

使用道具 举报

37

主题

595

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1572
金钱
1572
注册时间
2017-7-17
在线时间
308 小时
 楼主| 发表于 2022-9-3 11:11:17 | 显示全部楼层
tovax 发表于 2022-9-2 16:08
很详细,厉害了
我也遇到了同样的问题,gpio_get_value无法获取输出引脚的值,使用的是字符设备 ...

就是说你在pinctrl里面的配置根本就不生效,因为pinctrl子系统并不会被gpio子系统自动调用,除非你在字符设备驱动里面手动去解析pinctrl节点的配置。你可以修改下pinctrl节点的配置,然后读取相应的寄存器看看,看看是不是寄存器是不是根本不受影响。至于你基本功能是对的,是因为上电之后的管脚默认配置本身就是OK的。
回复 支持 反对

使用道具 举报

13

主题

58

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2018-1-25
在线时间
38 小时
发表于 2022-9-4 10:03:45 来自手机 | 显示全部楼层
candylife9 发表于 2022-9-3 11:02
我找资料得到的答案是,字符设备要使用pinctrl的话,需要自己手动调用一些pinctrl子系统提供的接口。但是 ...

谢谢你的回复,你的分析跟我的测试结果完全一致。我再看看怎么在字符设备驱动框架下调用pinctrl api,目前也是看到了pinctrl_get需要struct device指针参数。
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2024-2-9
在线时间
5 小时
发表于 2024-2-23 22:35:10 | 显示全部楼层
2024年过来看,教程也没改过来
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 02:01

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表