返回顶部
首页 > 资讯 > 精选 >怎么进行rk3288 GPIO的使用
  • 506
分享到

怎么进行rk3288 GPIO的使用

2023-06-05 18:06:25 506人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关怎么进行rk3288 GPio的使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。GPIO 使用 简介 GPIO, 全称 General-Pu

这篇文章将为大家详细讲解有关怎么进行rk3288 GPio的使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

GPIO 使用 

简介 

GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。 RK3288 有 9 组 GPIO bank: GPIO0,GPIO1, …, GPIO8。每组又以 A0~A7, B0~B7, C0~C7, D0~D7 作为编号区分(不是所有 bank 都有全部编号,例如 GPIO5 就只有 B0~B7, C0~C3)。

每个 GPIO 口除了通用输入输出功能外,还可能有其它复用功能,例如 GPIO5_B4,可以复用成以下功能之一:

  • spi0_clk

  • ts0_data4

  • uart4exp_ctsn

每个 GPIO 口的驱动电流、上下拉和重置后的初始状态都不尽相同,详细情况请参考《RK3288 规格书》中的 “RK3288 function IO description” 一章。

RK3288 的 GPIO 驱动是在以下 pinctrl 文件中实现的:

kernel/drivers/pinctrl/pinctrl-rockchip.c

其核心是填充 GPIO bank 的方法和参数,并调用 gpiochip_add 注册到内核中。

使用 

sunychip-rk3288开发板有两个电源 LED 灯是 GPIO 口控制的,分别是: 怎么进行rk3288 GPIO的使用

从电路图上看,GPIO 口输出低电平时灯亮,高电平时灯灭。 另外,扩展槽上引出了几个空闲的 GPIO 口,分别是:

怎么进行rk3288 GPIO的使用

这几个 GPIO 口可以自定义作输入、输出使用。

输入输出 

下面以电源 LED 灯的驱动为例,讲述如何在内核编写代码控制 GPIO 口的输出。 首先需要在 dts (Device Tree) 文件 firefly-rk3288.dts 中增加驱动的资源描述:

firefly-led{    compatible = "firefly,led";    led-work = <&gpio8 GPIO_A2 GPIO_ACTIVE_LOW>;    led-power = <&gpio8 GPIO_A1 GPIO_ACTIVE_LOW>;    status = "okay";};

这里定义了两颗 LED 灯的 GPIO 设置:

led-work  GPIO8_A2  GPIO_ACTIVE_LOWled-power GPIO8_A1  GPIO_ACTIVE_LOW

GPIO_ACTIVE_LOW 表示低电平有效(灯亮),如果是高电平有效,需要替换为 GPIO_ACTIVE_HIGH 。 之后在驱动程序中加入对 GPIO 口的申请和控制则可:

#ifdef  CONFIG_OF#include <linux/of.h>#include <linux/of_gpio.h>#endif static int firefly_led_probe(struct platfORM_device *pdev){    int ret = -1;int gpio, flag;    struct device_node *led_node = pdev->dev.of_node;       gpio = of_get_named_gpio_flags(led_node, "led-power", 0, &flag);    if (!gpio_is_valid(gpio)){        printk("invalid led-power: %d\n",gpio);        return -1;    }     if (gpio_request(gpio, "led_power")) {        printk("gpio %d request failed!\n",gpio);        return ret;    }    led_info.power_gpio = gpio;    led_info.power_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0 : 1;    gpio_direction_output(led_info.power_gpio, !(led_info.power_enable_value));    ...    on_error:gpio_free(gpio);}

of_get_named_gpio_flags 从设备树中读取 led-power 的 GPIO 配置编号和标志,gpio_is_valid 判断该 GPIO 编号是否有效,gpio_request 则申请占用该 GPIO。如果初始化过程出错,需要调用 gpio_free 来释放之前申请过且成功的 GPIO 。 调用 gpio_direction_output 就可以设置输出高还是低电平,因为是 GPIO_ACTIVE_LOW ,如果要灯亮,需要写入 0 。 实际中如果要读出 GPIO,需要先设置成输入模式,然后再读取值:

int val;gpio_direction_input(your_gpio);val = gpio_get_value(your_gpio);

下面是常用的 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 v)

复用 

如何定义 GPIO 有哪些功能可以复用,在运行时又如何切换功能呢?以 I2C4 为例作简单的介绍。 查规格表可知,I2C4_SDA 与 I2C4_SCL 的功能定义如下: 怎么进行rk3288 GPIO的使用

在 /kernel/arch/arm/boot/dts/rk3288.dtsi 里有:

i2c4: i2c@ff160000 {    compatible = "rockchip,rk30-i2c";    reg = <0xff160000 0x1000>;    interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;    #address-cells = <1>;    #size-cells = <0>;    pinctrl-names = "default", "gpio";    pinctrl-0 = <&i2c4_sda &i2c4_scl>;    pinctrl-1 = <&i2c4_gpio>;    gpiOS = <&gpio7 GPIO_C1 GPIO_ACTIVE_LOW>, <&gpio7 GPIO_C2 GPIO_ACTIVE_LOW>;    clocks = <&clk_gates6 15>;    rockchip,check-idle = <1>;    status = "disabled";};
  • 此处,跟复用控制相关的是 pinctrl- 开头的属性:

    • pinctrl-names 定义了状态名称列表: default (i2c 功能) 和 gpio 两种状态。

    • pinctrl-0 定义了状态 0 (即 default)时需要设置的 pinctrl: i2c4_sda 和 i2c4_scl

    • pinctrl-1 定义了状态 1 (即 gpio)时需要设置的 pinctrl: i2c4_gpio

这些 pinctrl 在 /kernel/arch/arm/boot/dts/rk3288-pinctrl.dtsi 中定义:

/ {     pinctrl: pinctrl@ff770000 {        compatible = "rockchip,rk3288-pinctrl";        ...             gpio7_i2c4 {            i2c4_sda:i2c4-sda {                rockchip,pins = <I2C4TP_SDA>;                rockchip,pull = <VALUE_PULL_DISABLE>;                rockchip,drive = <VALUE_DRV_DEFAULT>;                //rockchip,tristate = <VALUE_TRI_DEFAULT>;            };            i2c4_scl:i2c4-scl {                rockchip,pins = <I2C4TP_SCL>;                rockchip,pull = <VALUE_PULL_DISABLE>;                rockchip,drive = <VALUE_DRV_DEFAULT>;                //rockchip,tristate = <VALUE_TRI_DEFAULT>;            };            i2c4_gpio: i2c4-gpio {                rockchip,pins = <FUNC_TO_GPIO(I2C4TP_SDA)>, <FUNC_TO_GPIO(I2C4TP_SCL)>;                rockchip,drive = <VALUE_DRV_DEFAULT>;            };        };        ...    }  }

I2C4TP_SDA, I2C4TP_SCL 的定义在 /kernel/arch/arm/boot/dts/include/dt-bindings/pinctrl/rockchip-rk3288.h 中:

#define GPIO7_C1 0x7c10#define I2C4TP_SDA 0x7c11 #define GPIO7_C2 0x7c20#define I2C4TP_SCL 0x7c21

FUN_TO_GPIO 的定义在 /kernel/arch/arm/boot/dts/include/dt-bindings/pinctrl/rockchip.h 中:

#define FUNC_TO_GPIO(m)     ((m) & 0xfff0)

也就是说 FUNC_TO_GPIO(I2C4TP_SDA) == GPIO7_C1, FUNC_TO_GPIO(I2C4TP_SCL) == GPIO7_C2 。 像 0x7c11 这样的值是有编码规则的:

7 c1 1| |  `- func| `---- offset`------ bank0x7c11 就表示 GPIO7_C1 func1, 即 i2c4tp_sda 。

在复用时,如果选择了 “default” (即 i2c 功能),系统会应用 i2c4_sda 和 i2c4_scl 这两个 pinctrl,最终得将 GPIO7_C1 和 GPIO7_C2 两个针脚切换成对应的 i2c 功能;而如果选择了 “gpio” ,系统会应用 i2c4_gpio 这个 pinctrl,将 GPIO7_C1 和 GPIO7_C2 两个针脚还原为 GPIO 功能。

我们看看 i2c 的驱动程序 /kernel/drivers/i2c/busses/i2c-rockchip.c 是如何切换复用功能的:

static int rockchip_i2c_probe(struct platform_device *pdev){    struct rockchip_i2c *i2c = NULL;    struct resource *res;    struct device_node *np = pdev->dev.of_node;    int ret;    // ...    i2c->sda_gpio = of_get_gpio(np, 0);    if (!gpio_is_valid(i2c->sda_gpio)) {        dev_err(&pdev->dev, "sda gpio is invalid\n");        return -EINVAL;    }    ret = devm_gpio_request(&pdev->dev, i2c->sda_gpio, dev_name(&i2c->adap.dev));    if (ret) {        dev_err(&pdev->dev, "failed to request sda gpio\n");        return ret;    }    i2c->scl_gpio = of_get_gpio(np, 1);    if (!gpio_is_valid(i2c->scl_gpio)) {        dev_err(&pdev->dev, "scl gpio is invalid\n");        return -EINVAL;    }    ret = devm_gpio_request(&pdev->dev, i2c->scl_gpio, dev_name(&i2c->adap.dev));    if (ret) {        dev_err(&pdev->dev, "failed to request scl gpio\n");        return ret;    }    i2c->gpio_state = pinctrl_lookup_state(i2c->dev->pins->p, "gpio");    if (IS_ERR(i2c->gpio_state)) {        dev_err(&pdev->dev, "no gpio pinctrl state\n");        return PTR_ERR(i2c->gpio_state);    }    pinctrl_select_state(i2c->dev->pins->p, i2c->gpio_state);    gpio_direction_input(i2c->sda_gpio);    gpio_direction_input(i2c->scl_gpio);    pinctrl_select_state(i2c->dev->pins->p, i2c->dev->pins->default_state);    // ...}

首先是调用 of_get_gpio 取出设备树中 i2c4 结点的 gpios 属于所定义的两个 gpio:

gpios = <&gpio7 GPIO_C1 GPIO_ACTIVE_LOW>, <&gpio7 GPIO_C2 GPIO_ACTIVE_LOW>;

然后是调用 devm_gpio_request 来申请 gpio,接着是调用 pinctrl_lookup_state 来查找 “gpio” 状态,而默认状态 “default” 已经由框架保存到 i2c->dev-pins->default_state 中了。最后调用 pinctrl_select_state 来选择是 “default” 还是 “gpio” 功能。 下面是常用的复用 API 定义:

#include <linux/pinctrl/consumer.h> struct device {    //...    #ifdef     CONFIG_PINCTRLstruct dev_pin_info    *pins;    #endif    //...};struct dev_pin_info {    struct pinctrl *p;    struct pinctrl_state *default_state;    #ifdef CONFIG_PMstruct pinctrl_state *sleep_state;    struct pinctrl_state *idle_state;    #endif};struct pinctrl_state * pinctrl_lookup_state(struct pinctrl *p, const char *name);int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);

关于怎么进行rk3288 GPIO的使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: 怎么进行rk3288 GPIO的使用

本文链接: https://lsjlt.com/news/244126.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么进行rk3288 GPIO的使用
    这篇文章将为大家详细讲解有关怎么进行rk3288 GPIO的使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。GPIO 使用 简介 GPIO, 全称 General-Pu...
    99+
    2023-06-05
  • RK3399 /RK3288 ADB使用是怎样的
    RK3399 /RK3288 ADB使用是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。RK3399 /RK3288 ADB使用Linux安装adb1. &...
    99+
    2023-06-05
  • 怎么使用C语言操作树莓派GPIO
    这篇文章主要介绍了怎么使用C语言操作树莓派GPIO,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。第一步安装GPIO库。cd /tmpwget https:...
    99+
    2023-06-15
  • Linux内核gpio的具体使用用法是什么
    这篇文章主要为大家分析了Linux内核gpio的具体使用用法是什么的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“Linux内核gpio的具体使用用法是什么”...
    99+
    2023-06-28
  • 怎么进行Spring-Retry的使用
    怎么进行Spring-Retry的使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1 Spring-Retry的简介在日常的一些场景中, 很多需要进行重试的操作.而spr...
    99+
    2023-06-25
  • 怎样进行SoapUI的进阶使用
    这期内容当中小编将会给大家带来有关怎样进行SoapUI的进阶使用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。关于SoapUI的简单使用,大家可以参考网上并自己摸索下,这里就不说了,下面说的是一些不常见的...
    99+
    2023-06-17
  • 怎么理解树莓派的GPIO编程
    本篇文章为大家展示了怎么理解树莓派的GPIO编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。树莓派除了提供常见的网口和USB接口 ,还提供了一组GPIO(General Purpose Input...
    99+
    2023-06-05
  • 怎么使用Hybris的customer coupon进行promotion
    这篇文章主要介绍“怎么使用Hybris的customer coupon进行promotion”,在日常操作中,相信很多人在怎么使用Hybris的customer coupon进行promotion问题上存在疑惑,小编查阅了各式资料,整理出简...
    99+
    2023-06-04
  • 怎么使用FrameLayout进行布局
    今天就跟大家聊聊有关怎么使用FrameLayout进行布局,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。在FrameLayout中,这个布局直接在屏幕上开辟出一块空白的区域,所有添加...
    99+
    2023-06-08
  • 怎么使用Python进行下载
    本篇内容介绍了“怎么使用Python进行下载”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.使用requests你可以使用requests...
    99+
    2023-06-15
  • 怎么使用VIM进行画图
    小编给大家分享一下怎么使用VIM进行画图,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Vim 是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便...
    99+
    2023-06-28
  • 使用Kotlin怎么进行编程
    今天就跟大家聊聊有关使用Kotlin怎么进行编程,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Kotlin 基本语法先说个学习Kotlin语法的小窍门,将代码用Java写好,然后Co...
    99+
    2023-05-31
    kotlin
  • 怎么使用Mongodb进行分析
    要使用Mongodb进行分析,需要按照以下步骤进行操作:1. 安装Mongodb数据库:首先,需要安装Mongodb数据库,并将其设...
    99+
    2023-08-23
    Mongodb
  • Webpack怎么使用命令行进行安装
    这篇文章主要介绍了Webpack怎么使用命令行进行安装的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Webpack怎么使用命令行进行安装文章都会有所收获,下面我们一起来看看吧。...
    99+
    2024-04-02
  • 怎么进行MySQL INSERT IGNORE语句的使用
    怎么进行MySQL INSERT IGNORE语句的使用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所...
    99+
    2024-04-02
  • 怎么进行Linux中patch文件的使用
    怎么进行Linux中patch文件的使用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。diff的功能就是用来比较两个文件的不同,然后记录下来,也就是所谓的diff补丁,patc...
    99+
    2023-06-28
  • 怎么进行Spark NLP使用入门
    怎么进行Spark NLP使用入门,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。AI在企业中的应用关于AI在企业中应用的年度O‘Reilly报告已经在2019年2月发布, 该报...
    99+
    2023-06-19
  • Android怎么使用GRPC进行通信
    这篇文章主要介绍“Android怎么使用GRPC进行通信”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android怎么使用GRPC进行通信”文章能帮助大家解决问题。引言Android作为一个开发平...
    99+
    2023-07-05
  • MySQL怎么使用Python进行连接
    一、表格与键概念主键:可唯一表示该资料(可以设置多个列表为主键)设置外键进行表与表的相连,且外键必须是其他表的主键(外键也可以设置自己表格的主键)二、创建资料库CREATE DATABASE `sql_tutorial`; --创建资...
    99+
    2023-05-14
    Python MySQL
  • Python怎么使用Spacy进行分词
    这篇文章主要介绍“Python怎么使用Spacy进行分词”,在日常操作中,相信很多人在Python怎么使用Spacy进行分词问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python怎么使用Spacy进行分词...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作