linux内核GPIO编程说明

来源:互联网 发布:2016各类案件数据统计 编辑:程序博客网 时间:2024/05/21 11:37
内核GPIO编程说明


参考资料:https://www.kernel.org/doc/Documentation/gpio/


从官方资料来看,linux内核中的gpio接口目前有新旧两个版本,新的版本的接口是descriptor-based的,而旧的是integer-based的。旧的接口已出于兼容性的考虑仍被支持,但已不再建议使用。网上目前大多GPIO编程说明都是旧的版本,所以这篇说明就以介绍新的接口版本为主。


1.驱动首先需要包含头文件:


#include <linux/gpio/consumer.h>


2.调用gpio设备所需函数,函数返回描述符或错误码


struct gpio_desc *gpiod_get(struct device *dev, const char *con_id,
   enum gpiod_flags flags)


如果设备需要使用多个gpio,则需在函数中添加index参数:

struct gpio_desc *gpiod_get_index(struct device *dev,
 const char *con_id, unsigned int idx,
 enum gpiod_flags flags)


其中gpiod_flag控制初始化模式,有以下几种:
* GPIOD_ASIS or 0 不进行初始化
* GPIOD_IN 将gpio初始化为input模式
* GPIOD_OUT_LOW 将gpio初始化为低电平output
* GPIOD_OUT_HIGH 将gpio初始化为高电平output


也可以用以下两个函数调用可用gpio。当没有gpio调用成功时,返回null


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)


或者在获取多个gpio时只要调用一个函数即可:


struct gpio_descs *gpiod_get_array(struct device *dev,
  const char *con_id,
  enum gpiod_flags flags)


该函数返回结构体gpi_descs:


struct gpio_descs {
unsigned int ndescs;
struct gpio_desc *desc[];
}


3. 释放一个gpio使用函数:


void gpiod_put(struct gpio_desc *desc)


或者释放多个gpio使用


void gpiod_put_array(struct gpio_descs *descs)


在调用这些函数后,被释放的描述符不可再被使用。


4.GPIO的设置
调用以下函数来的设置gpio的方向:


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
5.GPIO的访问
GPIO的访问可通过主存的读写指令完成,这种操作不需要sleep,所以在内部硬中断时也可以被调用,安全性较高。使用以下函数来进行该原子访问操作:


int gpiod_get_value(const struct gpio_desc *desc);
void gpiod_set_value(struct gpio_desc *desc, int value);


另一种gpio设备访问必须使用消息总线如I2C或SPI,这种操作需要在队列中等待,所以不再能在IRQ中被调用:


int gpiod_get_value_cansleep(const struct gpio_desc *desc)
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)


分辨此类gpio设备:


int gpiod_cansleep(const struct gpio_desc *desc)


6.输出信号
有些设备采用低电平有效的方式输出逻辑信号。此时低电平输出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)


可以通过以下函数对一组GPIO进行输出设置:


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)


7.映射到IRQs


int gpiod_to_irq(const struct gpio_desc *desc)


8.GPIO和ACPI
在ACPI系统上,GPIO设备在GpioIo()/GpioInt()从_CRS中获得的资源列表中被描述,这些资源不能在系统GPIO中被使用。
原创粉丝点击