RK3568驱动指南|第十二篇 GPIO子系统-第136章 实战:实现动态切换引脚复用功能

news2024/9/21 14:31:59

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十二篇 GPIO子系统_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第136章 实战:实现动态切换引脚复用功能

再上一个小节中完成了GPIO子系统与pinctrl子系统相结合实验,在本章节中将更进一步,实现引脚动态切换引脚复用功能。

这里仍旧使用RK3568底板背面的20 pin GPIO底座的1号管脚来完成本章节要进行的动态切换引脚复用的功能,该引脚的核心板原理图内容如下所示:

图136-1

 左侧为该引脚的一些其他复用功能,在前面的章节中复用的都是GPIO功能,而本章节中将实现I2C3_SDA和GPIO两个复用功能的动态切换。

136.1 设备树的修改

本小节修改好的设备树以及编译好的boot.img镜像存放路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\90_gpioctrl09\01_内核镜像。

首先根据上图中的复用功能查看设备树中是否已经对该引脚进行了复用,在确保该引脚无任何复用之后,rk3568-evb1-ddr4-v10.dtsi设备树进行内容的添加,将根节点中的gpiol_a0修改为以下内容:

  my_gpio:gpio1_a0 {
      compatible = "mygpio";
      my-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "mygpio_func1", "mygpio_func2";
        pinctrl-0 = <&mygpio_ctrl>;
        pinctrl-1 = <&i2c3_sda>;
    };

pinctrl-names 表示引脚控制器配置的名称,这里有两个值,分别对应复用1和复用2。

pinctrl-0 指定了与该配置相关联的引脚控制器句柄,这里为 &mygpio_ctrl,表示复用为gpio功能。

pinctrl-1 指定了与该配置相关联的引脚控制器句柄,这里为 &i2c3_sda,表示复用为i2c3_sda功能。

添加完成如下图所示:

图136-2

然后找到pinctrl节点,在节点尾部进行修改和添加,具体内容如下所示:

    mygpio_func1 {
        mygpio_ctrl: my-gpio-ctrl {
            rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
        };
    };  

    mygpio_func2 {
        i2c3_sda: i2c3_sda {
            rockchip,pins = <1 RK_PA0 1 &pcfg_pull_none>;
        };
    };     

修改添加完成如下图所示:

图136-3

至此,关于设备树相关的修改就完成了,保存退出之后,编译内核,然后将生成的boot.img镜像烧写到开发板上即可。

136.2 驱动程序的编写

本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\88_gpioctrl07\02_module

编写完成的gpio_api.c代码如下所示:

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio.h>
#include <linux/device.h>
struct pinctrl *gpio_pinctrl;          // GPIO pinctrl 实例指针
struct pinctrl_state *func1_state;     // 功能1状态
struct pinctrl_state *func2_state;     // 功能2状态
int ret;

ssize_t selectmux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    unsigned long select;
    select = simple_strtoul(buf, NULL, 10);
    if (select == 1) {
        pinctrl_select_state(gpio_pinctrl, func1_state);     // 选择功能1状态
    } else if (select == 0) {
        pinctrl_select_state(gpio_pinctrl, func2_state);     // 选择功能2状态
    }
    return count;
}
DEVICE_ATTR_WO(selectmux);       // 定义可写的设备属性 selectmux

int pinctrl_get_and_lookstate(struct device *dev)
{
    gpio_pinctrl = pinctrl_get(dev);    // 获取GPIO pinctrl实例
    if (IS_ERR(gpio_pinctrl)) {
        printk("pinctrl_get is error\n");
        return -1;
    }

    func1_state = pinctrl_lookup_state(gpio_pinctrl, "mygpio_func1");    // 查找功能1状态
    if (IS_ERR(func1_state)) {
        printk("pinctrl_lookup_state is error\n");
        return -2;
    }

    func2_state = pinctrl_lookup_state(gpio_pinctrl, "mygpio_func2");    // 查找功能2状态
    if (IS_ERR(func2_state)) {
        printk("pinctrl_lookup_state is error\n");
        return -2;
    }

    return 0;
}

// 平台设备初始化函数
static int my_platform_probe(struct platform_device *dev)
{
    printk("This is mydriver_probe\n");
    pinctrl_get_and_lookstate(&dev->dev);     // 获取并查找GPIO pinctrl实例和状态
    device_create_file(&dev->dev, &dev_attr_selectmux);    // 在设备上创建属性件
    return 0;
}

// 平台设备的移除函数
static int my_platform_remove(struct platform_device *pdev)
{
    printk(KERN_INFO "my_platform_remove: Removing platform device\n");

    // 清理设备特定的操作
    // ...

    return 0;
}


const struct of_device_id of_match_table_id[]  = {
	{.compatible="mygpio"},
};

// 定义平台驱动结构体
static struct platform_driver my_platform_driver = {
    .probe = my_platform_probe,
    .remove = my_platform_remove,
    .driver = {
        .name = "my_platform_device",
        .owner = THIS_MODULE,
		.of_match_table =  of_match_table_id,
    },
};

// 模块初始化函数
static int __init my_platform_driver_init(void)
{
    int ret;

    // 注册平台驱动
    ret = platform_driver_register(&my_platform_driver);
    if (ret) {
        printk(KERN_ERR "Failed to register platform driver\n");
        return ret;
    }

    printk(KERN_INFO "my_platform_driver: Platform driver initialized\n");

    return 0;
}

// 模块退出函数
static void __exit my_platform_driver_exit(void)
{
    // 注销平台驱动
    platform_driver_unregister(&my_platform_driver);

    printk(KERN_INFO "my_platform_driver: Platform driver exited\n");
}

module_init(my_platform_driver_init);
module_exit(my_platform_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("topeet");

136.3运行测试

136.3.1 编译驱动程序

在上一小节中的gpio_api.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += gpio_api.o    #此处要和你的驱动源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel    #这里是你的内核目录                                                                                                                            
PWD ?= $(shell pwd)
all:
    make -C $(KDIR) M=$(PWD) modules    #make操作
clean:
    make -C $(KDIR) M=$(PWD) clean    #make clean操作

对于Makefile的内容注释已在上图添加,保存退出之后,来到存放gpio_api.c和Makefile文件目录下,如下图(图136-4)所示:

图136-4

然后使用命令“make”进行驱动的编译,编译完成如下图(图136-5)所示:

图136-5

编译完生成gpio_api.ko目标文件,如下图(图136-6)所示:

图136-6

至此驱动模块就编译成功了。

136.3.2 运行测试

首先需要确保当前开发板使用的内核镜像是我们在135.2小节中修改设备树后编译生成的镜像,然后

启动开发板,首先使用以下命令查看gpio1 RK_PA0引脚的复用功能,如下图所示:

cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins | grep 32

图136-7

可以看到在没有加载驱动之前,gpio1 RK_PA0引脚是没有进行复用的,然后使用以下命令进行驱动的加载,如下图(图54-5)所示:

insmod gpio_api.ko

图136-8

然后使用以下命令进入/sys/devices/platform/gpio1_a0/目录,其中的selectmux文件就是用来动态修改服用关系的,如下图所示:

cd /sys/devices/platform/gpio1_a0/

 

图136-9

当向selectmux文件写入0时表示选择功能2,也就是将该引脚复用为I2C3_SDA,当向selectmux文件写入1时表示选择功能1,也就是将该引脚复用为GPIO,这里我们先输入以下命令向selectmux文件写入1,验证GPIO的复用

echo 1 > selectmux

 

图136-10

然后重新使用使用以下命令查看gpio1 RK_PA0引脚的复用功能,如下图所示:

cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins | grep 32

图136-11

根据打印信息可以得到gpio1 RK_PA0已经被设置为了GPIO功能,然后输入以下命令向selectmux文件写入0,验证I2C3_SDA的复用

echo 0 > selectmux

图136-12

然后重新使用使用以下命令查看gpio1 RK_PA0引脚的复用功能,如下图所示:

cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins | grep 32

图136-13

根据打印信息可以得到gpio1 RK_PA0已经被复用为了I2C3_SDA功能,最后使用以下命令进行驱动的卸载,如下图所示:

rmmod gpio_api.ko

图136-14

至此,实现动态切换引脚复用功能实战就完成了。

 

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

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

相关文章

C语言天花板——指针(进阶3)

篇接上文(http://t.csdnimg.cn/Tl42h)&#xff0c;今天我们来讲一些有趣的关于指针的问题&#x1f6a2;&#x1f6a2;&#x1f6a2; 首先我们来看个代码&#xff1a; int main() {//一维数组int a[] { 1,2,3,4 };//4个元素&#xff0c;每个元素使int类型(4个字节)printf(&qu…

【LeetCode】24. 两两交换链表中的节点(中等)——代码随想录算法训练营Day04

题目链接&#xff1a;24. 两两交换链表中的节点 题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1…

基于JAVA的民宿预定管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用例设计2.2 功能设计2.2.1 租客角色2.2.2 房主角色2.2.3 系统管理员角色 三、系统展示四、核心代码4.1 查询民宿4.2 新增民宿4.3 新增民宿评价4.4 查询留言4.5 新增民宿订单 五、免责说明 一、摘要 1.1 项目介绍 基于…

Centos7下升级gcc/g++版本(简单 + 避坑)

在 Centos7 下&#xff0c;使用 yum 安装高版本的 gcc/g 最简单&#xff1a; yum -y install centos-release-scl yum -y install devtoolset-11-gcc devtoolset-11-gcc-c devtoolset-11-binutils需要安装哪个个版本的gcc/g&#xff0c;就把数字替换成对应的版本号。例如上面代…

Velodyne 64E S3 硬件连接和 velodyne_driver ROS驱动安装

在当前的研究工作中&#xff0c;点云语义分割技术的应用显得尤为重要&#xff0c;而我选择了rangenet作为分割算法的核心。尽管课题组拥有一款80线激光雷达&#xff0c;但是在实际测试中&#xff0c;我们发现该算法模型在我们的数据集上的泛化表现并不理想。为了改善这一情况&a…

ubuntu22.04虚拟机安装教程

ubuntu22.04虚拟机安装教程 1.下载镜像&#xff1a; https://ubuntu.com/ 打开后点击Download: 或者用清华镜像源下载&#xff1a;滑到最底下&#xff0c;点击ubuntu-releases 选中这个版本ubuntu-22.04.3-desktop-amd64点击下载 2.虚拟机加载&#xff1a;打开VM&#xff0…

移动通信系统关键技术多址接入OFDM学习(7)

1.OFDM是一种多载波传输方案&#xff0c;可以将高速串行传输转换为低速并行传输&#xff0c;增加符号持续时间&#xff0c;抗多径干扰能力强。 串行和并行有着不同的比特持续时间&#xff0c;同时拥有相同的数据速率。因此&#xff0c;虽然OFDM将串行信号转换为并行信号&#…

Java项目:06 Springboot的进销存管理系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 进销存管理系统 介绍 进销存系统是为了对企业生产经营中进货、出货、批发销售、付款等全程进行&#xff08;从接获订单合同开 始&#xff0c;进入物料采购、入…

QT上位机开发(crc校验)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 crc校验是数据校验中一种常用的方法。我们在上位机和下位机沟通的时候&#xff0c;有的时候需要检验数据在传输的时候有&#xff0c;没有发生数据被…

uniapp-uniCloud的基本使用(编写云存储的地区级联选择器)

目录 新建项目&#xff0c;创建 uniCloud 服务空间并关联 1. 新建项目 2. 创建 uniCloud 服务空间并关联 manifest.json内未配置Appld,请重新获取后再 云数据库的使用 城市选择和云数据库 介绍 云端数据 DB Schema概述 新建项目&#xff0c;创建 uniCloud 服务空间并关…

Web前端 ---- 【Vue3】vue3中的组件传值(props、自定义事件、全局事件总线)

目录 前言 props 自定义事件 全局事件总线 安装第三方库mitt 封装event-bus.js文件 使用全局事件总线 清除全局事件绑定 前言 本文介绍在vue3中的组件传值&#xff0c;props、自定义事件以及全局事件总线。相较于vue2中&#xff0c;略有变化。关于vue2中的组件传值看这篇…

坑记(HttpInputMessage)

一、背景知识 public interface HttpInputMessage extends HttpMessage Represents an HTTP input message, consisting of headers and a readable body.Typically implemented by an HTTP request on the server-side, or a response on the client-side.Since: 3.0 Author:…

【python】08.面向对象编程基础

面向对象编程基础 活在当下的程序员应该都听过"面向对象编程"一词&#xff0c;也经常有人问能不能用一句话解释下什么是"面向对象编程"&#xff0c;我们先来看看比较正式的说法。 "把一组数据结构和处理它们的方法组成对象&#xff08;object&#…

【Minio】常见问题解决思路

检查存储服务器对应的端口与应用服务器是否能够互通&#xff0c;通过ping|telnet命令检查、查看防火墙端口是否开放&#xff0c;检查防火墙端口linux系统和windows系统各有不同。检查电脑上的杀毒软件是否限制了网络端口和文件权限问题。检查minio配置信息是否正确&#xff0c;…

linux 如何创建文件

我们在写一些教程的时候&#xff0c;经常会需要创建一些用于演示的文档&#xff0c;这些文档往往需要填充一些不特定的内容。那么如何快速的创建演示用的文档呢&#xff1f; docfaker.py docfaker.py是一个py脚本&#xff0c;用于创建一个简单的txt文档&#xff0c;docfaker.…

备战抖音商城好物年货节,品牌焕发新商机

农历春节前的最后一个月&#xff0c;打工人们逐渐将置办年货提上日程。忙碌了一年的辛苦与疲惫&#xff0c;总能在喜气洋洋买年货的过程中&#xff0c;被一扫而空。这是“年味”的开始&#xff0c;也是公司高管郭广宇面临的一场关键战役。 郭广宇今年35岁&#xff0c;是三只松鼠…

《SRE Google 运维解密》笔记

指导思想 介绍 Google 生产环境介绍 borg 是 k8s 的前身。 拥抱风险 服务质量 现在的 SLO 没有更细粒度的划分到季度 如果划分到季度&#xff0c;需要用这个数据来限制什么或者进行什么活动&#xff1f; L1S 链路的 SLA 的签署工作已经做了很多 对于 SLA 的达成情况数据没有…

HTB-SAU

信息收集 # cat port.nmap # Nmap 7.94 scan initiated Thu Jan 11 19:26:51 2024 as: nmap -sS --min-rate 10000 -p- -oN port.nmap 10.10.11.224 Nmap scan report for 10.10.11.224 (10.10.11.224) Host is up (0.28s latency). Not shown: 65531 closed tcp ports (r…

【RHEL】Vivado调用VCS+Verdi联合仿真报错解决

问题描述 在使用VCS Verdi仿真Vivado工程时&#xff0c;点击行为仿真按钮进度条窗口消失后&#xff0c;Verdi窗口并未出现&#xff0c;查看消息报错如下&#xff1a; vcs: line 34205: 119837 Segmentation fault (core dumped) ${TOOL_HOME}/bin/cfs_ident_exec -f ${X…

OpenCV 基于C++图像读取及存储API函数

OpenCV可以从存储介质中读入图像&#xff0c;也可以将摄像头(Camera)抓取的图像载入内存&#xff0c;然后进行处理。而存储图像就是将内存中的图像数据写入存储介质中&#xff0c;如写入硬盘、优盘等。 OpenCV要读入图像、操作图像。首先要用到Mat类&#xff0c;并且需创建Mat对…