当前位置: 首页 > 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…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...