自己翻译的内核gpiolib文档,是2.6.38版本的。原文在:http://lxr.linux.no/linux+v2.6.38/Documentation/gpio.txt
内核文档
2011/05/08
标识端口
-------------
gpio使用0~MAX_INT之间的整数标识,不能使用负数。
使用以下函数检查一个端口号的合法性:
int gpio_is_valid(int number);
? 使用gpio
-------------
使用io的第一步是分配端口,使用 gpio_request()。
接下来要做的是标记它的方向。
通常应该检查它们的返回值。通常应该假定这两个接口会在线程上下文中调用。但是
对于自旋锁安全的gpio也可以在线程出现之前的早期初始化之间使用。
对于输出的gpio,提供的值作为输出的初始值。
? 使用自旋锁安全的gpio
----------------------------------
大部分gpio控制器可以使用内存读写指令来访问,不需要睡眠,可以在中断上下文访问。
对于gpio_cansleep返回假的gpio可以使用下面的接口访问:
int gpio_get_value(unsigned gpio);
void gpio_set_value(unsigned gpio, int value);
返回的值是布尔值,零代表低,非零代表搞电平。当读取输出引脚的值,返回值应该是引脚上的实际状态,
这个值不一定等于配置的输出值,因为从设定信号到信号稳定需要一定时间。
不是所有的平台可以读取输出的引脚值,这些平台不能总是返回零。用这两这两个函数访问
不能非在睡眠的上下文中安全访问的gpio将是一个错误。
? 可被休眠上下文中访问的GPIO
----------------------------------------------
一些gpio控制器必须使用基于信息的总线,比如i2c和spi.读写gpio值的命令需要在队列中等待。
操作这些gpio可能会睡眠,不能在中断上下文中调用。
支持这种gpio的平台为了通过在这个函数中返回非零来区分其它
类型的gpio(需要一个已经被gpio_request申请的gpio号):
int gpio_cansleep(unsigned gpio);
为了访问这些端口,定义了另一组函数接口:
int gpio_get_value_cansleep(unsigned gpio);
void gpio_set_value_cansleep(unsigned gpio, int value);
只能在允许睡眠的上下文中访问这些端口,比如线程化的中断中,
必须使用这些接口而不是没有cansleep前缀的自旋锁安全接口。
除了这些接口可能睡眠这个事实之外,它们操作那些不能在中断处理函数中访问的端口,这些调用的表现和
自旋锁安全的调用表现一致。
另外:调用安装和配置这样的gpio必须是在可睡眠的上下文中,因为他们可能需要访问gpio控制器。
## gpio_request_one()
## gpio_request_array()
## gpio_free_array()
? 申请和释放gpio
------------------------
为了获取系统配置错误,定义了两个调用:
int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned gpio);
应该假设这两个函数实在进程上下文中调用的,但对于自旋锁安全的gpio也可从
在进程建立之前的早期启动过程中调用。
考虑到大多数情况下gpio会在申请过后立即需要被配置,下面三个接口负责这些工作:
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
int gpio_request_array(struct gpio *array, size_t num);
void gpio_free_array(struct gpio *array, size_t num);
“falg”用来配置下面的特性:
为了同时处理多个gpio,定义了一个专门结构体:
典型的使用如下:
-
GPIO映射到IRQ
----------------------------
返回值是对应的编号或者是负的错误码。使用未用gpio_direction_input()安装的gpio编号或者不是从
gpio_to_irq()得到的中断号是不会被gpio检查的错误。
gpio_to_irq()返回的中断编号可以传给request_irq()和free_irq()。
irq_to_gpio()返回的gpio编号通常用来调用gpio_get_value(),比如在沿触发的中断中获取引脚的状态。
有些平台不支持这种映射,应该避免调用映射函数。
模拟漏极开路
------------------
gpio可能支持也可能不支持漏极开路输出。如果硬件不支持,可以模拟漏极开路输出的输入或者输出:
LOW: gpio_direction_output(gpio, 0) 忽略上拉电阻。
HIGH: gpio_direction_input(gpio) 关闭输出,上拉电阻控制信号。
如果驱动输出高电平但是gpio_get_value(gpio)报告的电平是低电平(经过一定延迟之后),可以断定
其它部分正在信号线上输出低电平。
GPIO 的框架(可选)
===============
GPIO的框架在gpiolib中实现。
如果使能了 debugfs,系统下会出现 /sys/kernel/debug/gpio这个文件。这个文件内
将会列出所有注册在框架内的控制器和当前使用的gpio的状态。
在gpio框架中使用"struct gpio_chip"表示每个控制器的所有信息:
--设置gpio方向的方法
--访问gpio状态的方法
--表示是否会睡眠的标志
--可选的debugfs方法
--诊断用的标签lable(char指针)
当然还有每个实例的独有数据(可能来自dev.platform_data);第一个gpio的编号和管理的gpio数量。
gpiolib支持多个gpio控制器的实例,使用gpiochip_add()来注册,使用gpiochip_remove()注销。
gpio_chip的debugfs方法将会忽略未被申请的gpio。使用gpiochip_is_requested()将会返回NULL(未被申请)或者
lable(已被申请)
平台支持
------------
为了支持gpio框架,必须选择Kconfig中的选项:ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB。并且
在 包含,还要定义三个函数: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
同时也可以提供ARCH_NR_GPIOS的定义,以反映平台支持的gpio数量。
ARCH_REQUIRE_GPIOLIB表示gpiolib代码总是会编译进内核中。
ARCH_WANT_OPTIONAL_GPIOLIB表示gpiolib默认是关闭的,但是用户可以使能它并把它编译进内核。
如果这两个选项一个都未被选中,gpiolib则不能被用户使能。
通常那三个函数接口可以直接使用框架内的代码(通过gpio_chip来调用):
用户空间的sysfs接口(可选)
==================
在sysfs下的路径
---------------------
在/sys/class/gpio下有三种类型的入口:
以上接口不包括标准“device”文件和它们的链接。
控制接口(第一类)是只写的:
GPIO管脚的路径类似于/sys/class/gpio/gpio42/ (for GPIO #42)的形式,并且有以下可读写的属性:
GPIO控制器的路径类似于/sys/class/gpio/gpiochip42/(这个控制器的最小端口是42)并且有以下的读写属性:
从内核空间中导出
------------------------
内核可以对已经被
gpio_request()申请的gpio的导出进行明确的管理。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以上内容是内核文档的内容,下面分析gpio_chip的内容,这是一个控制器。
struct gpio_chip {
gpio_chip的接口:
extern const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset); 如果offet对应的gpio已经被申请了则返回NULL,否则返回lable指针或者“??”
extern int __must_check gpiochip_reserve(int start, int ngpio);
将start开始的ngpio个编号保留
这个函数是在全局范围内预留一段编号,将来供某个gpio_chip使用。