当前位置:首页 > 经验 >

gpio设置教程(gpio模式怎么设置)

来源:原点资讯(www.yd166.com)时间:2022-11-06 11:58:02作者:YD166手机阅读>>

gpio设置教程,gpio模式怎么设置(1)

作者 | 赵青窕

随着Linux内核代码的逐步完善,其gpio口的操作接口也在不断完善。内核中存在多种GPIO API接口,我们该如何使用这些API接口呢?我们又该如何在设备树中配置GPIO呢?

目前的内核中提供了三种版本的API接口供我们使用,分别是Pinctrl子系统对应的API接口和GPIO子系统对应的API接口(GPIO子系统提供了两种类型的API接口),在本文中我将会通过内核中GPIO架构的角度来说明这三类API接口;我们对GPIO的控制,除了合适的API接口外,还需要通过设备树对GPIO进行配置,虽然不同架构中设备树的配置方式不同,但本文中也会举例说明设备树如何配置,对应的代码中如何使用API接口;最后说明我们可以用到的调试手段。

1.内核GPIO架构

下图是内核中,GPIO架构中的核心部分框架图(暂时不考虑GPIO架构对应的sysfs和debugfs):

gpio设置教程,gpio模式怎么设置(2)

图 1:GPIO架构

从上图中的上半部分可以看出以下关键信息:

  • 内核提供了两种控制引脚的方式,一种是采用Pinctrl子系统,一种是采用GPIO子系统(该系统又有两种方式,后面小节中会进行说明),用户编写驱动时可以调用这两个子系统提供的API接口来达到控制GPIO口的目的;
  • GPIO子系统的功能是通过Pinctrl子系统来实现的。虽然从图中看出,Pinctrl子系统和GPIO子系统并存,但内核需要对所有的GPIO口进行管理,因此就需要一个统一的管理接口或者模块,Pinctrl就完成这种统一管理的目标,比如我们采用GPIO子系统的API接口gpio_request来申请GPIO口时,内核需要记录哪些GPIO口已经申请过了,若Pinctrl子系统和GPIO子系统各维护一套GPIO管理策略,那就可能导致Pinctrl子系统和GPIO子系统同时操作同一个GPIO口的情况,这种显然是不可行的,且从高通平台内核代码中可以看出gpio_request有如下的调用关系:

gpio_request--->gpiod_request----> gpiod_request_commit---->chip->request(系统启动时设置为gpopchip_generic_request) ---->pinctrl_gpio_request

该调用关系从GPIO子系统的API函数gpio_request最后调用了Pinctrl子系统的函数pinctrl_gpio_request,这种调用关系,也证实了Pinctrl和GPIO子系统的关系。对于其他接口,如gpio_direction_input,gpio_set_value等函数的调用,同gpio_request相似,其最后均是调用到对应的chip->direction_input,chip->set,进而调用pinctrl_gpio_direction_input,等函数,由于这类API函数比较多,在此就不展示其调用关系了;

  • 内核采用结构体struct pinctrl_dev来表示一个控制器,所有的pinctrl_dev会形成链表,链表头就是pinctrldev_list,在函数pinctrl_gpio_request内部,会调用函数pinctrl_get_device_gpio_range来根据GPIO号,遍历链表pinctrldev_list来查找该GPIO口对应的pinctrl_dev,当然这部分工作均是由系统来维护,我们只需知道整个框架,并如何使用GPIO的整个子系统即可。

注意:目前从我看到的代码中发现,有些厂家在实现GPIO子系统时,并非所有的功能均通过Pinctrl子系统,但gpio_request是会通过Pinctrl子系统,因为Pinctrl子系统中会标记哪些GPIO已经request了,这样后续模块采用request继续申请该资源时就会失败;不过大家放心,即使其部分功能不通过Pinctrl子系统,但其对驱动模块提供的API接口不受其影响。

2.用户驱动中控制GPIO

在编写驱动时,可以采用以下两种方式来设置:

  • Pinctrl方式,该方式最终是采用Pinctrl子系统来实现各项功能的;
  • 采用GPIO子系统接口的方式,该方式其实有两种,分别是legacy和gpio description的方式。但目前的内核中,legacy内部会调用gpio description的方式,后面内容中,我会以legacy的方式来说明使用方法。
Pinctrl控制引脚方式

下面,我以高通平台Pinctrl的方式来说明其代码和设备树的配置。

我们先来看一下设备树:

&tlmm{ client1_state1: client1_state1 { mux { pins = "gpio0"; function = "gpio"; }; config { pins = "gpio0"; bias-disable; drive-strength =<2> ; input-enable; }; }; client1_state2: client1_state2 { mux { pins = "gpio0"; function = "gpio"; }; config { pins = "gpio0"; bias-disable; drive-strength = <2>; output-high; }; }; }; &soc { client1 { pinctrl-names = "state1", "state2"; pinctrl-0 = <&client1_state1 >; pinctrl-1 = <&client1_state2>; }; }; 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.

上面是典型的设备树的配置,其中包含两个节点,分别是tlmm中的引脚配置和我们的设备client1。

tlmm中定义了两种GPIO状态,分别是作为输入功能的GPIO0和作为输出功能的GPIO0。不同平台的设备树中的配置方法不同,但均需要像上面设备树那样,配置两部分:

引脚功能配置,是作为普通的GPIO口,还是复用为其他的功能;

引脚驱动配置,包括引脚内部的上拉或者下拉,驱动能力等。

接下来,一起看下代码中如何进行操作,其操作需要按照下面的顺序:

  • 先调用devm_pinctrl_get或者pinctrl_get函数获取对应的struct pinctrl*;
  • 紧接着调用pinctrl_lookup_state(struct pinctrl *p, const char *name)来根据name获取对应的配置;
  • 最后我们采用函数pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)来进行状态的选择。选择某一状态,就是设置了对应的引脚,且引脚的request操作是在该函数内部完成的,该函数内部会调用pin_request来进行申请,且调用该函数后,引脚的状态就是设备树中设备的状态,如上面设备树中,client1_state1对应的引脚使用了其GPIO功能,且配置为输入(设备树中是通过input-enable进行配置的),client1_state2对应的引脚也使用了其GPIO的功能,且配置为输出高(设备树中是通过out-high进行配置的)。
采用GPIO子系统

&soc { client1 { qcom,gpio-client1 = <&tlmm 100 0>; //100就是GPIO号 }1.2.3.4.5.

这种方式在设备树的配置方式上比较简单,其代码操作如下:

  • 使用函数of_get_named_gpio(node, " qcom,gpio-client1", 0)获取GPIO号。
  • 接下来是最重要的一步,调用函数gpio_request来进行GPIO的request操作。该函数最后会通过Pinctrl接口间接调用pin_request来进行引脚的申请操作。之前有一次工作中粗心,忘记request操作,但发现该GPIO可能也会正常操作,但会有工作不稳定的情况发生;
  • 接下来可以调用函数gpio_direction_input或者gpio_direction_output来进行GPIO输入或者输出模式的配置,gpio_direction_output调用的同时,可以设置输出高或者输出低;
  • 如果配置位输入模式,则可以使用函数gpio_get_value来获取GPIO口的状态。

如果需要把引脚配置为中断功能,则我们需要使用函数irq = gpio_to_irq(gpio)来获得irq号,根据irq号来进行适当的中断配置。

通过上面两种方式,我们可以发现Pinctrl的方式,其设备树复杂,但API接口简单,只需要通过函数pinctrl_select_state选择设备树中某一配置即可。GPIO子系统的方式是设备树简单,但代码复杂,设备树中只配置了GPIO号,其余的如GPIO的方向及输出信号均需要通过代码来进行设置,这正是不同API接口及其设备树的优缺点。

3.GPIO调试

不同平台的调试方式可能会存在一些差异,比如MTK的不同平台间都会有差异,在此我就介绍一种常见的需要debugfs支持的方式。

我们在编译内核时,需要配置相应的debugfs宏来打开该功能,只有配置相应宏后,我们就可以进入机器的/sys/class/gpio下对GPIO口进行操作,下面是对应的操作顺序:

  • cd /sys/class/gpio/
  • echo 99 > export(此处99代表引脚号,确切地说echo时,应采用对应引脚gpio_request获得到的数值)
  • cd gpio99
  • echo in/out > direction //设置GPIO输入或输出
  • cat direction //获取GPIO输入输出状态
  • echo 0/1 > value //拉低或者拉高对应的GPIO口
  • cat value //查看GPIO口的高低状态
4.总结

希望大家通过本文,可以了解内核中GPIO的机制并掌握其操作方法,但需要说明的是在内核之前的阶段也会进行引脚的配置,比如我们使用串口来打印bootloader阶段的日志,这种情况下串口引脚一定是在内核之前的阶段进行配置的。

作者介绍

赵青窕,51CTO社区编辑,从事多年驱动开发。研究兴趣包含安全OS和网络安全领域,发表过网络相关专利。

来源:51CTO技术栈

作者:赵青窕

栏目热文

gpio使用技巧(gpio口使用方法汇总)

gpio使用技巧(gpio口使用方法汇总)

相信大多是硬件工程师的第一个程序都是使用IO口点灯,就像程序员的第一个程序都是Hello world一样。本篇文章将详细...

2022-11-06 11:49:31查看全文 >>

gplp的使用方法(gplp实际操作)

gplp的使用方法(gplp实际操作)

文/琼凉 GPLP曾经如日中天的直播行业迎来了下半场——王思聪30亿贱卖熊猫直播,虎牙和映客相继上市,以及斗鱼主播的相继...

2022-11-06 11:53:56查看全文 >>

gprinter使用方法(gprinter app使用教程)

gprinter使用方法(gprinter app使用教程)

随着互联网的迅速发展和普及,人们通过网络进行着大量的商业交易行为,从而使国内电子商务市场的发展迅速崛起。B2C市场逐渐饱...

2022-11-06 11:58:07查看全文 >>

gpr软件使用说明(gprs使用教程)

gpr软件使用说明(gprs使用教程)

探地雷达,又称地质雷达,管线探测雷达,环保行业称为暗管探测仪。产品简介:SL-GPR系列无线探地雷达具有无线传输功能的系...

2022-11-06 11:47:13查看全文 >>

gpio引脚操作方法(gpio原理图解)

gpio引脚操作方法(gpio原理图解)

ESP8266 引脚分配参考:您应该使用哪些 GPIO 引脚?本文是 ESP8266 GPIO 的指南:引脚图、它们的功...

2022-11-06 12:03:44查看全文 >>

gpr附着详细流程(gpr初始化怎么解决)

gpr附着详细流程(gpr初始化怎么解决)

OLX703A是一种由韩国临床阶段的制药公司OliX Pharmaceuticals开发的乙肝新机制化合物,目前OliX...

2022-11-06 11:53:37查看全文 >>

入门学gprs(gprs编程基础)

入门学gprs(gprs编程基础)

导读物联网,顾名思义,把“物”“连成网”。物联网通常分为三个层:感知层、传输层、应用层。和“云、管、端”的概念相同。感知...

2022-11-06 11:50:13查看全文 >>

gpr打开教程(gpr按键图解)

gpr打开教程(gpr按键图解)

使用Arduino控制NEO-6M GPS模块应用本应用说明如何将NEO-6M GPS模块与Arduino一起使用以获取...

2022-11-06 11:46:04查看全文 >>

gprinter(gprinter打印机打不出字)

gprinter(gprinter打印机打不出字)

如今,市场上的票据打印机可谓琳琅满目,品牌及种类各异。消费者因看得眼花缭乱,而无从下手。今天,小编为大家重点推荐佳博品牌...

2022-11-06 12:26:25查看全文 >>

gpio入门教程(gpio内部结构图解)

gpio入门教程(gpio内部结构图解)

点亮LED概述本教程目的是用程序将 LED 灯点亮,3秒钟后灯自动熄灭。在所有软件编程语言中,第一个程序都叫 hello...

2022-11-06 11:59:15查看全文 >>

文档排行