[驱动程序] 内核GPIO相关函数

一、通用gpio的申请和释放

#include <linux/gpio.h> //linux自带的
#include <cfg_type.h> //芯片厂商提供的
或#include <mach/platform.h> //该头文件也包含#include <cfg_type.h>

1.单个GPIO的申请和释放

int gpio_request(unsigned gpio, const char *label);

参数:
gpio,引脚的编号,依赖于芯片厂商提供的源代码,没有唯一的。
返回值:成功,0;失败,错误码(<0)

void gpio_free(unsigned gpio);

2.配置GPIO为输出模式和输入模式

int gpio_direction_output(unsigned gpio, int value);

参数:
gpio,引脚的编号
value,1 输出高电平;0 输出低电平
返回值:成功,0;失败,错误码

int gpio_direction_input(unsigned gpio);

参数:
gpio,引脚的编号
返回值:成功,0;失败,错误码

3.设置GPIO的输出值和输入值

void gpio_set_value(unsigned gpio, int value);

参数:
gpio,引脚的编号
value,1 输出高电平;0 输出低电平

int gpio_get_value(unsigned gpio);

参数:
gpio,引脚的编号
返回值:引脚的电平。1,高电平;0,低电平

4.申请一组gpio和释放一组gpio

int gpio_request_array(struct gpio *array, size_t num);

参数:
array,gpio结构体数组
num,申请多少个gpio
返回值:成功,0;失败,错误码

void gpio_free_array(struct gpio *array, size_t num);

参数:
array,gpio结构体数组
num,释放多少个gpio
返回值:无

5.gpio结构体

struct gpio {
    unsigned gpio; //GPIO编号
    unsigned long flags; //指定GPIO配置
    const char *label; //自定义GPIO描述
};

flags可以选定如下,详见在gpio.txt中

//配置为输入模式
GPIOF_DIR_IN - to configure direction as input

//配置为输出模式
GPIOF_DIR_OUT - to configure direction as output

//以下的的GPIOF_INIT_LOW与GPIOF_INIT_HIGH 只有配置为输出模式后才能生效
GPIOF_INIT_LOW - as output, set initial level to LOW
GPIOF_INIT_HIGH - as output, set initial level to HIGH

//配置为开漏模式
GPIOF_OPEN_DRAIN - gpio pin is open drain type.

//配置为开源模式
GPIOF_OPEN_SOURCE - gpio pin is open source type.

//配置为输出模式且默认输出电平值为低电平
GPIOF_OUT_INIT_LOW - configured as output, initial level LOW

//配置为输出模式且默认输出电平值为高电平
GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH

例子:

static struct gpio leds_gpios[] = {
    { PAD_GPIO_E+13, GPIOF_OUT_INIT_HIGH, "LED D7" }, /* default to OFF /
    { PAD_GPIO_C+17, GPIOF_OUT_INIT_HIGH, "LED D8" }, / default to OFF /
    { PAD_GPIO_C+8, GPIOF_OUT_INIT_HIGH, "LED D9" }, / default to OFF /
    { PAD_GPIO_C+7, GPIOF_OUT_INIT_HIGH, "LED D10" }, / default to OFF */
};
//申请gpio引脚
gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
//释放系统占用的引脚资源
gpio_free_array(leds_gpios,ARRAY_SIZE(leds_gpios));

二、gpiod的申请

新的kernel版本都推荐使用gpiod开头的接口,因为gpiod开头的接口传进去的是gpio_desc结构体,方便做资源管理,使用 gpiod 的好处是我们申请后不进行 free 也没有什么问题;传统的gpio接口传进去的是GPIO number,需要手动释放资源,不好做资源管理。

1.获取 gpio 描述符和释放

使用一下两个函数获取 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_descs *gpiod_get_array(struct device *dev,
                       const char *con_id,
                       enum gpiod_flags flags)
释放:
void gpiod_put(struct gpio_desc *desc)
void gpiod_put_array(struct gpio_descs *descs)
或者
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,
                    enum gpiod_flags flags)
 
struct gpio_desc *devm_gpiod_get_index(struct device *dev,
                      const char *con_id, unsigned int idx,
                      enum gpiod_flags flags)

区别是devm它在设备的生命周期内自动管理 GPIO 资源的分配和释放

2.设置和获取 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)

3.设备和读取 GPIO 口电平

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

4.实例

struct swgpiocontrol_desc{
    struct gpio_desc *led_desc;// 开机指示灯
    struct gpio_desc *amp_mute_desc;// 音频功放使能,高电平打开
    struct gpio_desc *wake_desc;// D3输入脚, csk唤醒d3, csk升级时候需要配置为输出,下拉
}

struct swgpiocontrol_desc *swgpiocontrol_dev;

static int swcskcontrol_probe(struct platform_device *pdev) {

    struct device_node *node = pdev->dev.of_node;
    struct device *dev = &pdev->dev;

    swgpiocontrol_dev->led_desc = devm_gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
    if (IS_ERR(swgpiocontrol_dev->wake_desc)) {
    pr_err("register gpio wake: %p, err: %d\n", swgpiocontrol_dev->wake_desc,
        IS_ERR(swgpiocontrol_dev->wake_desc));
    return -1;
    }
    
    //音频功放使能
    swgpiocontrol_dev->amp_mute_desc = devm_gpiod_get_index(dev,
 "amp_mute", 0, GPIOD_OUT_HIGH);
    if (IS_ERR(swgpiocontrol_dev->amp_mute_desc)) {
    pr_err("register gpio amp_mute: %p, err: %d\n", swgpiocontrol_dev->amp_mute_desc,
        IS_ERR(swgpiocontrol_dev->amp_mute_desc));
    return -1;
    }

    swgpiocontrol_dev->wake_desc = devm_gpiod_get_index(dev,
 "wake", 0, GPIOD_IN);
    if (IS_ERR(swgpiocontrol_dev->wake_desc)) {
    pr_err("register gpio wake: %p, err: %d\n", swgpiocontrol_dev->wake_desc,
        IS_ERR(swgpiocontrol_dev->wake_desc));
    return -1;
    }
}

    //设置内部上拉
    gpiod_set_pull(swgpiocontrol_dev->led_desc, GPIOD_PULL_UP);
                                                                                                                                                                                                  
    //输出低电平
    gpiod_direction_output(swgpiocontrol_dev->wake_desc, 0);

    //输入模式
    gpiod_direction_input(swgpiocontrol_dev->wake_desc);

    //设置低电平
    gpiod_set_value(swgpiocontrol_dev->amp_mute_desc, 0);

    //设置高电平
    gpiod_set_value(swgpiocontrol_dev->amp_mute_desc, 1);

拓展:第1点和第2点相结合

devm_gpio_request_one();
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值