gpio简介

GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。Linux内核中gpio是最简单,最常用的资源。驱动程序,应用程序都能够通过相应的接口使用gpio,gpio使用0~MAX之间的整数标识,不能使用负数,gpio与硬件体系密切相关的,不过linux有一个框架处理gpio,能够使用统一的接口来操作gpio。使用gpio接口需要包含头文件#include <linux/gpio.h>和#include <linux/of_gpio.h>,Documentation/gpio.txt文件有相关说明。

RK3288有9组GPIO bank:GPIO0~GPIO8,每组又以 A0~A7, B0~B7, C0~C7, D0~D7 作为编号区分(不是所有 bank 都有全部编号,例如 GPIO0 就只有A0~C7)。 所有的GPIO在上电后的初始状态都是输入模式,可以通过软件设为上拉或下拉,也可以设置为中断脚,驱动强度都是可编程的。 每个 GPIO 口除了通用输入输出功能外,还可能有其它复用功能。

Linux常用的gpio API定义如下:

#include <linux/gpio.h>
#include <linux/of_gpio.h> enum of_gpio_flags {OF_GPIO_ACTIVE_LOW = 0x1,
};  int of_get_named_gpio_flags(struct device_node *np, const char *propname,
int index, enum of_gpio_flags *flags);
int gpio_is_valid(int gpio);
int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned gpio);
int gpio_direction_input(int gpio);
int gpio_direction_output(int gpio, int value);
void gpio_set_value(unsigned int gpio, int value);
int gpio_get_value(unsigned gpio);
int gpio_to_irq(unsigned int gpio);
void free_irq(unsigned int irq, void *dev_id);

操作普通GPIO说明

(1)、在dts添加gpio的引用描述:在dts文件上添加,通常在设备树中以 类似以下的配置来表示gpio的配置使用,这里定义了一个pin脚作为一般的输出输入口,rk3288平台的GPIO0_B5。

led_ctrl {compatible = "rk3288, led_ctrl";status = "okay";gpio-en = <&gpio1 13 GPIO_ACTIVE_HIGH>; //GPIO0_B5
};

(2)、解析dts并且获取gpio口:函数返回值就得到gpio号。

int of_get_named_gpio_flags(struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags);

(3)、判断gpio口是否合法能用。

int gpio_is_valid(int number)

(4)、申请gpio口:gpio_request的第一个参数是需要申请的gpio号。第二个参数是我们给该gpio起个名字,申请成功后,可以通过/sys/kernel/debug/gpio文件查看到该GPIO的状态。

int gpio_request(unsigned gpio, const char *label)

(5)、设置gpio口的方向,如果是设置方向为输出的话同时设置电平拉高或拉低:

int gpio_direction_input(unsigned gpio); //设置gpio为输入int gpio_direction_output(unsigned gpio, int value); //设置gpio为输出,且设置电平

(6)、操作gpio口(拉高或者拉低gpio的电平,value为1是拉高,0是拉低):

void gpio_set_value(unsigned int gpio, int value);

(7)、获取gpio口的状态:get到1为高电平,得到0为低电平;

ret = gpio_get_value(unsigned gpio);

(8)、释放gpio口:在remove函数中添加对应的释放操作;

gpio_free(int number)

操作gpio API demo说明

1、dts里面的节点添加gpio的配置使用:

 leds {compatible = "rk3288, led";status = "okay";gpio_en = <&gpio4 11 GPIO_ACTIVE_HIGH>;};

2、然后再在驱动中probe函数解析,例如在这里的设备是leds,然后调用of_get_named_gpio_flags获取gpio口,然后调用gpio_direction_output接口设置gpio的电平。

 struct device_node *leds_node = pdev->dev.of_node;enum of_gpio_flags flags;gpio_en = of_get_named_gpio_flags(leds_node,"gpio-en", 0, &flags);pr_err("---[czd]--- gpio_en is %d --\n", gpio_en);if (!gpio_is_valid(gpio_en)) {pr_err("gpio_en: %d is invalid\n", gpio_en);return -ENODEV;}if (gpio_request(gpio_en, "gpio_en")) {pr_err("gpio_en: %d request failed!\n", gpio_en);gpio_free(gpio_en);return -ENODEV;}gpio_direction_output(gpio_en, 1); //这里设置GPIO的电平拉高

gpio用作中断脚说明

一、API函数:

1、这个函数的作用是转换gpio编号到对应irq号

static inline int gpio_to_irq(unsigned int gpio)
{return __gpio_to_irq(gpio);
}

2、中断注册函数

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev_id)

参数说明:
irq中断号。(和平台架构相关,结合datasheet以及平台文件) IRQ_EINT(x)
中断处理函数: 中断发生时,系统调用这个函数,dev_id参数将被传递给它
中断标记: IRQ_TYPE_EDGE_FALLING 上升或下降中断触发
中断名字:
dev_id 一般使用设备的设备结构体或者NULL
返回值:request_irq()返回0表示成功,返回-EINVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用,且不能被共享。

3、中断卸载函数:

void free_irq(unsigned int irq, void *dev_id)

4、中断服务函数:

irq_handler_t irq16_handler(int irq,void *dev_id)
二、举例说明

1、GPIO口的中断使用与GPIO的输入输出类似,首先在DTS文件中增加gpio的配置。

key_gpio_irq {compatible = "key_gpio_irq";irq-gpio = <&gpio4 24 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D0,这里配置上升沿触发中断 */
};

IRQ_TYPE_EDGE_RISING表示中断由上升沿触发,当该引脚接收到上升沿信号时可以触发中断函数。 这里还可以配置成如下:

IRQ_TYPE_NONE         //默认值,无定义中断触发类型
IRQ_TYPE_EDGE_RISING  //上升沿触发
IRQ_TYPE_EDGE_FALLING //下降沿触发
IRQ_TYPE_EDGE_BOTH    //上升沿和下降沿都触发
IRQ_TYPE_LEVEL_HIGH   //高电平触发
IRQ_TYPE_LEVEL_LOW    //低电平触发

然后在probe函数中对dts所添加的配置进行解析,再做中断的注册申请,代码如下:


static irqreturn_t leds_gpio_irq(int irq, void *dev_id) //中断函数
{ printk("Enter leds gpio irq test program!\n"); return IRQ_HANDLED;
}static int irq_gpio_probe(struct platform_device *pdev)
{   struct device_node *leds_node = pdev->dev.of_node;enum of_gpio_flags flags;int ret;irq-gpio = of_get_named_gpio_flags(leds_node,"irq-gpio", 0, &flags);pr_err("---[czd]--- irq-gpio is %d --\n", irq-gpio);if (!gpio_is_valid(irq-gpio)) {pr_err("irq-gpio: %d is invalid\n", irq-gpio);return -ENODEV;}if (gpio_request(irq-gpio, "irq-gpio")) { printk("gpio %d request failed!\n", irq-gpio); gpio_free(irq-gpio); return IRQ_NONE; } ret = gpio_direction_input(irq-gpio);if (ret < 0){pr_err("%s: set gpio direction input (%d) fail\n", __func__, wakeup_gpio);return ret;}irq-gpio_number = gpio_to_irq(irq-gpio); //转换gpio编号到对应irq号。 if (irq-gpio) { ret = request_irq(irq-gpio_number, leds_gpio_irq, flag, "key_gpio_irq", key-gpio); if (ret != 0) free_irq(irq-gpio, key-gpio); dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret); } return 0;
}

调用gpio_to_irq把GPIO的PIN值转换为相应的IRQ值,调用gpio_request申请占用该GPIO口,调用request_irq申请中断,如果失败要调用free_irq释放,该函数中irq-gpio_number是要申请的硬件中断号,leds_gpio_irq是中断处理函数,flag是中断处理的属性:例如要设置上升沿触发中断则使用IRQ_TYPE_EDGE_RISING,”key_gpio_irq”是设备驱动程序名称,key-gpio是该设备的device结构,在注册共享中断时会用到,如果不用到可以设为NULL。

补充说明:
1、如果不知道自己使用的GPIO是否用对了,可以使用万用表量一下GPIO电平是否是自己控制的状态(高或者低电平)或者使用以下命令查看一下GPIO的情况:
cat /sys/kernel/debug/gpio

2、查看一下GPIO的复用情况:
cat /d/pinctrl/pinctrl/pinmux-pins //不同平台可能会有差异,一般关键字是pinmux,可以使用find命令查找一下

Linux驱动编程操作GPIO的简要说明相关推荐

  1. Linux驱动编程 step-by-step (二) 简单字符设备驱动

    简单字符设备驱动 1.主次设备号 主设备号标识设备连接的的驱动,此设备好由内核使用,标识在相应驱动下得对应的设备 在linux中设备号是一个32位的dev_t类型 typedef __u32    _ ...

  2. Linux驱动编程 step-by-step (二)

    简单字符设备驱动 1.主次设备号 主设备号标识设备连接的的驱动,此设备好由内核使用,标识在相应驱动下得对应的设备 在linux中设备号是一个32位的dev_t类型 typedef __u32    _ ...

  3. Linux驱动编程 step-by-step

    第三次看了LDD3了(虽然现在已经是kernel3.0但从这本书商还是能学到很多) 每次都有一些收获 现在终于能够写一写代码了 驱动程序的作用: 简单来说 驱动程序就是使计算机与设备通信的特殊的代码, ...

  4. linux驱动编程——ch340x驱动移植

    Linux驱动编程--ch340x驱动移植 主要概念: ​ ch340x驱动移植 ​ 作为通用器件,厂商都有提供适配各种平台的驱动.linux一般会提供驱动源码. ​ 一般所谓驱动移植,就是将厂商的驱 ...

  5. 嵌入式学习笔记——使用寄存器编程操作GPIO

    使用寄存器编程操作GPIO 前言 GPIO相关的寄存器 GPIO 端口模式寄存器 (GPIOx_MODER) (x = A..I) 位操作 GPIO 端口输出类型寄存器 (GPIOx_OTYPER) ...

  6. Linux驱动编程视频教程

    本视频教程主要介绍字符驱动.杂项设备.中断.调试驱动的基本方法以及驱动的移植等. Linux驱动编程视频教程: 链接:https://pan.baidu.com/s/1Yn5d4w9uudb4tGDT ...

  7. Linux驱动编程(驱动程序基石)(上)

    一.休眠与唤醒 要休眠的线程,放在 wq 队列里,中断处理函数从 wq 队列里把它取出来唤醒.所以,我们要做这几件事: ① 初始化 wq 队列 ② 在驱动的 read 函数中,调用 wait_even ...

  8. Linux驱动编程 step-by-step (五)主要的文件操作方法实现

    主要的文件操作方法实现 文件操作函数有很多的操作接口,驱动编程需要实现这些接口,在用户编程时候系统调用时候会调用到这些操作 [cpp] view plaincopy struct file_opera ...

  9. linux驱动read函数 copytouser,Linux驱动编程 step-by-step (五)主要的文件操作方法实现...

    主要的文件操作方法实现 文件操作函数有很多的操作接口,驱动编程需要实现这些接口,在用户编程时候系统调用时候会调用到这些操作 structfile_operations { ... loff_t (*l ...

  10. 迅为4412开发板Linux驱动教程之GPIO的初始化

    视频下载地址:http://pan.baidu.com/s/1c06oiti GPIO的初始化 • 在内核源码目录下使用命令"ls drivers/gpio/*.o",可以看到&q ...

最新文章

  1. 800 名科学家联名主张废除 p 值!斯坦福教授直言,没有p值,期刊将充斥“无可辩驳的废话”!...
  2. db2不记录日志插入记录
  3. 黑白世界,感受不同的旅行...
  4. django mysql 一对多_请教,django中 如何向带有外键(一对多和多对多)数据库中批量插入数据?...
  5. 几个重要的Linux系统内核文件介绍
  6. 添加多浏览器支持是什么意思_周公解梦:梦见无缘无故多了一个儿子什么意思...
  7. Scale-Adaptive Neural Dense Features: Learning via Hierarchical Context Aggregation
  8. hnrxgs伸缩器在管道中的作用以及工作原理
  9. python大纲图_干货!!python自学大纲!
  10. 超长正整数的加法(酷勤网)
  11. 低碳环保+变废为宝=马铃薯淀粉生产废水处理设备
  12. Python初学问题-input输入、while循环、函数
  13. 各种浏览器的内核是什么
  14. LearnGL - 11.1 - 实现简单的Gouraud光照模型 dot 点积/点乘的作用
  15. c#的传输组件dotnetty
  16. python web
  17. 单招计算机英语面试口语,面试单招英语自我介绍
  18. Undefined symbols for architecture i386: _OBJC_CLASS_$_AVOSCloud, referenced from:
  19. 后台管理界面-- 登录设计
  20. JVM 双亲委派模型

热门文章

  1. iOS 开发中常见的设计模式
  2. 命令行解决mysql中文乱码
  3. IBM的ITIL管理解决方案
  4. python验证码识别——前处理
  5. Pycharm如何调整代码颜色以及字体样式
  6. 【ACL'21】弱标签的垃圾数据,也能变废为宝!
  7. 刘知远老师为你解读:自然语言理解到底难在哪儿?
  8. 【推荐系统】推荐系统研究中常用的评价指标
  9. 数据预处理—8.属性归约之主成分分析(理论及python实现)
  10. 2.4 sklearn中的metrics.roc_auc_score评价指标