GPIO子系统

来源:互联网 发布:8月编程语言排行榜 编辑:程序博客网 时间:2024/09/21 09:19

GPIO相关的内核参考文档为Documentation/gpio.txt

GPIO相应的API

标准GPIO API

这些API的头文件定义于include/linux/gpio.h中,实际位于include/asm-generic/gpio.h中

bool gpio_is_valid(int number);int gpio_request(unsigned gpio, const char *label);void gpio_free(unsigned gpio);int gpio_direction_input(unsigned gpio);int gpio_direction_output(unsigned gpio, int value);int __gpio_get_value(unsigned gpio);void __gpio_set_value(unsigned gpio, int value);int gpio_export(unsigned gpio, bool direction_may_change);void gpio_unexport(unsigned gpio);int __gpio_cansleep(unsigned gpio);int gpio_get_value_cansleep(unsigned gpio);void gpio_set_value_cansleep(unsigned gpio, int value);int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);int gpio_request_array(const struct gpio *array, size_t num);void gpio_free_array(const struct gpio *array, size_t num);

中断部分的API

中断函数的原型实现在kernel/irq目录下

int __gpio_to_irq(unsigned gpio);int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);void free_irq(unsigned int irq, void *dev_id);int irq_set_irq_type(unsigned int irq, unsigned int type);void enable_irq(unsigned int irq);void disable_irq(unsigned int irq);int __disable_irq_nosync(unsigned int irq);

使用GPIO步骤

  1. include header
    #include <linux/gpio.h>
  2. check valid (optional)
    每一个chip上的gpio数量是有限制的(而且gpio号码一定>=0),为了防止指定的gpio号码是错的,可以先使用gpio_is_valid来检查。
    int gpio_is_valid(int number);//return true if valid.
  3. request gpio (optional, but recommended)
    gpio_request可以检查gpio number是否超出范围或小于0及指定的gpio是否正在使用,因为有时候别的地方也控制着同一个gpio可能会发生预期外的结果。

    /*** return -EINVAL if GPIO is not valid(same as gpio_is_valid)* return -EBUSY if GPIO is already used* return 0 if GPIO is fine to use* 因此我們只要檢查回傳質是否>=0就可以判斷是否可用。* 第一個參數是填入GPIO的號碼、第二個參數是想要對這個GPIO的命名。* $ cat /sys/kernel/debug/gpio就可以看到 */int gpio_request(unsigned gpio, const char *label);
  4. configure gpio

    /* set as input or output, returning 0 or negative errno */int gpio_direction_input(unsigned gpio);int gpio_direction_output(unsigned gpio, int value);
  5. access gpio

     /* GPIO INPUT:  return zero or nonzero */int gpio_get_value(unsigned gpio);/* GPIO OUTPUT */void gpio_set_value(unsigned gpio, int value);
  6. free gpio
    当使用完GPIO之后利用gpio_free来释放GPIO
    int gpio_free(unsigned gpio);


GPIO源码架构分析

gpio相应的API其实调用的是注册的struct gpio_chip中的一些方法,来看下struct gpio_chip这个结构体,

struct gpio_chip {        const char              *label;        struct device           *dev;        struct module           *owner;        struct list_head        list;        int                     (*request)(struct gpio_chip *chip, unsigned offset);        void                    (*free)(struct gpio_chip *chip, unsigned offset);        int                     (*get_direction)(struct gpio_chip *chip, unsigned offset);        int                     (*direction_input)(struct gpio_chip *chip, unsigned offset);        int                     (*get)(struct gpio_chip *chip, unsigned offset);        int                     (*direction_output)(struct gpio_chip *chip, unsigned offset, int value);        int                     (*set_debounce)(struct gpio_chip *chip, unsigned offset, unsigned debounce);        void                    (*set)(struct gpio_chip *chip, unsigned offset, int value);        int                     (*to_irq)(struct gpio_chip *chip, unsigned offset);        void                    (*dbg_show)(struct seq_file *s, struct gpio_chip *chip);        int                     base;        u16                     ngpio;        struct gpio_desc        *desc;        const char              *const *names;        unsigned                can_sleep:1;        unsigned                exported:1;

所以要使用gpio相应的API,必须事先注册一个struct gpio_chip结构体,并实现其中的方法,如下是一个例子,

static struct gpio_chip template_chip = {        .label                  = "wm8994",        .owner                  = THIS_MODULE,        .request                = wm8994_gpio_request,        .direction_input        = wm8994_gpio_direction_in,        .get                    = wm8994_gpio_get,        .direction_output       = wm8994_gpio_direction_out,        .set                    = wm8994_gpio_set,        .to_irq                 = wm8994_gpio_to_irq,        .dbg_show               = wm8994_gpio_dbg_show,        .can_sleep              = 1,};

另外需要说明一点是在struct gpio_chip结构体的这些函数中,既可以直接去操作gpio相应的寄存器,也可以通过i2c等接口去操作gpio,也可以调用pinctrl中提供的一些操作gpio的方法,总之,这个结构体的这些函数必须实现能够操作gpio。

0 3
原创粉丝点击