[ROC-RK3568-PC] [Firefly-Android] 10min带你了解普通GPIO的使用

Posted Neutionwei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ROC-RK3568-PC] [Firefly-Android] 10min带你了解普通GPIO的使用相关的知识,希望对你有一定的参考价值。

🍇 博主主页:Systemcall小酒屋
🍇 博主简介:Neutionwei,C站嵌入式领域新星创作者之一,一枚热爱开源技术、喜欢分享技术心得的极客,注重简约风格,热衷于用简单的案例讲述复杂的技术,“假传万卷书,真传一案例”,这是厦大一位教数学的院士说过的一句话,另外“成就是最好的老师”,技术既要沉淀,也得分享,成就感的正反馈是支持我持续耕耘的动力!
🍇 专栏目录:Firefly-RK356x板卡
🍇 专栏说明:本专栏主要基于Firefly旗下的RK356x板卡进行入门篇讲述,欢迎订阅,博主会持续更新!

文章目录

一、GPIO介绍

GPIO,全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。 所有的 GPIO 在上电后的初始状态都是输入模式,可以通过软件设为上拉或下拉,也可以设置为中断脚,驱动强度都是可编程的,其核心是填充 GPIO bank 的方法和参数,并调用 gpiochip_add 注册到内核中。

本文以 GPIO0_B4GPIO4_D5 这两个 GPIO 口为例写了一份简单操作 GPIO 口的驱动,在 SDK 的路径为:kernel/drivers/gpio/gpio-firefly.c,以下就以该驱动为例介绍 GPIO 的操作。

二、GPIO引脚计算

ROC-RK3568-PC 有 5 组 GPIO bank:GPIO0~GPIO4,每组又以 A0-A7B0-B7C0-C7D0-D7 作为编号区分,常用以下公式计算引脚:

  • GPIO 引脚计算公式:pin = bank * 32 + number
  • GPIO 小组编号计算公式:number = group * 8 + X

下面演示GPIO4_D5 引脚计算方法:

bank = 4;       // GPIO4_D5 => 4, bank ∈ [0,4]
group = 3;      // GPIO4_D5 => 3, group ∈ (A=0), (B=1), (C=2), (D=3)
X = 5;          // GPIO4_D5 => 5, X ∈ [0,7]

number = group * 8 + X = 3 * 8 + 5 = 29
pin = bank * 32 + number = 4 * 32 + 29 = 157;

GPIO4_D5 对应的设备树属性描述为:<&gpio4 29 IRQ_TYPE_EDGE_RISING>,由kernel/include/dt-bindings/pinctrl/rockchip.h的宏定义可知,也可以将GPIO4_D5描述为<&gpio4 RK_PD5 IRQ_TYPE_EDGE_RISING>

kernel/include/dt-bindings/pinctrl/rockchip.h内容如下:

#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_H__                                                                                            
#define __DT_BINDINGS_ROCKCHIP_PINCTRL_H__                                                                                            
                                                                                                                                      
#define RK_GPIO0    0                                                                                                                 
#define RK_GPIO1    1                                                                                                                 
#define RK_GPIO2    2                                                                                                                 
#define RK_GPIO3    3                                                                                                                 
#define RK_GPIO4    4                                                                                                                 
#define RK_GPIO6    6                                                                                                                 
                                                                                                                                      
#define RK_PA0      0                                                                                                                 
#define RK_PA1      1                                                                                                                 
#define RK_PA2      2                                                                                                                 
#define RK_PA3      3                                                                                                                 
#define RK_PA4      4                                                                                                                 
#define RK_PA5      5                                                                                                                 
#define RK_PA6      6                                                                                                                 
#define RK_PA7      7                                                                                                                 
#define RK_PB0      8                                                                                                                 
#define RK_PB1      9                                                                                                                 
#define RK_PB2      10                                                                                                                
#define RK_PB3      11                                                                                                                
#define RK_PB4      12                                                                                                                
#define RK_PB5      13                                                                                                                
#define RK_PB6      14                                                                                                                
#define RK_PB7      15                                                                                                                
#define RK_PC0      16                                                                                                                
#define RK_PC1      17                                                                                                                
#define RK_PC2      18                                                                                                                
#define RK_PC3      19                                                                                                                
#define RK_PC4      20                                                                                                                
#define RK_PC5      21                                                                                                                
#define RK_PC6      22                                                                                                                
#define RK_PC7      23                                                                                                                
#define RK_PD0      24                                                                                                                
#define RK_PD1      25                                                                                                                
#define RK_PD2      26                                                                                                                
#define RK_PD3      27                                                                                                                
#define RK_PD4      28                                                                                                                
#define RK_PD5      29                                                                                                                
#define RK_PD6      30                                                                                                                
#define RK_PD7      31                                                                                                                
                                                                                                                                      
#define RK_FUNC_GPIO    0                                                                                                             
#define RK_FUNC_1   1                                                                                                                 
#define RK_FUNC_2   2                                                                                                                 
#define RK_FUNC_3   3                                                                                                                 
#define RK_FUNC_4   4                                                                                                                 
#define RK_FUNC_5   5                                                                                                                 
#define RK_FUNC_6   6                                                                                                                 
#define RK_FUNC_7   7                                                                                                                 
                                                                                                                                      
#endif   

GPIO4_D5引脚没有被其它外设复用时, 我们可以通过export导出该引脚去使用:

:/ # ls /sys/class/gpio/
export     gpiochip128  gpiochip32   gpiochip64  unexport
gpiochip0  gpiochip255  gpiochip500  gpiochip96
:/ # echo 157 > /sys/class/gpio/export

导出后可看到gpio157

:/ # ls /sys/class/gpio/
export   gpiochip0    gpiochip255  gpiochip500  gpiochip96
gpio157  gpiochip128  gpiochip32   gpiochip64   unexport
:/ # ls /sys/class/gpio/gpio157
active_low  device  direction  edge  power  subsystem  uevent  value
:/ # cat /sys/class/gpio/gpio157/direction
in
:/ # cat /sys/class/gpio/gpio157/value
0

三、普通GPIO配置

首先在kernel/arch/arm64/boot/dts/rockchip/rk356x-firefly-demo.dtsi中增加驱动的资源描述:

gpio_demo: gpio_demo 
            	status = "okay";
            	compatible = "firefly,rk356x-gpio";
            	firefly-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;          /* GPIO0_B4 */
            	//firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */
            ;

配置含义如下:

  • firefly-gpio配置为GPIO0_B4GPIO_ACTIVE_HIGH表示高电平有效

如果配置为低电平有效则为GPIO_ACTIVE_LOW

然后在 probe 函数中对 DTS 所添加的资源进行解析,代码如下:

static int firefly_gpio_probe(struct platform_device *pdev)

	int ret;
    int gpio;
    enum of_gpio_flags flag;
	struct firefly_gpio_info *gpio_info;
    struct device_node *firefly_gpio_node = pdev->dev.of_node;

	printk("Firefly GPIO Test Program Probe\\n");
   	gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct firefly_gpio_info *), GFP_KERNEL);
   	if (!gpio_info) 
        return -ENOMEM;
    
	gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio", 0, &flag); // 从设备树中读取 firefly-gpio 和 firefly-irq-gpio 的 GPIO 配置编号和标志
	if (!gpio_is_valid(gpio))  // 判断该 GPIO 编号是否有效
    	printk("firefly-gpio: %d is invalid\\n", gpio); return -ENODEV;
    
	if (gpio_request(gpio, "firefly-gpio"))  // 申请占用该 GPIO
        printk("gpio %d request failed!\\n", gpio);
        gpio_free(gpio); // 释放之前申请过且成功的 GPIO 
        return -ENODEV;
     
	gpio_info->firefly_gpio = gpio;
    gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
   	gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);
    printk("Firefly gpio putout\\n");
    ...

在驱动中调用 gpio_direction_output 就可以设置输出高还是低电平,这里默认输出从 DTS 获取得到的有效电平 GPIO_ACTIVE_HIGH,如果驱动正常工作,可以用万用表测得对应的引脚应该为高电平。如果要读出 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);

以上是关于[ROC-RK3568-PC] [Firefly-Android] 10min带你了解普通GPIO的使用的主要内容,如果未能解决你的问题,请参考以下文章

[ROC-RK3568-PC] Kernel配置支持docker或者k8s

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解ADC的使用

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解ADC的使用

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解LED的使用

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解PWM的使用

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解PWM的使用