Linux内核中的GPIO驱动

本文参考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

  1. 设置方向(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
  2. 访问
    访问分为两种,一种是通过储存器读写实现的,这种操作属于原子操作,不需要等待,所以可以在中断处理程序中使用:

    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)
  3. 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)
  4. 设置多个输出
    使用如下函数设置一组设备的输出值

    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()使用
  5. 映射到IRQ
    使用如下函数获取一个GPIO设备对应的IRQ中断号

    int gpiod_to_irq(const struct gpio_desc *desc)

    返回值时一个IRQ number,或者一个负数的错误代码。得到的中断号可以传递给函数request_irq(),free_irq().
  6. ACPI
    在ACPI系统上,GPIO设备在GpioIo()/GpioInt()从_CRS中获得的资源列表中被描述,这些资源不能在系统GPIO中被使用。
  7. 兼容旧版本
    旧的GPIO系统使用基于标号的结构而不是基于描述符。可以使用如下两个函数进行相互转换:

    int desc_to_gpio(const struct gpio_desc *desc)
    struct gpio_desc *gpio_to_desc(unsigned gpio)

    注意不能使用一套API的方法释放另一套API获取的设备
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PWM-GPIO驱动程序是Linux内核的一个驱动模块,用于控制嵌入式系统GPIO引脚产生PWM信号。该驱动程序允许开发人员通过编程的方式来控制GPIO引脚的电平变化,从而产生不同占空比的PWM信号。 在Linux内核,PWM-GPIO驱动程序通过向用户空间提供了相应的接口来实现PWM信号的控制。开发人员可以通过打开相应的设备节点,并使用相应的系统调用函数来设置PWM的频率、占空比等参数,从而实现对GPIO引脚的PWM信号的控制。 驱动程序的核心部分是一个PWM子系统,它与GPIO子系统紧密集成。PWM子系统负责管理PWM信号的生成和控制,而GPIO子系统负责管理GPIO引脚的配置和操作。PWM-GPIO驱动程序在这两个子系统之间起着桥梁的作用。 PWM-GPIO驱动程序的实现方式与硬件平台相关,每个平台可能有不同的具体实现。在驱动程序的初始化过程,必须先配置GPIO引脚的功能为PWM模式,并将相应的寄存器映射到内核,以便能够通过对寄存器的操作来控制GPIO引脚。驱动程序还需要初始化PWM子系统,为每个GPIO引脚分配相应的PWM通道,并根据需求设置PWM的频率、占空比等参数。 通过PWM-GPIO驱动程序,开发人员可以方便地利用Linux内核的功能来实现对嵌入式系统GPIO引脚产生PWM信号的控制。这为开发PWM驱动、控制舵机、LED等应用提供了便捷的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值