gpio接口是干什么的?gpio怎么用?

网友投稿 482 2022-11-01

gpio接口是干什么的?gpio怎么用?

一、gpio用途

每个GPIO端口可通过软件分别配置成输入或输出。Maxim的GPIO产品线包括8端口至28端口的GPIO,提供推挽式输出或漏极开路输出。提供微型3mm x 3mm QFN封装。

不同系统间的GPIO的确切作用不同。通用常有下面几种:

2.输入值可读(1,0)。一些芯片支持输出管脚回读,这在线或的情况下非常有用(以支持双向信号线)。GPIO控制器可能具有一个输入防故障/防反跳逻辑,有时还会有软件控制。

3.输入经常被用作中断信号,通常是边沿触发,但也有可能是电平触发。这些中断可以配置为系统唤醒事件,从而将系统从低功耗模式唤醒。

4.一个GPIO经常被配置为输入/输出双向,根据不同的产品单板需求,但也存在单向的情况。

5.大多是GPIO可以在获取到spinlock自旋锁时访问,但那些通过串行总线访问的通常不能如此操作(休眠的原因)。一些系统中会同时存在这两种形式的GPIO。

二、gpio优点

集成IIC从机接口:GPIO内置IIC从机接口,即使在待机模式下也能够全速工作。

小封装:GPIO器件提供最小的封装尺寸 ― 3mm x 3mm QFN!

低成本:您不用为没有使用的功能买单。

快速上市:不需要编写额外的代码、文档,不需要任何维护工作。

灵活的灯光控制:内置多路高分辨率的PWM输出。

可预先确定响应时间:缩短或确定外部事件与中断之间的响应时间。

更好的灯光效果:匹配的电流输出确保均匀的显示亮度。

GPAUP 没有上拉电阻。

三、GPIO系统结构

如前面提醒的一样,一个可选的实现结构使得平台支持不同种类的GPIO控制器使用同一个编程接口变得简单。这个结构称为gpiolib。

作为一个调试目的,如果debugfs有效,一个/sys/kernel/debug/gpio文件在那里将被找到。它列出了所有的通过这个结构注册的GPIO控制器,和GPIO当前的使用状态。

Controller Drivers: gpio_chip

控制器驱动:gpio_chip

在这个架构中,每个GPIO控制器被封装为一个“gpio_chip”结构体,此结构体中包含了每个控制器的通用信息:

--确定GPIO方向的方法

--存取GPIO值的方法

--可选的debugfs dump方法(展现附加的状态如上拉配置等)

--用于诊断目的的标签

每个实例也有自己的私有数据,可能来自device.platform_data:它的第一个GPIO和它暴露几个GPIO.

平台支持

他也可以提供一个自定义的值:ARCH_NR_GPIOS,以便能更好的反映平台实际使用的GPIO数目,并不浪费静态区域空间。(它应该计数 内建/SOC GPIO和GPIO扩展器扩展的数目)

ARCH_REQUIRE_GPIOLIB意味着此平台上gpiolib代码将永久编译进内核

如果这些选项都未被选上,平台不能通过GPIO-lib支持GPIO,这些代码也不能被用户使能。

那些函数琐细的实现可以直接使用架构代码,它们经常通过gpio_chip分配:

#define gpio_get_value__gpio_get_value

#define gpio_set_value__gpio_set_value

#define gpio_cansleep__gpio_cansleep

对于SOC来说,平台特定的代码为每个bank的片上GPIO定义和注册了gpio_chip实例。那些GPIO应该被编号和打上标签以匹配芯片厂商文档,且直接匹配单板设计图。他们可以从零开始一直到平台特定的限制。这些GPIO通常集成到单板初始化过程中以使得它们总是有效的,从arch_initcall()到更早,它们总是可以为中断服务。

板级支持

例如,单板setup代码可以创建结构标示芯片想要暴露的GPIO的范围,且使用platform_data传递它们到每个GPIO扩展器芯片。这样芯片驱动的probe()历程可以传递这些数据到gpiochip_add()。

初始化顺序是很重要的。例如当一个依赖于基于I2C的GPIO的设备,它的probe()例程应该仅能在GPIO有效后调用。这意味着设备不能在GPIO可以工作之前注册。一个解决这样依赖的方法是在板级特定代码中,对于这种gpio_chip控制器来提供setup()和teardown()回调,这些板级特定的回调将注册设备一旦所有的需要资源有效时,并且在GPIO控制器无效时将它们移除。

用户空间的Sysfs接口(可选)

使用gpiolib实现结构的平台可以选择为GPIO配置一个sysfs用户接口。这与debugfs接口不同,因为它提供了覆盖GPIO方向和值的控制而不只是显示一个gpio状态信息摘要。另外,它可以在产品系统中提供而不需要调试支持。

为系统给出对应的硬件文档,用户空间可以知道例如GPIO#23控制着保护线,用于保护flash中的boot区域。系统升级程序可能需要临时移除这个保护,首先引入一个GPIO,然后改变它的输出状态,接下来在重新使能写保护之前升级代码。通常用法中,GPIO#23将不会被触碰,并且内核也不需知道它的信息。

同样依靠一个合适的硬件文档,在一些系统用户空间,GPIO可以被用于决定那些内核并不关心的系统配置数据。对于一些任务,简单用户空间GPIO驱动是系统真正需要的

注意,针对通用“LED和按钮”的标准内核驱动存在对应的GPIO任务“leds-gpio”和“gpio-keys”。使用它们代替直接与GPIO通话,它们集成在内核架构比你的用户态代码可能更好。

Paths in Sysfs

Sysfs路径

There are three kinds of entry in /sys/class/gpio:

/sys/class/gpio有3个入口条目:

-控制接口用于用户空间获取GPIO控制

-GPIO自己

-GPIO控制器(“gpio_chip”实例)

这是对于标准文件的补充,包括“device”符号

控制接口是只写的:

/sys/class/gpio/

“export” ————通过写GPIO的号码到此文件,用户空间可以要求内核导出一个GPIO的控制到用户空间

例如:“echo 19 》 export”将创建一个GPIO #19的“gpio19”节点(假设内核代码未申请此GPIO号)。

“unexport”————与“export”效果相反

例如:“echo 19 》 unexport”将移除一个由“export”文件导出的“gpio19”节点。

GPIO信号拥有如/sys/class/gpio/gpio42/(对应于GPIO#42)的路径,并且具有下列读写属性:

/sys/class/gpio/gpioN/

“direction”————读为“in”或是“out”。这个值通常可写。写“out”默认初始化此值为低。为了确定无障碍操作,值“low”和“high”可以被写入以配置GPIO的输出初始化值。

注意这个属性“将不存在”如果内核不支持改变一个GPIO的方向,或者它不能被内核代码导出(不能显式的允许用户空间来重新配置GPIO的选项。)

“value”—————读作“0”(低)或“1”(高)。如果GPIO被配置为一个输出,这个值可写;任何非零值均被视为高。

如果管脚可以被配置为中断产生中断管脚,且如果它已经被配置为产生中断(参考“edge”描述),你可以poll(2)此文件并且当中断触发时poll(2)将返回。如果你使用了poll(2),设置POLLPRI和POLLERR事件。如果你使用select(2),在exceptfds中设置文件描述符。在poll(2)返回之后,有两个选择一是lseek(2)到sysfs文件的开始且读新的值,另一个是关闭文件且重打开它来读取新的值。(为何这样设置?)

这个文件只在管脚可以配置为中断产生输入管脚时存在。

“active_low”————读为0(false)或1(true)。写任何非零值都会反转读或写的值。目前和后来的poll(2)支持经由edge属性配置为“rising”或“falling”上升沿或下降沿将遵循这个设置。

GPIO控制器具有如/sys/class/gpio/gpiochip42/(针对控制器,实现GPIO开始于#42)的路径,且具有下列制度属性:

/sys/class/gpio/gpiochipN/

“base”————与N相等,是第一个被此芯片管理的GPIO

“label”————提供用于诊断(并不总是独一无二的)

“ngpio”————管理的GPIO数(N到N+ngpio-1)

大多数情况下,单板文档应该提供GPIO的使用目的。虽然如此这些号码并非总是固定的,一个子板上的GPIO可能与基础板使用的不同。此种情况下,你可能需要使用gpiochip节点(可能与设计结合)来为每个信号决定正确的GPIO号码。

从内核代码中导出

内核代码可以显式管理那些使用gpio_request()申请的GPIO的导出

int gpio_export(unsigned gpio, bool direction_may_change);

/* reverse gpio_export() */

void gpio_unexport();

/* create a sysfs link to an exported GPIO node */

int gpio_export_link(struct device *dev, const char *name,

unsigned gpio)

/* change the polarity of a GPIO node in sysfs */

int gpio_sysfs_set_active_low(unsigned gpio, int value);

一个内核驱动申请一个GPIO后,它可以使用gpio_export()使得sysfs接口有效。驱动可以控制信号方向是否可以改变。这使得驱动可以防止用户空间代码不小心冲击重要的系统状态。

明确的exporting有助于调试(使得一些实验更简单),或是提供一个总是可以使用的接口,适合于bsp文档。

GPIO被导出后,gpio_export_link()允许在sysfs的任何地方创建GPIO sysfs节点的符号链接。驱动可以用此在它们自己设备sysfs目录下提供指定名字的接口(链接到GPIO节点)

驱动可以使用gpio_sysfs_set_active_low()隐藏GPIO在用户空间和单板之间的线极性不同。这仅影响sysfs接口。极性变换可以在gpio_export()之前和之后完成,并且前面使能的poll(2) (支持上升沿或下降沿事件)将被重新配置为遵循此设置。

四、GPIO使用方法

要使用GPIO,系统首先要分配一个GPIO,使用gpio_request() 为系统分配一个GPIO。

接下来要做的一件事是标示GPIO的方向,通常在使用GPIO建立一个platform_device时(位于单板的setup代码中):

/* set as input or output, returning 0 or negative errno */

int gpio_direction_input(unsigned gpio);

int gpio_direction_output(unsigned gpio, int value);

返回0标示成功,或是一个负的errno错误码。它应该被检查,因为get/set调用没有错误返回,且可能会有错误配置。你通常应该在线程上下文中使用这些调用。虽然如此,对于spinlock-safe的GPIO,在tasking使能之前使用也是可以的,作为一个早期的单板建立。

对于输出GPIO,value参数提供了初始输出值。这有助于避免系统启动过程中的信号干扰。

为了与GPIO早期的接口兼容,设置一个GPIO的方向,隐性要求申请GPIO。这个兼容性从可选的gpiolib架构中移除了。

Spinlock-Safe GPIO访问

-------------------------

大多数GPIO控制器可以使用内存读写指令访问。它们不需要休眠,且可以从内部硬件中断处理(非线程)和类似的上下文环境安全完成。

使用下列调用访问这些GPIO,此时gpio_cansleep将总是返回错误

/* GPIO INPUT: return zero or nonzero */

int gpio_get_value(unsigned gpio);

/* GPIO OUTPUT */

void gpio_set_value(unsigned gpio, int value);

其中,value是一个布尔型参数,零表示低,非零表示高。当读一个输出管脚的值时,返回的值应该是在管脚上看到的值。。。这并不总是与指定输出值相匹配的,因为存在开漏信号和输出延迟问题。

get/set调用没有错误返回,因为“无效GPIO”应该已经由gpio_direction_*()提早报告了。虽然如此,并非所有的平台都可以读取输出管脚的值,那些不能读的应该总是返回零。同时,对那些可能导致睡眠的GPIO使用这些接口是一个错误。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:ELK学习笔记之ELK分析syslog日志
下一篇:mybatis的动态SQL以及连接池详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~