GPIO && Pinctrl 子系统

GPIO && Pinctrl 子系统

前面是通过查找寄存器的方式来开发驱动,实际开发中如果是这样做的话,那属实是太低效了,现在的单片机都已经不执着于写裸机寄存器了。

那应该怎么做才能高效呢?

Linux 下针对引脚有2个重要的子系统:GPIOPinctrl

Pintctrl 子系统重要概念

无论是哪种芯片,都有大差不差的如下图结构
在这里插入图片描述
要想让 pinA、 B 用于GPIO,需要设置 IOMUX 让它们连接到 GPIO 模块;

要想让 pinA、 B 用于I2C,需要设置 IOMUX 让它们连接到 I2C 模块;

所以 GPIO、 I2C 应该是并列的关系,它们能够使用之前,需要设置 IOMUX。时候并不仅仅是设置 IOMUX,还要配置引脚,比如 上拉下拉开漏 等等。

现在的芯片动辄几百个引脚,在使用到 GPIO 功能时,让你一个引脚一个引脚去找对应的寄存器,这要疯掉。术业有专攻,这些累活就让芯片厂家做吧──他们是 BSP 工程师。

BSP 工程师是更懂他自家的芯片,但是同时也要求驱动工程师能看懂他们的代码,否则得反思自己的水平了。

所以为了更方便驱动工程师的开发,要把引脚的复用、配置抽出来,做成 Pinctrl 子系统,给 GPIO、I2C 等模块使用。

BSP 工程师在 GPIO 子系统、Pinctrl 子系统中把自家芯片的支持加进去后,我们就可以非常方便地使用这些引脚了;点灯简直太简单了。

大多数的芯片,没有单独的 IOMUX 模块,引脚的复用、配置等等,就是在GPIO 模块内部实现的。在硬件上 GPIO 和 Pinctrl 是如此密切相关,在软件上它们的关系也非常密切。

重要概念

涉及2个对象,需要有认知;pin controllerclient device

前者提供服务:可以用它来服用引脚、配置引脚。
后者使用服务:声明自己要使用哪些引脚的哪些功能,怎么配置它们。

pin controller

或许在芯片手册会找到 pin controller ,他是一个软件上的概念,可以认为它对应的 IOMUX 是用来复用引脚的,还可以配置引脚 (比如上下拉电阻等)。

注意

pin controllerGPIO Controller 不是一回事,前者控制的引脚可用于 GPIO 功能、 I2C 功能;
后者只是把引脚配置为输入、输出等简单的功能。
即先用 pin controller 把引脚配置为 GPIO,再用 GPIO Controler 把引脚配置为输入或输出。

client device

客户设备,谁的客户;Pinctrl 系统的客户,那就是使用 Pinctrl 系统的设备,使用引脚的设备。它在设备树里会被定义为一个节点,在节点里声明要用哪些引脚。
在这里插入图片描述
左边是 pin controller 节点,右边是 client device 节点

pin state

对于一个“ client device”来说,比如对于一个 UART 设备,它有多个“状态”: default、 sleep 等。
对应的引脚也有这些状态。
比如默认状态下, UART 设备是工作的,那么所用的引脚就要复用为 UART 功能。
在休眠状态下,为了省电,可以把这些引脚复用为 GPIO 功能;或者直接把它们配置输出高电平。
上图中, pinctrl-names 里定义了 2 种状态: default、 sleep。

  • 第 0 种状态用到的引脚在 pinctrl-0 中定义,它是 state_0_node_a,位于 pincontroller 节点中。
  • 第 1 种状态用到的引脚在 pinctrl-1 中定义,它是 state_1_node_a,位于 pincontroller 节点中。
  • 当这个设备处于 default 状态时, pinctrl 子系统会自动根据上述信息把所用引脚复用为 uart0 功能。
  • 当这个设备处于 sleep 状态时, pinctrl 子系统会自动根据上述信息把所用引脚配置为高电平。

groups 和 function

一个设备会用到一个或多个引脚,这些引脚就可以归为一组(group);这些引脚可以复用为某个功能: function。

Generic pin multiplexing node 和 Generic pin configuration node

在上图左边的 pin controller 节点中,有子节点或孙节点,它们是给 client device 使用的。
可以用来描述复用信息:哪组(group)引脚复用为哪个功能(function);
可以用来描述配置信息:哪组(group)引脚配置为哪个设置功能(setting),比如上拉、下拉等。

注意

pin controller 节点的格式, 没有统一的标准!!!!每家芯片都不一样。
甚至上面的 group、 function 关键字也不一定有,但是概念是有的

示例

在这里插入图片描述

代码中怎么引用 pinctrl

这是透明的,我们的驱动基本不用管。当设备切换状态时,对应的 pinctrl 就会被调用;
比如在 platform_deviceplatform_driver 的枚举过程中,流程如下
在这里插入图片描述
当系统休眠时,也会去设置该设备 sleep 状态对应的引脚,不需要我们自己去调用代码。非要自己调用,也有函数

devm_pinctrl_get_select_default(struct device *dev);      // 使用"default"状态的引脚
pinctrl_get_select(struct device *dev, const char *name); // 根据 name 选择某种状态的引脚
pinctrl_put(struct pinctrl *p);                           // 不再使用, 退出时调用
  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值