本文参考linux官方文档https://www.kernel.org/doc/Documentation/gpio/consumer.txt进行编写。
头文件
需要首先包含头文件
#include <linux/gpio/consumer.h>
获取&释放
使用一下两个函数获取GPIO设备,多个设备时需要附带index参数。函数返回一个GPIO描述符,或一个错误编码,可以使用IS_ERR()进行检查:
struct gpio_desc *gpiod_get(struct device *dev, const char *con_id,
enum gpiod_flags flags)
struct gpio_desc *gpiod_get_index(struct device *dev,
const char *con_id, unsigned int idx,
enum gpiod_flags flags)
或者也可以使用如下两个函数获取可用设备:
struct gpio_desc *gpiod_get_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
struct gpio_desc *gpiod_get_index_optional(struct device *dev,
const char *con_id,
unsigned int index,
enum gpiod_flags flags)
使用如下函数同时获取多个设备:
struct gpio_descs *gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
该函数返回一个GPIO描述序列:
struct gpio_descs {
unsigned int ndescs;
struct gpio_desc *desc[];
}
一个GPIO描述符可以使用如下函数释放:
void gpiod_put(struct gpio_desc *desc)
void gpiod_put_array(struct gpio_descs *descs)
需要注意GPIO描述符被释放后不可再使用,而且不允许使用第一个函数来释放通过序列获取得到GPIO描述符。
使用GPIO
- 设置方向(Input | Output)
使用如下函数设置一个设备的方向
int gpiod_direction_input(struct gpio_desc *desc)
int gpiod_direction_output(struct gpio_desc *desc, int value)
使用如下函数检查一个设备的方向:int gpiod_get_direction(const struct gpio_desc *desc)
函数返回GPIOF_DIR_IN或者GPIOF_DIR_OUT -
访问
访问分为两种,一种是通过储存器读写实现的,这种操作属于原子操作,不需要等待,所以可以在中断处理程序中使用:int gpiod_get_value(const struct gpio_desc *desc); void gpiod_set_value(struct gpio_desc *desc, int value);
还有一种访问必须通过消息总线比如I2C或者SPI,这种访问需要在总线访问队列中等待,所以可能进入睡眠,此类访问不能出现在IRQ handler。
可以使用如下函数分辨这些设备:int gpiod_cansleep(const struct gpio_desc *desc)
使用如下函数读写:
int gpiod_get_value_cansleep(const struct gpio_desc *desc) void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
-
active-low & raw value
有些设备采用低电平有效的方式输出逻辑信号。此时低电平输出1,高电平输出0。此时可以通过访问raw_value的方式来访问实际电路上的值,与逻辑处理无关:int gpiod_get_raw_value(const struct gpio_desc *desc) void gpiod_set_raw_value(struct gpio_desc *desc, int value) int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
逻辑关系汇总如下:
Function (example) active-low property physical line
gpiod_set_raw_value(desc, 0); don’t care low
gpiod_set_raw_value(desc, 1); don’t care high
gpiod_set_value(desc, 0); default (active-high) low
gpiod_set_value(desc, 1); default (active-high) high
gpiod_set_value(desc, 0); active-low high
gpiod_set_value(desc, 1); active-low low可以使用如下函数判断一个设备是否是低电平有效的设备。
int gpiod_is_active_low(const struct gpio_desc *desc)
- 设置多个输出
使用如下函数设置一组设备的输出值
void gpiod_set_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
以上函数均可配套gpiod_get_array()使用 - 映射到IRQ
使用如下函数获取一个GPIO设备对应的IRQ中断号
int gpiod_to_irq(const struct gpio_desc *desc)
返回值时一个IRQ number,或者一个负数的错误代码。得到的中断号可以传递给函数request_irq(),free_irq(). - ACPI
在ACPI系统上,GPIO设备在GpioIo()/GpioInt()从_CRS中获得的资源列表中被描述,这些资源不能在系统GPIO中被使用。 - 兼容旧版本
旧的GPIO系统使用基于标号的结构而不是基于描述符。可以使用如下两个函数进行相互转换:
int desc_to_gpio(const struct gpio_desc *desc)
struct gpio_desc *gpio_to_desc(unsigned gpio)
注意不能使用一套API的方法释放另一套API获取的设备