STM32MP157驱动开发——GPIO 和 和 Pinctrl 子系统的概念

文章目录

  • Pinctrl 子系统重要概念
    • 概述
    • 重要概念
      • pin controller:
      • client device:
    • 代码中怎么引用 pinctrl
  • GPIO 子系统重要概念
    • 概述
    • 在设备树中指定引脚
    • 在驱动代码中调用 GPIO 子系统
      • 头文件
      • 常用函数
      • 实例:

BSP工程师针对芯片的寄存器写Pinctrl子系统,驱动工程师使用Pinctrl 子系统

Pinctrl 子系统重要概念

概述

无论是哪种芯片,都有类似图的结构, IOMUX 认为是引脚功能选择器,有时候还需要配置引脚,比如上拉、下拉、开漏等等。前面提到的这些操作都可以交给Pinctrl 子系统完成。即把引脚的复用、配置抽出来,做成 Pinctrl 子系统,给 GPIO、I2C 等模块使用

在这里插入图片描述
ps:大多数的芯片,没有单独的 IOMUX 模块,即没有pinctl子系统去管理引脚的复用、配置等等,这些功能都在GPIO 模块内部实现的,所以在硬件上 GPIO 和 Pinctrl 是密切相关,在软件上它们的关系也非常密切

重要概念

涉及 2 个对象:pin controller、client device。

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

pin controller:

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

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

client device:

Pinctrl 系统的客户,那就是使用 Pinctrl 系统的设备,使用引脚的设备。它在设备树里会被定义为一个节点,在节点里声明要用哪些引脚

关系图,右边device是设备树的一个节点,它是Pinctrl 系统的客户

在这里插入图片描述

首先是介绍一个概念引脚的状态:pin state

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

某种状态下对应的引脚配置有如下关联:

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

左图 pin controller 节点中,是给client device 使用的。

  • 可以用来描述复用信息:哪组(group)引脚复用为哪个功能(function);
  • 可以用来描述配置信息:哪组(group)引脚配置为哪个设置功能(setting),比如上拉、下拉等。

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

代码中怎么引用 pinctrl

当设备切换状态时,对应的pinctrl 就会被调用。比如在 platform_device 和 platform_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); // 不再使用, 退出时调用

GPIO 子系统重要概念

概述

ps:大多数的芯片,没有单独的 IOMUX 模块,即没有pinctl子系统去管理引脚的复用、配置等等,这些功能都在GPIO 模块内部实现的,所以在硬件上 GPIO 和 Pinctrl 是密切相关,在软件上它们的关系也非常密切

在这里插入图片描述
通过 Pinctrl 子系统,先把所用引脚配置为 GPIO 功能,然后就可以根据设置引脚方向(输入还是输出)、读值──获得电平状态,
写值──输出高低电平。

当 BSP 工程师实现了 GPIO 子系统后,我们就可以:

  • 在设备树里指定 GPIO 引脚
  • 在驱动代码中:使用 GPIO 子系统的标准函数获得 GPIO、设置 GPIO 方向、读取/设置 GPIO 值。

这样的驱动代码,将是单板无关的,更换单板只需要修改设备树文件,指定GPIO引脚

在设备树中指定引脚

指定引脚就要先确定:它是哪组的?组里的哪一个?

在设备树中,“GPIO 组”就是一个 GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它名字,一般都是厂家定
义好,在 xxx.dtsi 文件中:该节点中有关键属性gpio-controller#gpio-cells

  • “gpio-controller”表示这个节点是一个 GPIO Controller,它下面有很多引脚。
  • “#gpio-cells = <2>”表示这个控制器下每一个引脚要用 2 个 32 位的数(cell)来描述。普遍的用法是,用第 1 个 cell 来表示哪一个引脚,用第 2 个 cell 来表示有效电平:
GPIO_ACTIVE_HIGH : 高电平有效
GPIO_ACTIVE_LOW : 低电平有效

在自己的设备节点中使用属性"[<name>-]gpios",引用某个引脚,可以使用 gpios 属性,也可以使用 name-gpios 属性,示例如下:
在这里插入图片描述
name:描述符,在GPIO标准函数中作为参数
在这里插入图片描述

在驱动代码中调用 GPIO 子系统

GPIO 子系统有两套接口:

  • 基于描述符的(descriptor-based)。函数都有前缀“gpiod_”,它使用 gpio_desc 结构体来表示一个引脚;
  • 老的(legacy)。函数都有前缀“gpio_”,它使用一个整数来表示一个引脚。

头文件

#include <linux/gpio/consumer.h> // descriptor-based#include <linux/gpio.h> // legacy

常用函数

descriptor-basedlegacy
获得 GPIO
gpiod_getgpio_request
gpiod_get_index
gpiod_get_arraygpio_request_array
devm_gpiod_get
devm_gpiod_get_index
devm_gpiod_get_array
设置方向
gpiod_direction_inputgpio_direction_input
gpiod_direction_outputgpio_direction_output
读值、写值
gpiod_get_valuegpio_get_value
gpiod_set_valuegpio_set_value
释放 GPIO
gpio_freegpio_free
gpiod_putgpio_free_array
gpiod_put_array
devm_gpiod_put
devm_gpiod_put_array

建议使用“devm_”版本的相关函数

  • 有前缀“devm”的含义是“设备资源管理” (Managed DeviceResource),这是一种自动释放资源的机制。它的思想是“资源是属于设备的,设备不存在时资源就可以自动释放”。比如在 Linux 开发过程中,先申请了 GPIO,再申请内存;如果内存申请失败,那么在返回之前就需要先释放 GPIO 资源。如果使用 devm 的相关函数,在内存申请失败时可以直接返回:设备的销毁函数会自动地释放已经申请了的GPIO 资源。

实例:

假设备在设备树中有如下节点

foo_device {
	compatible = "acme,foo";
	...
	led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
				<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
				<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
	power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};

那么可以使用下面的函数获得引脚,并设置电平:

struct gpio_desc *red, *green, *blue, *power;
red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);

调用gpiod_set_value设置的值是“逻辑值”,不一定等于物理值,需要对比设备树文件中设置的属性,例如:

在这里插入图片描述

旧的“gpio_”函数没办法根据设备树信息获得引脚,它需要先知道引脚号。

在 GPIO 子系统中,每注册一个 GPIO Controller 时会确定它的“basenumber”,那么这个控制器里的第 n 号引脚的号码就是:base number + n。但是如果硬件有变化、设备树有变化,这个 base number 并不能保证是固定的,应该查看 sysfs 虚拟文件系统中来确定 base number。

先在开发板的/sys/class/gpio 目录下,找到各个 gpiochipXXX 目录,每个目录对应一个GPIO控制器,然后进入某个 gpiochip 目录,查看文件 label 的内容,根据 label 的内容对比设备树,label 内容来自设备树,比如它的寄存器基地址。用来跟设备树(dtsi 文件)比较,就可以知道这对应哪一个 GPIO Controller。

例如,下图是在 stm32mp157 上运行的结果,通过对比设备树可知 gpiochip112对应 gpioH,所以 gpioH 这组引脚的基准引脚号就是 112,cat base 指令得到的也是基准引脚,cat ngpio得到的是这组引脚里面有多少个引脚
在这里插入图片描述
打开ubuntu,进入内核的设备树文件目录,cd /home/book/100ask_stm32mp157_pro-sdk/Linux-5.4/arch/arm64/boot/dts,打开设备树文件:vi stm32mp15xxx-100ask.dtsi,根据label值找到对应的那组寄存器

如图,如果想要操作PG2引脚,可知该引脚属于GPIOG那一组,通过设备树和控制器的对比,找到该组的引脚的基准引脚号,然后在该基准引脚号的基础上加2得到该引脚的引脚号
在这里插入图片描述

那么,我们可以在终端输入如下指令操作该引脚:

将引脚暴露在/sys/class/gpio 目录下

echo 98 > /sys/class/gpio/export

修改方向位输入

echo in > /sys/class/gpio/gpio98/direction

获取引脚值

cat /sys/class/gpio/gpio98/value

销毁该引脚控制器

echo 98 > /sys/class/gpio/unexport

对于输出引脚,我们可以调用如下指令使其输入1

echo N > /sys/class/gpio/export
echo out > /sys/class/gpio/gpioN/direction
echo 1 > /sys/class/gpio/gpioN/value
echo N > /sys/class/gpio/unexport

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/46081.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTTPS安全套接字层超文本传输协议

HTTPS安全套接字层超文本传输协议 HTTPS简介HTTPS和HTTP的主要区别客户端在使用HTTPS方式与Web服务器通信时的步骤SSL/TLS协议的加密&#xff08;握手&#xff09;过程为什么数据传输阶段使用对称加密HTTPS 的优点HTTPS 的缺点HTTPS 的优化证书优化会话复用 HTTPS简介 HTTP协议…

PPT逻辑设计与完美呈现

PPT逻辑设计与完美呈现 https://haoxinyunxueyuan.zhixueyun.com/#/study/course/detail/detailInfoCD00——朱宁川 logo设计神器: https://www.zitijia.com/logodiy/index 一 PPT设计 第一章、PPT的灵魂设计-5W PPT灵魂设计(5W) 以终为始&#xff0c;从目标出发 why 目…

防抖和节流

1. 防抖 1.1 定义 针对高频触发事件&#xff0c;让事件处理函数的逻辑代码延迟一段时间再执行&#xff0c;如果在延迟的这段时间再次触发&#xff0c;则重新开始计时&#xff0c;直到在计时的这段时间内没有再次触发&#xff0c;则执行事件处理函数的逻辑代码 原因&#xff…

(五)RabbitMQ-进阶 死信队列、延迟队列、防丢失机制

Lison <dreamlison163.com>, v1.0.0, 2023.06.23 RabbitMQ-进阶 死信队列、延迟队列、防丢失机制 文章目录 RabbitMQ-进阶 死信队列、延迟队列、防丢失机制死信队列延迟队列延迟队列介绍**延迟队列_死信队列_的实现**延迟队列_插件实现下载插件RabbitMQ 配置类RabbitMQ …

SpringCloudAlibaba微服务实战系列(一)Nacos服务注册发现

SpringCloudAlibaba微服务实战系列&#xff08;一&#xff09;Nacos服务注册发现 实战前先做一个背景了解。 单体架构、SOA和微服务 单体架构&#xff1a;近几年技术的飞速发展&#xff0c;各种各样的服务已经进入到网络化。单体架构发布时只需要打成一个war或jar包发布即可&a…

2023年的深度学习入门指南(19) - LLaMA 2源码解析

2023年的深度学习入门指南(19) - LLaMA 2源码解析 上一节我们学习了LLaMA 2的补全和聊天两种API的使用方法。本节我们来看看LLaMA 2的源码。 补全函数text_completion源码解析 上一节我们讲了LLaMA 2的编程方法。我们来复习一下&#xff1a; generator Llama.build(ckpt_di…

设计模式 - 工厂模式

一、 简单工厂&#xff08;Simple Factory Pattern&#xff09; 1、概念 一个工厂对象决定创建出哪一种产品类的实力&#xff0c;但不属于GOF23种设计模式。 简单工厂适用于工厂类负责创建的对象较少的场景&#xff0c;且客户端只需要传入工厂类的参数&#xff0c;对于如何创…

fastadmin采坑之接口分页处理

其实不算fastadmin的代码而是thinkphp自带的分页代码 paginate函数就是自带的分页函数&#xff0c;开始我以为这个只能用于渲染模板不能用于接口&#xff0c;后面看到源代码发现请求参数带page就可以 /*** ApiTitle (获取协会会员)* ApiSummary (获取协会会员)* ApiMethod …

Java在线OJ项目(一)、多进程编程实现 做题代码的编译和运行

在线OJ项目&#xff08;一&#xff09;、多进程编程实现 做题代码的编译和运行 一、回顾线程和进程二、进程比线程的优势三、多进程编程样例四、多进程思想 实现对代码 的编译 以及 运行两个功能CommandUtil 由于我们是在线oj&#xff0c;所以得编译用户的代码不仅编译 还需要 …

[ELK使用篇]:SpringCloud整合ELK服务

文章目录 一&#xff1a;前置准备-(参考之前博客)&#xff1a;1.1&#xff1a;准备Elasticsearch和Kibana环境&#xff1a;1.1.1&#xff1a;地址&#xff1a;[https://blog.csdn.net/Abraxs/article/details/128517777](https://blog.csdn.net/Abraxs/article/details/1285177…

云服务器远程nacos服务注册失败/不健康Client not connected, current status:STARTING

文章目录 Nacos报错docker安装不用 docker安装 Nacos报错 docker安装 使用docker在云服务器安装Nacos之后出现Client not connected, current status:STARTING 使用docker 安装之后需要添加映射端口 docker run -e JAVA_OPTS"-Xms256m -Xmx256m"-e MODEstandalone…

领导需求不好接?给你一份“化危为机的自救指南”

领导高瞻远瞩&#xff0c;落地成难&#xff0c;问题&#xff1a;领导常常是急性发挥&#xff0c;时间稍微久一点就思路就模糊了&#xff0c;后续怎么做都不对。 遇到这种情况的小伙伴&#xff0c;公屏打上“pua”。 这种情况下&#xff0c;给出自救指南&#xff1a; 1、引导交…

深度学习——批标准化Batch Normalization

什么是批标准化&#xff1f; 批标准化&#xff08;Batch Normalization&#xff09;是深度学习中常用的一种技术&#xff0c;旨在加速神经网络的训练过程并提高模型的收敛速度。 批标准化通过在神经网络的每一层中对输入数据进行标准化来实现。具体而言&#xff0c;对于每个输…

vue3+elementplus后台管理系统,实现侧边栏菜单显示到主内容区域

目录 1 创建页面2 设置路由3 修改首页4 首页的完整代码总结 我们已经使用vue3和elmentplus初步搭建了首页&#xff0c;上一篇中有个问题没解决&#xff0c;就是在侧边栏导航功能里&#xff0c;如果点击菜单希望是在首页打开页面而不是跳转到新页面。以下是我们希望实现的效果 这…

AI学习笔记二:YOLOV5环境搭建及测试全过程

若该文为原创文章&#xff0c;转载请注明原文出处。 记录yolov5从环境搭建到测试全过程。 一、运行环境 1、系统&#xff1a;windows10 &#xff08;无cpu) 2、yolov5版本&#xff1a;yolov5-5.0 3、python版本&#xff1a;py3.8 在创建虚拟环境前需要先把miniconda3和py…

GUI自动化测试进阶:页面对象模式

本文介绍的是页面对象设计模式及其常见的滥用继承的错误。 本文和语言无关&#xff0c;但作者主要使用python和java。本文假设读者已经具有了一定的python或java基础&#xff0c;知道类和方法是什么。 如果完全没有这方面的基础&#xff0c;请看我的《测试人员如何学Python》。…

【图像分类】基于LIME的CNN 图像分类研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 基于LIME&#xff08;Local Interpretable Model-Agnostic Explanations&#xff09;的CNN图像分类研究是一种用于解释CNN模型的方法。LIME是一…

【UE5 多人联机教程】04-加入游戏

效果 步骤 1. 新建一个控件蓝图&#xff0c;父类为“USC_Button_Standard” 控件蓝图命名为“UMG_Item_Room”&#xff0c;用于表示每一个搜索到的房间的界面 打开“UMG_Item_Room”&#xff0c;在图表中新建一个变量&#xff0c;命名为“Session” 变量类型为“蓝图会话结果…

自恢复保险丝(PPTC)的金属材料说明

保险丝大家都是知道的&#xff0c;但保险丝当中的自恢复保险丝&#xff08;PPTC&#xff09;可能就不太了解的。 其实PPTC自恢复保险丝与大家所认识的保险丝一样&#xff0c;都是起到限流作用&#xff0c;达到电路防护效果。简单来说就是一旦电路中的电流超过所规定的电流时&am…

【数据结构】二叉树详解(3)

⭐️ 前言 ✨ 往期链接&#xff1a;【数据结构】二叉树详解(1) 在第一篇二叉树文章中&#xff0c;我们探讨了二叉树的链式结构定义与实现。二叉的遍历包含( 前序/中序/后序遍历 )及代码实现和递归流程图的详细讲解。还有一些二叉树的其他接口定义与实现&#xff0c;包含 Binar…