RK3588平台驱动调试篇 [ GPIO篇 ] - RK3588-对GPIO的操作控制

news2024/10/7 16:24:49

1. 简介

  • RK3588从入门到精通
  • 本⽂介绍Linux操作gpio⽅法
  • 开发板:ArmSoM-W3

2. GPIO配置

Rockchip Pin的ID按照 控制器(bank)+端口(port)+索引序号(pin) 组成

2.1 GPIO驱动介绍

驱动包括Pinctrl驱动( drivers/pinctrl/pinctrl-rockchip.c ) 和 GPIO驱动
( drivers/gpio/gpio-rockchip.c )

  • Pinctrl驱动是主要驱动,提供IO的⽅法集
  • GPIO驱动是完成 gpiochip 的功能,包括 GPIO 和 IRQ

2.2 GPIO复用

RK3588有5个GPIO控制器,每个控制器可以控制32个IO,作为GPIO功能时,端口⾏为由GPIO控制器寄存器配置

  • 控制器和GPIO控制器数量⼀致
  • 端口固定 A、B、C和D
  • 索引序号固定 0、1、2、3、4、5、6、7

同⼀个控制器如果存在多种复⽤引脚,⼀般叫做m0、m1、m2等等,比如PWM功能:

	pwm1 {
		/omit-if-no-ref/
		pwm1m0_pins: pwm1m0-pins {
			rockchip,pins =
				/* pwm1_m0 */
				<0 RK_PC0 3 &pcfg_pull_none>;
		};

		/omit-if-no-ref/
		pwm1m1_pins: pwm1m1-pins {
			rockchip,pins =
				/* pwm1_m1 */
				<1 RK_PD3 11 &pcfg_pull_none>;
		};

		/omit-if-no-ref/
		pwm1m2_pins: pwm1m2-pins {
			rockchip,pins =
				/* pwm1_m2 */
				<1 RK_PA3 11 &pcfg_pull_none>;
		};
	};

一个Pin脚可以复⽤成多种功能,比如pwm1的GPIO0-C0脚可以有以下脚的复用

PDM0_CLK0_M1/PWM1_M0/I2C2_SDA_M0/CAN0_RX_M0/SPI0_MOSI_M0/PCIE30X1_0_CLKREQN_M0/GPIO0_C0_d

2.3 DTS介绍

dts⼀般把pinctrl节点放在soc.dtsi,例如rk3588s.dtsi,⼀般位于最后⼀个节点,在这个文件中可以找到板子所有可以配置的功能引脚

aliases {
		csi2dcphy0 = &csi2_dcphy0;
		csi2dcphy1 = &csi2_dcphy1;
		csi2dphy0 = &csi2_dphy0;
		csi2dphy1 = &csi2_dphy1;
		csi2dphy2 = &csi2_dphy2;
		dsi0 = &dsi0;
		dsi1 = &dsi1;
		ethernet1 = &gmac1;
		gpio0 = &gpio0;
		gpio1 = &gpio1;
		gpio2 = &gpio2;
		gpio3 = &gpio3;
		gpio4 = &gpio4;
		i2c0 = &i2c0;
		i2c1 = &i2c1;
		i2c2 = &i2c2;
		i2c3 = &i2c3;
		i2c4 = &i2c4;
		i2c5 = &i2c5;
		i2c6 = &i2c6;
		i2c7 = &i2c7;
		i2c8 = &i2c8;
		rkcif_mipi_lvds0= &rkcif_mipi_lvds;
		rkcif_mipi_lvds1= &rkcif_mipi_lvds1;
		rkcif_mipi_lvds2= &rkcif_mipi_lvds2;
		rkcif_mipi_lvds3= &rkcif_mipi_lvds3;
		rkvenc0 = &rkvenc0;
		rkvenc1 = &rkvenc1;
		jpege0 = &jpege0;
		jpege1 = &jpege1;
		jpege2 = &jpege2;
		jpege3 = &jpege3;
		serial0 = &uart0;
		serial1 = &uart1;
		serial2 = &uart2;
		serial3 = &uart3;
		serial4 = &uart4;
		serial5 = &uart5;
		serial6 = &uart6;
		serial7 = &uart7;
		serial8 = &uart8;
		serial9 = &uart9;
		spi0 = &spi0;
		spi1 = &spi1;
		spi2 = &spi2;
		spi3 = &spi3;
		spi4 = &spi4;
		spi5 = &sfc;
		hdcp0 = &hdcp0;
		hdcp1 = &hdcp1;
	};

最后arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi ⽂件通过include形式加到rk3588s.dtsi。
rk3588s-pinctrl.dtsi⽂件已经枚举了rk3588s芯⽚所有iomux的实例,各模块⼀般不再需要创建iomux实例;
创建iomux实例需要遵循如下规则:

  1. 必须在pinctrl节点下
  2. 必须以function+group的形式添加
  3. function+group的格式如下
function {
	group {
		rockchip,pin = <bank gpio func &ref>;
		};
};

比如我添加如下gpio口的使用说明

&pinctrl {
	leds {
		led_rgb_b: led-rgb-b {
			rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
	hym8563 {
		rtc_int: rtc-int {
			rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

使用某一个gpio口的时候要注意是否有其他功能引用这个io口

2.3.1 修改gpio口

如果我们需要修改pwm1的默认脚gpio0c0为gpio1d3

pwm1: pwm@fd8b0010 {
  compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
  reg = <0x0 0xfd8b0010 0x0 0x10>;
  #pwm-cells = <3>;
  pinctrl-names = "active";
  pinctrl-0 = <&pwm1m0_pins>;
  clocks = <&cru 677>, <&cru 676>;
  clock-names = "pwm", "pclk";
  status = "disabled";
 };
 &pwm1 {
 status = "okay";
};
&pwm1 {
 pinctrl-0 = <&pwm1m1_pins>;
 status = "okay";
};

2.3.2 配置某个GPIO电平

有个别需求是某个GPIO不属于某个特定模块,更多是某个电源开关,希望在系统开机后尽快输出⾼或低电平,使⽤"regulator-fixed",regulator-fixed通常⽤于定义电压固定的regulator,或由某个GPIO开关控制的regulator。
以MIPI屏幕电源使能为例,gpio口为gpio1c4

vcc_lcd_mipi1: vcc-lcd-mipi1 {   
		status = "okay";
		compatible = "regulator-fixed";
		regulator-name = "vcc_lcd_mipi1";
		gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>;
		enable-active-high;
		regulator-boot-on;
		regulator-state-mem {
			regulator-off-in-suspend;
		};
	};
	

3. Linux下控制GPIO

编译内核的时候加入 Device Drivers-> GPIO Support ->/sys/class/gpio/… (sysfs interface)。
在这里插入图片描述

通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入
/sys/class/gpio 的使用说明可以参考这篇文章:linux系统基于syfs控制gpio

文件IO方式操作GPIO,使用到了4个函数open、close、read、write。以下是一个简单的基于 C 语言的流水灯和呼吸灯效果的示例代码。这个示例代码使用的是 Linux 上的用户空间 GPIO 控制,你需要适配代码以使用正确的 GPIO 引脚和路径。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define LED_NUM 4

// GPIO 控制的相关路径
#define SYSFS_GPIO_EXPORT "/sys/class/gpio/export"
#define SYSFS_GPIO_DIR_PREFIX "/sys/class/gpio/gpio"
#define SYSFS_GPIO_VALUE_SUFFIX "/value"

// 设置 GPIO 方向
void set_gpio_direction(int gpio, const char *dir) {
    char gpio_path[50];
    sprintf(gpio_path, "%s%d/direction", SYSFS_GPIO_DIR_PREFIX, gpio);
    
    int fd = open(gpio_path, O_WRONLY);
    if (fd == -1) {
        perror("Error opening direction file");
        exit(EXIT_FAILURE);
    }
    write(fd, dir, strlen(dir));
    close(fd);
}

// 控制 GPIO 输出
void set_gpio_value(int gpio, int value) {
    char gpio_path[50];
    sprintf(gpio_path, "%s%d/value", SYSFS_GPIO_DIR_PREFIX, gpio);
    
    int fd = open(gpio_path, O_WRONLY);
    if (fd == -1) {
        perror("Error opening value file");
        exit(EXIT_FAILURE);
    }
    char str_value = value ? '1' : '0';
    write(fd, &str_value, 1);
    close(fd);
}

int main() {
    int leds[LED_NUM] = {17, 18, 19, 20};  // 假设使用的 GPIO 引脚编号
    int i, j;
    
    for (i = 0; i < LED_NUM; i++) {
        // 导出 GPIO
        int export_fd = open(SYSFS_GPIO_EXPORT, O_WRONLY);
        if (export_fd == -1) {
            perror("Error opening export file");
            return EXIT_FAILURE;
        }
        char gpio_str[3];
        sprintf(gpio_str, "%d", leds[i]);
        write(export_fd, gpio_str, strlen(gpio_str));
        close(export_fd);
        
        // 设置 GPIO 方向为输出
        set_gpio_direction(leds[i], "out");
    }
    
    while (1) {
        // 流水灯效果
        for (i = 0; i < LED_NUM; i++) {
            set_gpio_value(leds[i], 1);
            usleep(200000);
            set_gpio_value(leds[i], 0);
        }
        
        // 呼吸灯效果
        for (j = 0; j < 100; j++) {
            for (i = 0; i < LED_NUM; i++) {
                set_gpio_value(leds[i], 1);
                usleep(j * j);
            }
            for (i = 0; i < LED_NUM; i++) {
                set_gpio_value(leds[i], 0);
                usleep(j * j);
            }
        }
    }
    
    return 0;
}

上述代码示例仅为参考,实际使用时需要根据你的硬件和系统配置进行适当修改和测试。

ArmSoM 产品介绍: http://wiki.armsom.org/index.php/ArmSoM-w3

ArmSoM 技术论坛: http://forum.armsom.org/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/949450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

servlet初体验之环境搭建!!!

我们需要用到tomcat服务器&#xff0c;咩有下载的小伙伴看过来&#xff1a;如何正确下载tomcat&#xff1f;&#xff1f;&#xff1f;_明天更新的博客-CSDN博客 1. 创建普通的Java项目&#xff0c;并在项目中创建libs目录存放第三方的jar包。 建立普通项目 创建libs目录存放第三…

2023_Spark_实验三:基于IDEA开发Scala例子

一、创建一个空项目&#xff0c;作为整个项目的基本框架 二、创建SparkStudy模块&#xff0c;用于学习基本的Spark基础 三、创建项目结构 1、在SparkStudy模块下的pom.xml文件中加入对应的依赖&#xff0c;并等待依赖包下载完毕。 在pom.xml文件中加入对应的依赖 ​<!-- S…

模拟4~20ma电流输出的设计

文章目录 1. 原理2. 使用GP8102S或GP8212S进行设计2.1 共地型设计2.2 共源型设计2.3 其它电流需求 3. 隔离光耦电源连接方案4. 利用GP8102S实现0-40V 的可编程电压输出 1. 原理 4 ~ 20ma电流输出的目的不用多说&#xff0c;今天就简单聊一下4 ~ 20ma电流输出是怎么设计出来的&…

【AI】数学基础——概率论

随着联结主义学派的兴起&#xff0c;概率统计已经取代了数理逻辑&#xff0c;成为了人工智能研究的主流工具 数理统计的关注点是 无处不在的可能性 对随机事件发生的可能性进行规范的数学描述是概率论的公理化过程 频率学派认为先验分布式固定的&#xff0c;模型参数靠最大似…

C++day6

1. #include <iostream>using namespace std; class Animal { private:int id; public:Animal(){}Animal(int id):id(id){}virtual void show(){cout << "动物园门牌号:" << id << endl;} }; class Houzi:public Animal { private:string n…

用变压器实现德-英语言翻译【02/8】: 位置编码

一、说明 本文是“用变压器实现德-英语言翻译”系列的第二篇。它从头开始引入位置编码。然后&#xff0c;它解释了 PyTorch 如何实现位置编码。接下来是变压器实现。 二、技术背景 位置编码用于为序列中的每个标记或单词提供相对位置。阅读句子时&#xff0c;每个单词都依赖于它…

日本核污染水排海,有必要囤盐吗?

据央视新闻24日报道&#xff0c;当地时间8月24日13时&#xff0c;日本福岛第一核电站启动污水排海。消息一出&#xff0c;全球哗然。虽然事情已经过去了几天&#xff0c;但是&#xff0c;随着这一举动&#xff0c;大家就乱了阵脚&#xff0c;恐惧者有之&#xff0c;辱骂者有之&…

Nginx从入门到精通(超级详细)

文章目录 一、什么是Nginx1、正向代理2、反向代理3、负载均衡4、动静分离 二、centos7环境安装Nginx1、安装依赖2、下载安装包3、安装4、启动5、停止 三、Nginx核心基础知识1、nginx核心目录2、常用命令3、默认配置文件讲解4、Nginx虚拟主机-搭建前端静态服务器5、使用nignx搭建…

超声波俱乐部分享:AI冷静期,创业者们应该做什么?

8月26日&#xff0c;2023年第十一期超声波俱乐部内部分享会在北京望京举行。本期的主题是&#xff1a;AI冷静期&#xff0c;创业者们应该做什么&#xff1f; 到场的嘉宾有&#xff1a; 超声波创始人杨子超&#xff0c;超声波联合创始人、和牛商业创始人刘思雨&#xff0c;中国…

学习c++的第6天

#include <iostream> using namespace std; class Animal { public: virtual void perform()0; virtual ~Animal() { cout<<"Animal的析构函数"<<endl; } }; class Lion :public Animal { public : void perform() { cout<<"狮子…

41、springboot 整合 FreeMarker 模版技术

springboot 整合 FreeMarker 模版技术 ★ 整合FreeMarker的自动配置&#xff1a; FreeMarkerAutoConfiguration&#xff1a;负责整合Spring容器和获取FreeMarkerProperties加载的配置信息。FreeMarkerServletWebConfiguration/FreeMarkerReactiveWebConfiguration&#xff1a…

C++ 多级继承

所谓多级继承就是代代相传&#xff0c;几代人&#xff0c;后代继承祖辈的数据和方法。但是有三种不同的继承方式而已。 构造顺序&#xff0c;即基类先构造&#xff0c;其次代代相传&#xff0c;析构顺序则是从子代先析构&#xff0c;最后析构祖先。 构造:从祖宗开始&#xff0…

马上金九银十了,给大家一点面试方面的建议

哈喽大家好啊&#xff0c;我是Hydra。 好久不见&#xff0c;甚是想念。这段时间没有更新什么文章&#xff0c;其实是因为我跳了一波槽&#xff0c;出去面了一圈后&#xff0c;也顺利拿了不少架构岗位的offer。 正好马上要金九银十了&#xff0c;相信有不少小伙伴们估计也有跳…

1.2 数据库系统结构

思维导图&#xff1a; 学习目标&#xff1a; 学习数据库系统结构是一个结构性和系统性的过程。如果是我&#xff0c;我会采用以下策略&#xff1a; 1. **确定目标和动机**&#xff1a; - 明确为什么要学习数据库系统。是为了应对工作的需求、为了研究还是出于兴趣&#xf…

多用户商城系统常见的安全性和数据保护措施有哪些?

电子商务的迅速发展&#xff0c;越来越多的企业选择搭建多用户商城系统来扩展业务。然而&#xff0c;随之而来的是对数据安全和保护的日益关注。在选择多用户商城系统时&#xff0c;我们需要考虑一系列的安全性和数据保护措施&#xff0c;以确保商城系统的稳定性和用户数据的完…

【数据结构】带头双向循环链表---C语言版(单链表我们分手吧,不要再找我玩了!!!)

文章目录 &#x1f438;一、前言&#x1f438;二、链表的分类&#x1f344;1. 单向或者双向链表&#x1f344;2. 带头或者不带头链表&#x1f344;3. 循环或者非循环&#x1f344;4. 最常用链表 &#x1f438;三、带头双向循环链表详解&#x1f34e;创建带头双向循环链表⭕接口…

Power Pivot 实现数据建模

一、简介 Excel中的透视表适合小规模数据&#xff1b;如果想在稍微大一些的数据中进行高性能透视表分析&#xff0c;就要使用Power Pivot&#xff1b;再大一些数据&#xff0c;可能就需要大数据分析服务来进行分析。 Power Pivot&#xff0c;可以让没有技术背景的企业业务人员…

【前端demo】将二进制数转换为十进制数 原生实现

https://github.com/florinpop17/app-ideas 总结 文章目录 效果JavaScript实现进制转换原生代码遇到的问题 效果 二进制转换为十进制若输入为空或不是二进制&#xff0c;提示清空 JavaScript实现进制转换 parseInt parseInt(111,2)手动实现 bin是输入的字符串。 functio…

设备分配与回收、缓冲区管理

设备分配与回收 是什么&#xff1a;设备分配的任务是按照一定的策略&#xff0c;为提出I/O请求的进程分配合适的设备&#xff0c;确保CPU与I/O设备之间能正常通信&#xff0c;还应分配相应的控制器和通道。设备分配管理中的数据结构 设备控制表DCT&#xff1a;每个设备对应一张…

Spring Bean 生命周期顺序验证

看到一篇写的很好的 Spring Bean 生命周期的博客&#xff1a;一文读懂 Spring Bean 的生命周期&#xff0c;在此写个简单的 Bean 进行验证。 1. 创建Springboot项目 基于 springboot 的2.1.8.RELEASE 创建一个简单项目&#xff0c;只添加 spring-aop 包以引入spring依赖。 &…