当前位置: 首页 > news >正文

Linux框架(二)——pinctrl和gpio子系统

基于设备树的 LED 驱动,但是驱动的本质还是没变,都是配置 LED 灯所使用的 GPIO 寄存器,驱动开发方式和裸机基本没啥区别。

Linux 内核提供了 pinctrl 和 gpio 子系统用于GPIO 驱动,本章我们就来学习一下如何借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。

pinctrl子系统

pinctrl子系统简介

Linux 驱动讲究驱动分离与分层,驱动分离与分层其实就是按照面向对象编程的设计思想而设计的设备驱动框架,不管什么外设驱动,GPIO 驱动基本都是必须的,而 pinctrl 和 gpio 子系统又是 GPIO 驱动必须使用的,

基于设备树初始化流程:

  1. 修改设备树,添加相应的节点,节点里面重点是设置 reg 属性,reg 属性包括了 GPIO相关寄存器。
  2. 获取 reg 属性中 PMU_GRF_GPIO0C_IOMUX_L、PMU_GRF_GPIO0C_DS_0 、GPIO0_SWPORT_DR_H 和 GPIO0_SWPORT_DDR_H 这些寄存器的地址,并且初始化它们
  3. 在②里面将 GPIO0_C0 这个 PIN 设置为通用输出功能(GPIO),也就是设置复用功能。
  4. 在②里面将 GPIO0_C0 这个 PIN 设置为输出模式。

②中完成对 GPIO0_C0 这个 PIN 相关的寄存器地址获取,③和④设置这个 PIN的复用功能、上下拉等

引脚设置基本需要的两个方面:

  1. 设置 PIN 的复用功能。
  2. PIN 复用为 GPIO 功能,设置 GPIO 相关属性。输入、输出功能,驱动能力等级

因此 Linux 内核针对 PIN 推出了 pinctrl 子系统,对于 GPIO 的电气属性配置推出了 gpio 子系统。

传统的配置 pin 的方式就是直接操作相应的寄存器,但是这种配置方式比较繁琐、而且容易出问题(比如 pin 功能冲突)。pinctrl 子系统就是为了解决这个问题而引入的

pinctrl 子系统主要工作内容如下:

  1. 获取设备树中 pin 信息。
  2. 根据获取到的 pin 信息来设置 pin 的复用功能
  3. 根据获取到的 pin 信息来设置 pin 的电气特性,如驱动能力。

对于我们使用者来讲,只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始化工作均由 pinctrl 子系统来完成,pinctrl 子系统源码目录为 drivers/pinctrl。

pinctrl子系统驱动

  1. 在设备树里面设置 PIN 的配置信息,毕竟 pinctrl 子系统要根据你提供的信息来配置 PIN 功能,一般会在设备树里面创建一个节点来描述 PIN 的配置信息。rk3568.dtsi 文件
  2. 向 pinctrl 节点追加数据,不同的外设使用的 PIN 不同、其配置也不同,因此一个萝卜一个坑,将某个外设所使用的所有 PIN 都组织在一个子节点里面。先打开 rk3568-pinctrl.dtsi文件,此文件需要编译内核以后才能得到

每个 pincrtl 节点必须至少包含一个子节点来存放 pincrtl 相关信息,也就是 pinctrl 集,这个集合里面存放当前外设用到哪些引脚(PIN)、复用配置、上下拉、驱动能力等。一般这个存放pincrtl集的子节点名字是**“rockchip,pins”。**

在“rockchip,pins”子节点里面存放外设的引脚描述信息,格式如下:

rockchip,pins = <PIN_BANK PIN_BANK_IDX MUX &phandle>
/*****************************************
1. PIN_BANK			PIN_BANK 就是 PIN 所属的组
RK3568 一共有 5 组 PIN:GPIO0~GPIO4,分别对应 0~42. PIN_BANK_IDX		PIN_BANK_IDX 是组内的编号
以 GPIO0 组为例,一共有 A0~A7、B0~B7、C0~C7、D0~D7,这 32 个 PIN。3. MUX				MUX 就是设置 PIN 的复用功能4. phandle			phandle用来描述一些引脚的通用配置信息
pcfg_pull_up、pcfg_pull_down、pcfg_pull_none 和 pcfg_pull_none_drv_level_0 就是可使用的配置项********************************************/

设备树中添加 pinctrl 节点模板

如何在设备树中添加某个外设的 PIN 信息

创建对应的节点

在 pinctrl 节点下添加一个子节点

	pinctrl: pinctrl {compatible = "rockchip,rk3568-pinctrl";rockchip,grf = <&grf>;rockchip,pmu = <&pmugrf>;#address-cells = <2>;#size-cells = <2>;ranges;gpio0: gpio@fdd60000 {compatible = "rockchip,gpio-bank";reg = <0x0 0xfdd60000 0x0 0x100>;interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>;gpio-controller;#gpio-cells = <2>;gpio-ranges = <&pinctrl 0 0 32>;interrupt-controller;#interrupt-cells = <2>;};

添加“rockchip,pins”属性

添加一个“rockchip,pins”属性,这个属性是真正用来描述 PIN 配置信息的

	uart0 {/omit-if-no-ref/uart0_xfer: uart0-xfer {rockchip,pins =/* uart0_rx */<0 RK_PC0 3 &pcfg_pull_up>,/* uart0_tx */<0 RK_PC1 3 &pcfg_pull_up>;};/omit-if-no-ref/uart0_ctsn: uart0-ctsn {rockchip,pins =/* uart0_ctsn */<0 RK_PC7 3 &pcfg_pull_none>;};/omit-if-no-ref/uart0_rtsn: uart0-rtsn {rockchip,pins =/* uart0_rtsn */<0 RK_PC4 3 &pcfg_pull_none>;};};

按道理来讲,当我们将一个 PIN 用作 GPIO 功能的时候也需要创建对应的 pinctrl 节点,并且将所用的 PIN 复用为 GPIO 功能,但是!对于 RK3568 而言,如果一个 PIN 用作 GPIO 功能的时候不需要创建对应的 pinctrl 节点!

gpio子系统

gpio子系统简介

pinctrl 子系统重点是设置 PIN(有的 SOC 叫做 PAD)的复用和电气属性

gpio 子系统顾名思义,就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO为输入输出,读取 GPIO 的值等。gpio 子系统的主要目的就是方便驱动开发者使用 gpio,驱动开发者在设备树中添加 gpio 相关信息,然后就可以在驱动程序中使用 gpio 子系统提供的 API函数来操作 GPIO,Linux 内核向驱动开发者屏蔽掉了 GPIO 的设置过程,极大的方便了驱动开发者使用 GPIO。

rk3568中gpio子系统

设备树中GPIO信息

		gpio0: gpio@fdd60000 {compatible = "rockchip,gpio-bank";reg = <0x0 0xfdd60000 0x0 0x100>;interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>;gpio-controller;#gpio-cells = <2>;gpio-ranges = <&pinctrl 0 0 32>;interrupt-controller;#interrupt-cells = <2>;};/****************************************************
compatible 属性值为“rockchip,gpio-bank”
reg 属性设置了 GPIO0 控制器的寄存器基地址为 0XFDD60000
interrupts 属性描述 GPIO0 控制器对应的中断信息
clocks 属性指定这个 GPIO0 控制器的时钟
“gpio-controller”表示 gpio0 节点是个 GPIO 控制器,每个 GPIO 控制器节点必须包含“gpio-controller”属性。

但是,CSI1 摄像头驱动程序怎么知道 RESET 引脚连接的 GPIO3_B6 呢?这里肯定需要设备树来告诉驱动,在设备树中的 CSI1 摄像头节点下添加一个属性来描述摄像头的 RESET 引脚就行了,CSI1 摄像头驱动直接读取这个属性值就知道摄像头的 RESET 引脚使用的是哪个 GPIO 了。

gpio子系统中的API函数

对于驱动开发人员,设置好设备树以后就可以使用 gpio 子系统提供的 API 函数来操作指定的 GPIO,gpio 子系统向驱动开发人员屏蔽了具体的读写寄存器过程。

gpio_request 函数

int gpio_request(unsigned gpio, const char *label)// gpio:要申请的 gpio 标号,使用 of_get_named_gpio 函数从设备树获取指定 GPIO 属性信// 息,此函数会返回这个 GPIO 的标号。
// label:给 gpio 设置个名字。
// 返回值:0,申请成功;其他值,申请失败

gpio_free 函数

void gpio_free(unsigned gpio);
// gpio:要释放的 gpio 标号。
// 返回值:无。

gpio_direction_input 函数

int gpio_direction_input(unsigned gpio);
// gpio:要设置为输入的 GPIO 标号。
// 返回值:0,设置成功;负值,设置失败。

gpio_direction_output 函数

int gpio_direction_output(unsigned gpio, int value);
// gpio:要设置为输出的 GPIO 标号。
// value:GPIO 默认输出值。
// 返回值:0,设置成功;负值,设置失败。

gpio_get_value 函数

int gpio_get_value(unsigned int gpio);
// gpio:要获取的 GPIO 标号。
// 返回值:非负值,得到的 GPIO 值;负值,获取失败。

gpio_set_value 函数

void gpio_set_value(unsigned int gpio, int value);
// gpio:要设置的 GPIO 标号。
// value:要设置的值。
// 返回值:无

设备数添加gpio节点

以led为例,学习一下如何创建 GPIO 节点。

创建led设备子节点

添加gpio属性信息

	rk3568_led: led0 {compatible = "atkrk3568-led";status = "okay";reg = <0x0 0xFDC20010 0x0 0x08 		/* PMU_GRF_GPIO0C_IOMUX_L */0x0 0xFDC20090 0x0 0x08 	/* PMU_GRF_GPIO0C_DS_0 */0x0 0xFDD60004 0x0 0x08 	/* GPIO0_SWPORT_DR_H */0x0 0xFDD6000C 0x0 0x08 >;	/* GPIO0_SWPORT_DDR_H */};gpioled{compatible = "zxk, led";led-gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;status = "okay";};
};

与GPIO相关的OF函数

在驱动程序中需要读取 gpio 属性内容,Linux 内核提供了几个与 GPIO 有关的 OF 函数

of_gpio_named_count 函数

int of_gpio_named_count(struct device_node *np, const char *propname);
// np:设备节点。
// propname:要统计的 GPIO 属性。
// 返回值:正值,统计到的 GPIO 数量;负值,失败。

of_gpio_count 函数

int of_gpio_count(struct device_node *np);
// np:设备节点。
// 返回值:正值,统计到的 GPIO 数量;负值,失败。

of_get_named_gpio 函数

此函数获取 GPIO 编号,因为 Linux 内核中关于 GPIO 的 API 函数都要使用 GPIO 编号,此函数会将设备树中类似<&gpio4 RK_PA1 GPIO_ACTIVE_LOW>的属性信息转换为对应的GPIO 编号,此函数在驱动中使用很频繁

int of_get_named_gpio(struct device_node *np,const char *propname,int index);
// np:设备节点。
// propname:包含要获取 GPIO 信息的属性名。
// index:GPIO 索引,因为一个属性里面可能包含多个 GPIO,此参数指定要获取哪个 GPIO的编号,如果只有一个 GPIO 信息的话此参数为 0。
// 返回值:正值,获取到的 GPIO 编号;负值,失败。

相关文章:

Linux框架(二)——pinctrl和gpio子系统

基于设备树的 LED 驱动&#xff0c;但是驱动的本质还是没变&#xff0c;都是配置 LED 灯所使用的 GPIO 寄存器&#xff0c;驱动开发方式和裸机基本没啥区别。 Linux 内核提供了 pinctrl 和 gpio 子系统用于GPIO 驱动&#xff0c;本章我们就来学习一下如何借助 pinctrl 和 gpio…...

C++ string的基本概念

文章目录 1. 什么是string&#xff1f;2. auto和范围for的使用2. 1 auto2. 2 范围for 3. 迭代器的概念、const string的概念3. 1 迭代器的概念3. 2 const string的概念 1. 什么是string&#xff1f; 在了解什么是string之前&#xff0c;我们首先需要知道字符串是什么。在C语言中…...

MAC虚拟机上安装WDA环境

MAC虚拟机上安装WDA环境 一、MAC虚拟机切换root权限二、macOS上安装xcode若你的macOS系统可以在appstore下载安装若你安装的macOS系统版本太低&#xff0c;无法在appstore上安装xcode 三、macOS上安装WebDriverAgent四、使用xcode配置WDA安装到手机上高版本系统支持 一、MAC虚拟…...

与 Cursor AI 对话编程:2小时开发报修维修微信小程序

本文记录了如何通过与 Cursor AI 对话&#xff0c;全程不写一行代码的情况下&#xff0c;完成一个完整的报修小程序。整个过程展示了 AI 如何帮助我们&#xff1a; 生成代码 、解决问题、优化实现、完善细节。 先看一下效果图&#xff1a; 一、项目配置 首先我是这样和 AI 对…...

leetcode-73.矩阵置零-day5

class Solution {public void setZeroes(int[][] mat) {int m mat.length, n mat[0].length;// 1. 扫描「首行」和「首列」记录「首行」和「首列」是否该被置零boolean r0 false, c0 false;for (int i 0; i < m; i) {if (mat[i][0] 0) {r0 true;break;}}for (int j …...

CSS学习记录13

CSS组合器 组合器是解释选择器之间关系的某种机制。CSS选择器可以包含多个简单选择器。在简单选择器之间&#xff0c;我们可以包含一个组合器。 CSS中有四种不同的组合器&#xff1a; 后代组合器&#xff08;空格&#xff09;子选择器&#xff08;>)相邻兄弟选择器&#…...

CAD图纸加密软件哪个最好用 | 安全可靠的解决方案

CAD图纸加密软件哪个最好用 | 安全可靠的解决方案 图纸文件泄密事件频发&#xff0c;给企业带来了严重的商业损失、技术秘密泄露、公共安全威胁以及信誉损害。 为了应对这一挑战&#xff0c;选择一款既安全可靠又易于使用的CAD图纸加密软件显得尤为重要。 在众多加密软件中&a…...

基于SSM+Vue的宠物医院管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

处理VUE框架中,ElementUI控件u-table空值排序问题

按照以下步骤进行操作&#xff1a; 分离数据&#xff1a;首先&#xff0c;将原始数据按照username为空和非空进行分类。对非空表进行排序&#xff1a;对非空表按照username进行升序排序。合并表格&#xff1a;将空表和排序后的非空表合并&#xff0c;保证空表挂接在排序后的非…...

专业140+总分400+北京理工大学826信号处理导论考研经验北理工电子信息与通信工程,真题,大纲,参考书。

考研总分400&#xff0c;专业826信号处理导论&#xff08;信号与系统和dsp&#xff09;140&#xff0c;成功上岸北理工&#xff0c;虽然已经一段时间&#xff0c;但是后劲很大&#xff0c;每每回想还是昨日事&#xff0c;群里同学多次要求分享自己的一些经验&#xff0c;感谢大…...

Rocky DEM tutorial5_Drop Weight test_落锤试验

tutorial5_Drop Weight test_落锤实验 文章目录 tutorial5_Drop Weight test_落锤实验0. 目的1. 模型介绍2. 模型设置2.1 设置Physics2.2 导入几何2.3 定义进口面2.4 设置motion frames2.5 设置边界条件2.6 设置材料2.7 设置 materials interactions2.8 设置 Particles2.9 设置…...

C#,在 C# 语言中将 LaTeX 转换为 PNG 或 JPG 图像

在 C 语言中将 LaTeX 转换为 PNG 或 JPG 图像# 12月 28&#xff0c; 2021 2 分钟 法尔汉拉扎 在 C 语言中将 TeX 转换为 PNG JPG 图像# TeX 格式用于处理技术和科学文件。它通常用于交流或发布此类文档。在某些情况下&#xff0c;您可能需要将 TeX 文件渲染为 PNG 或 JPG 等图像…...

Elasticsearch:Mapping-映射

一、创建索引 自动生成索引字段数据类型即自动映射 创建之前&#xff0c;先删除索引防止重复创建 删除索引: DELETE product_mapping创建索引 product_mapping并且赋值 PUT /product_mapping/_doc/1 {"name": "xiaomi phone","desc": "s…...

安装Tensorflow@FreeBSD(失败)

pkg 安装&#xff0c;失败&#xff0c;找不到:pkg: No packages available to install matching science/py-tensorflow have been found in the repositories ports安装 cd /usr/ports/science/py-tensorflow make install 报错: 按照提示重新发命令 make DISABLE_VULNERA…...

API接口示例:电商商品评论数据

当然&#xff0c;以下是一个简化的电商商品评论数据API接口的示例。请注意&#xff0c;这只是一个示例&#xff0c;实际的API接口可能会更加复杂&#xff0c;并且会包含更多的验证、错误处理和安全措施。 API接口示例&#xff1a;电商商品评论数据 基础信息 API名称&#xf…...

使用idea创建一个JAVA WEB项目

文章目录 1. javaweb项目简介2. 创建2.1 idea新建项目2.2 选择&#xff0c;命名2.3 打开2.4 选择tomcat运行2.5 结果 3. 总结 1. javaweb项目简介 JavaWeb项目是一种基于Java技术的Web应用程序&#xff0c;主要用于开发动态网页和Web服务。这种项目能够构建在Java技术栈之上&a…...

解决MyBatis在 Oracle 中使用 IN 语句不能超过 1000 问题

在 Oracle 数据库中&#xff0c;IN 语句常用于查询某个字段是否属于一组特定的值。对于大多数开发者而言&#xff0c;IN 是一种简单直观的查询方式&#xff0c;能够提升开发效率&#xff0c;避免过多的 OR 语句。然而&#xff0c;许多人在使用 IN 语句时可能遇到一个问题&#…...

最长递增子序列两种算法实现(动态规划,二分查找)

恭喜你刷到博主 DP 经典题目详解部分第一期&#xff0c;想学好 DP 请关注订阅&#xff0c;会持续更新&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 建议先阅读DP算法入门 00001 最长递增子序列&#xff08;Longest Increasing Subsequence&#xff0c;简写…...

Deepmotion技术浅析(三):特征提取

DeepMotion 的特征提取模块是整个动作捕捉和 3D 追踪流程的基础&#xff0c;负责从输入的视频帧中提取出具有代表性的视觉特征。这些特征将被用于人体姿态估计、动作识别、3D 重建等后续任务。 包括&#xff1a; 1.图像特征提取 卷积神经网络&#xff08;CNN&#xff09; 卷…...

国内CentOS使用yum安装docker和docker-compose

安装docker 安装需要的软件包&#xff0c; yum-util 提供yum-config-manager功能&#xff0c;另两个是devicemapper驱动依赖 yum install -y yum-utils device-mapper-persistent-data lvm2下载yum源采用阿里云的镜像源 wget -O /etc/yum.repos.d/docker-ce.repo https://mi…...

DuckDB + Spring Boot + MyBatis 构建高性能本地数据分析引擎

DuckDB 是一款令人兴奋的内嵌式分析型数据库 (OLAP)&#xff0c;它为本地数据分析和处理带来了前所未有的便捷与高效 &#x1f680;。它无需外部服务器&#xff0c;可以直接在应用程序进程中运行&#xff0c;并提供了强大的 SQL 支持和列式存储带来的高性能。 什么是 DuckDB&am…...

Ps:Adobe PDF 预设

Ps菜单&#xff1a;编辑/Adobe PDF 预设 Edit/Adobe PDF Presets 通过“Adobe PDF 预设” Adobe PDF Presets对话框&#xff0c;可以查看 Adobe PDF 预设&#xff0c;了解复杂的 PDF 设置。还可以编辑、新建、删除、载入预设&#xff0c;根据最终用途&#xff08;如高质量打印、…...

2048游戏的技术实现分析-完全Java和Processing版

目录 简介Processing库基础项目构建指南项目结构核心数据结构游戏核心机制图形界面实现性能优化代码详解设计模式分析测试策略总结与展望简介 2048是一款由Gabriele Cirulli开发的经典益智游戏。本文将深入分析其Java实现版本的技术细节。该实现使用了Processing库来创建图形界…...

探秘鸿蒙 HarmonyOS NEXT:实战用 CodeGenie 构建鸿蒙应用页面

在开发鸿蒙应用时&#xff0c;你是否也曾为一个页面的布局反复调整&#xff1f;是否还在为查 API、写模板代码而浪费大量时间&#xff1f;今天带大家实战体验一下鸿蒙官方的 AI 编程助手——CodeGenie&#xff08;代码精灵&#xff09; &#xff0c;如何从 0 到 1 快速构建一个…...

生成JavaDoc文档

生成 JavaDoc 文档 1、快速生成 文档 注解 2、常见的文档注解 3、脚本生成 doc 文档 4、IDEA工具栏生成 doc 文档 第一章 快速入门 第01节 使用插件 在插件工具当中&#xff0c;找到插件 javaDoc 使用方式&#xff0c;在代码区域&#xff0c;直接点击右键。选择 第02节 常用注…...

安全编码规范与标准:对比与分析及应用案例

在软件开发领域&#xff0c;尤其是涉及安全关键系统的开发中&#xff0c;遵循编码规范和标准是确保软件质量和安全性的重要手段。除了CERT C、CERT Java和MISRA外&#xff0c;还有其他多个与安全相关的编码规范和标准&#xff0c;以下是一些主要标准的对比说明&#xff1a; 一…...

软考 系统架构设计师系列知识点之杂项集萃(83)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;82&#xff09; 第150题 体系结构权衡分析方法&#xff08;Architecture Tradeoff Analysis Method&#xff0c;ATAM&#xff09;是一种常见的系统架构评估框架&#xff0c;该框架主要关注系统的…...

Linux文件系统详解:从入门到精通

无论是开发高性能应用还是进行系统级编程&#xff0c;文件系统都是我们必须掌握的基础知识。今天&#xff0c;我将带大家深入浅出地了解Linux文件系统的核心概念和工作原理。 一、Linux文件系统概述 Linux文件系统是操作系统中负责管理持久存储设备上数据的子系统。它不仅仅是…...

机器人玩转之---嵌入式开发板基础知识到实战选型指南(包含ORIN、RDK X5、Raspberry pi、RK系列等)

1. 基础知识讲解 1.1 什么是嵌入式开发板&#xff1f; 嵌入式开发板是一种专门设计用于嵌入式系统开发的硬件平台&#xff0c;它集成了微处理器、内存、存储、输入输出接口等核心组件于单块印刷电路板上。与传统的PC不同&#xff0c;嵌入式开发板具有体积小、功耗低、成本适中…...

Python 训练营打卡 Day 45

TensorBoard 简单来说&#xff0c;TensorBoard 是 TensorFlow 自带的一个「可视化工具」&#xff0c;就像给机器学习模型训练过程装了一个「监控屏幕」。你可以用它直观看到训练过程中的数据变化&#xff08;比如损失值、准确率&#xff09;、模型结构、数据分布等&#xff0c…...