Linux驱动开发基础__gpio子系统重要概念
创始人
2024-05-08 09:01:57
0

目录

1 引入

2  在设备树中指定引脚

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

4  sysfs 中的访问方法


1 引入

要操作 GPIO 引脚,先把所用引脚配置为 GPIO 功能,这通过 Pinctrl 子系统来实现。 
然后就可以根据设置引脚方向(输入还是输出)、读值──获得电平状态,写值──输出高低电平。 
以前我们通过寄存器来操作 GPIO 引脚,即使 LED 驱动程序,对于不同的板子它的代码也完全不同。 
当 BSP 工程师实现了 GPIO 子系统后,我们就可以: 
⚫  在设备树里指定 GPIO 引脚 
⚫  在驱动代码中:使用 GPIO 子系统的标准函数获得 GPIO、设置 GPIO 方向、读取/设置 GPIO 值。 
这样的驱动代码,将是单板无关的。

2  在设备树中指定引脚

在几乎所有 ARM 芯片中,GPIO 都分为几组,每组中有若干个引脚。所以在使用 GPIO 子系统之前,就要先确定:它是哪组的?组里的哪一个? 

在设备树中,“GPIO 组”就是一个 GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它名字,比如“gpio1”,然后指定要用它里面的哪个引脚,比如<&gpio1  0>。 
有代码更直观,下图是一些芯片的 GPIO 控制器节点,它们一般都是厂家定义好,在 xxx.dtsi 文件中:

 我们暂时只需要关心里面的这 2 个属性: 

gpio-controller; 
#gpio-cells = <2>; 

⚫  “gpio-controller”表示这个节点是一个 GPIO Controller,它下面有很多引脚。 
⚫  “#gpio-cells  =  <2>”表示这个控制器下每一个引脚要用 2 个 32 位的数(cell)来描述。 
为什么要用 2 个数?其实使用多个 cell 来描述一个引脚,这是 GPIO Controller 自己决定的。比如可以用其中一个 cell 来表示那是哪一个引脚,用另一个 cell 来表示它是高电平有效还是低电平有效,甚至还可以用更多的cell 来示其他特性。 
普遍的用法是,用第 1 个 cell 来表示哪一个引脚,用第 2 个 cell 来表示有效电平: 

GPIO_ACTIVE_HIGH : 高电平有效 
GPIO_ACTIVE_LOW  :  低电平有效 

定义 GPIO Controller 是芯片厂家的事,我们怎么引用某个引脚呢?在自己的设备节点中使用属性"[-]gpios",示例如下: 

上图中,可以使用 gpios 属性,也可以使用 name-gpios 属性。 

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

在设备树中指定了 GPIO 引脚,在驱动代码中如何使用? 也就是 GPIO 子系统的接口函数是什么? 
GPIO 子系统有两套接口:基于描述符的(descriptor-based)、老的(legacy)。前者的函数都有前缀“gpiod_”,它使用 gpio_desc 结构体来表示一个引脚;后者的函数都有前缀“gpio_”,它使用一个整数来表示一个引脚。 

要操作一个引脚,首先要 get 引脚,然后设置方向,读值、写值。 驱动程序中要包含头文件, 

#include    // descriptor-based 
或 
#include             // legacy 

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

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

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 时会确定它的“base number”,那么这个控制器里的第 n 号引脚的号码就是:base number + n。 
但是如果硬件有变化、设备树有变化,这个 base  number 并不能保证是固定的,应该查看 sysfs 来确定 base number。

4  sysfs 中的访问方法

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...