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

RK3568 Linux驱动学习——设备树下 LED 驱动

前言

上一章详细的讲解了设备树语法以及在驱动开发中常用的 OF 函数,本章就开始
第一个基于设备树的 Linux 驱动实验。

设备树 LED 驱动原理

之前直接在驱动文件 newchrled.c 中定义有关寄存器物理地址,然后使用 io_remap 函数进行内存映射,得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对 GPIO 的初始化。本章使用设备树来向 Linux 内核传递相关的寄存器物理地址,Linux 驱动文件使用上一章讲解的 OF 函数从设备树中获取所需的属性值,然后使用获取到的属性值来初始化相关的 IO。本章实验还是比较简单的,本章实验重点内容如下:

  1. 在 rk3568-atk-evb1-ddr4-v10.dtsi 文件中创建相应的设备节点。
  2. 编写驱动程序(在第七章实验基础上完成),获取设备树中的相关属性值。
  3. 使用获取到的有关属性值来初始化 LED 所使用的 GPIO。

硬件原理图分析

之前已经有了。

实验程序编写

修改设备树文件

在根节点 “/” 下创建一个名为“rk3568_led”的子节点,打开 rk3568-atk-evb1-ddr4-v10.dtsi文件,在根节点“/”最后面输入如下所示内容:

1 rk3568_led {
2     compatible = "atkrk3568-led";
3     status = "okay";
4     reg = <0x0 0xFDC20010 0x0 0x08 /* PMU_GRF_GPIO0C_IOMUX_L */
5            0x0 0xFDC20090 0x0 0x08 /* PMU_GRF_GPIO0C_DS_0 */
6            0x0 0xFDD60004 0x0 0x08 /* GPIO0_SWPORT_DR_H */
7            0x0 0xFDD6000C 0x0 0x08 >;/* GPIO0_SWPORT_DDR_H */
8     };

第 2 行,属性 compatible 设置 rk3568_led 节点兼容为“atkrk3568-led”。
第 3 行,属性 status 设置状态为“okay”。
第 4~7 行,reg 属性,非常重要!reg 属性设置了驱动里面所要使用的寄存器物理地址,比如第 4 行的“0x0 0xFDC20010 0x0 0x08”表示 RK3568 的 PMU_GRF_GPIO0C_IOMUX_L 寄存器,其中寄存器地址为 0xFDC20010,长度为 8 个字节。

设备树修改完成以后在 SDK 顶层目录输入如下命令重新编译一下内核:

./build.sh kernel

编译完成以后得到 boot.img,如下图所示:
内核编译的 boot.img

上图中 boot.img 就是编译出来的内核+设备树打包在一起的文件。烧写方法很简单,分两步:

  1. 开发板进入 LOADER 模式,前提是开发板已经烧写了 uboot,并且 uboot 正常运行。
  2. 打开 RKDevTool 工具,导入配置文件,然后将上图中的 boot.img 放到要烧写的
    目录,然后只烧写 boot.img。

或者可以在 Ubuntu 内如下完成烧写并重启:

cd ~/rk3568_linux_sdk/rockdev
sudo ../tools/linux/Linux_Upgrade_Tool/Linux_Upgrade_Tool/upgrade_tool UL MiniLoaderAll.bin -noreset
sudo ../tools/linux/Linux_Upgrade_Tool/Linux_Upgrade_Tool/upgrade_tool DI -p parameter.txt
sudo ../tools/linux/Linux_Upgrade_Tool/Linux_Upgrade_Tool/upgrade_tool DI -boot boot.img
sudo ../tools/linux/Linux_Upgrade_Tool/Linux_Upgrade_Tool/upgrade_tool RD

烧写完成以后启动开发板。Linux 启动成功以后进入到/proc/device-tree/目录中查看是否有 “rk3568_led”这个节点,结果如下图所示:
rk3568_led 节点

如果没有“rk3568_led”节点的话请重点检查下面两点:

  1. 检查设备树修改是否成功,也就是 rk3568_led 节点是否为根节点“/”的子节点。
  2. 检查是否使用新的设备树启动的 Linux 内核。

可以进入到上图中的 rk3568_led 目录中,查看一下都有哪些属性文件,结果如下图所示:
rk3568_led 节点文件

可以用 cat 命令查看一下 compatible、status 等属性值是否和设置的一致。

LED 灯驱动程序编写

与之前的 LED 很像,改了一些内容。

/* dtsled设备结构体 */
struct dtsled_dev{dev_t devid;			/* 设备号 	 */struct cdev cdev;		/* cdev 	*/struct class *class;		/* 类 		*/struct device *device;	/* 设备 	 */int major;				/* 主设备号	  */int minor;				/* 次设备号   */struct device_node	*nd; /* 设备节点 */
};struct dtsled_dev dtsled;	/* led设备 */

在设备结构体 dtsled_dev 中添加了成员变量 nd,nd 是 device_node 结构体类型指
针,表示设备节点。如果要读取设备树某个节点的属性值,首先要先得到这个节点,一般在设备结构体中添加 device_node 指针变量来存放这个节点。

/* 获取设备树中的属性数据 *//* 1、获取设备节点:rk3568_led */dtsled.nd = of_find_node_by_path("/rk3568_led");if(dtsled.nd == NULL) {printk("rk3568_led node not find!\r\n");goto fail_find_node;} else {printk("rk3568_led node find!\r\n");}/* 2、获取compatible属性内容 */proper = of_find_property(dtsled.nd, "compatible", NULL);if(proper == NULL) {printk("compatible property find failed\r\n");} else {printk("compatible = %s\r\n", (char*)proper->value);}/* 3、获取status属性内容 */ret = of_property_read_string(dtsled.nd, "status", &str);if(ret < 0){printk("status read failed!\r\n");} else {printk("status = %s\r\n",str);}/* 4、获取reg属性内容 */ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 16);if(ret < 0) {printk("reg property read failed!\r\n");} else {u8 i = 0;printk("reg data:\r\n");for(i = 0; i < 16; i++)printk("%#X ", regdata[i]);printk("\r\n");}/* 初始化LED *//* 1、寄存器地址映射 */PMU_GRF_GPIO0C_IOMUX_L_PI = of_iomap(dtsled.nd, 0);PMU_GRF_GPIO0C_DS_0_PI = of_iomap(dtsled.nd, 1);GPIO0_SWPORT_DR_H_PI = of_iomap(dtsled.nd, 2);GPIO0_SWPORT_DDR_H_PI = of_iomap(dtsled.nd, 3);

通过 of_find_node_by_path 函数得到 rk3568_led 节点,后续其他的 OF 函数要使用 device_node。
通过 of_find_property 函数获取 rk3568_led 节点的 compatible 属性,返回值为 property 结构体类型指针变量,property 的成员变量 value 表示属性值。
通过 of_property_read_string 函数获取 rk3568_led 节点的 status 属性值。
通过 of_property_read_u32_array 函数获取 rk3568_led 节点的 reg 属性所有值,并且将获取到的值都存放到 regdata 数组中。将获取到的 reg 属性值依次输出到终端上。
使用 of_iomap 函数一次性完成读取 reg 属性以及内存映射,of_iomap 函数是设备树推荐使用的 OF 函数。

编写测试 APP

这个可以直接用之前一个已经写好的。

编译驱动程序和测试 APP

编译驱动程序

编写 Makefile 文件,本章实验的 Makefile 文件和之前基本一样,只是将 obj-m 变量的值改为 dtsled.o,Makefile 内容如下所示:

KERNELDIR := /home/xhj/rk3568_linux_sdk/kernel
CURRENT_PATH := $(shell pwd)
obj-m := dtsled.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

输入如下命令编译出驱动模块文件:

make ARCH=arm64 //ARCH=arm64 必须指定,否则编译会失败

编译成功以后就会生成一个名为“dtsled.ko”的驱动模块文件。

编译测试 APP

输入如下命令编译测试 ledApp.c 这个测试程序:

/opt/atk-dlrk356x-toolchain/bin/aarch64-buildroot-linux-gnu-gcc ledApp.c -o ledApp

编译成功以后就会生成 ledApp 这个应用程序。

运行测试

先在开发板中输入如下命令关闭 LED 的心跳灯功能:

echo none > /sys/class/leds/work/trigger

在 Ubuntu 中将上一小节编译出来的 dtsled.ko 和 ledApp 这两个文件通过 adb 命令发送到开发板的/lib/modules/4.19.232 目录下,命令如下:

adb push dtsled.ko ledApp /lib/modules/4.19.232

发送成功以后进入到开发板目录 lib/modules/4.19.232 中,输入如下命令加载 dtsled.ko 驱动模块:

depmod //第一次加载驱动的时候需要运行此命令
modprobe dtsled //加载驱动

驱动加载成功以后会在终端中输出一些信息,如下图所示:

驱动加载成功

从上图可以看出,rk3568_led 这个节点找到了,并且 compatible 属性值为“atkrk3568-led”,status 属性值为“okay”,reg 属性的值为“0x0 0xFDC20010 0x0 0x08 0x0 0xFDC20090 0x0 0x08 0x0 0xFDD60004 0x0 0x08 0x0 0xFDD6000C 0x0 0x08”,这些都和设置的设备树一致。

驱动加载成功以后就可以使用 ledApp 软件来测试驱动是否工作正常,输入如下命令打开 LED 灯:

./ledApp /dev/dtsled 1 //打开 LED 灯

输入上述命令以后观察开发板上的红色 LED 灯是否点亮,如果点亮的话说明驱动工作正常。在输入如下命令关闭 LED 灯:

./ledApp /dev/dtsled 0 //关闭 LED 灯

输入上述命令以后观察开发板上的红色 LED 灯是否熄灭。如果要卸载驱动的话输入如下命令即可:

rmmod dtsled.ko
http://www.dtcms.com/a/341713.html

相关文章:

  • Redisson最新版本(3.50.0左右)启动时提示Netty的某些类找不到
  • PowerShell脚本检查业务健康状态
  • 解决Docker 无法连接到官方镜像仓库
  • Lecture 6 Kernels, Triton 课程笔记
  • JVM基础知识总结
  • Docker 核心技术:Linux Cgroups
  • GDB 的多线程调试
  • 针对具有下垂控制光伏逆变器的主动配电网络的多目标分层协调电压/无功控制方法的复现
  • 音频读写速度优化 音频格式
  • Transformer内容详解(通透版)
  • pip install -e中e 参数解释
  • 八辊矫平机·第三篇
  • 卸载win10/win11系统里导致磁盘故障的补丁
  • 广东省省考备考(第八十二天8.20)——资料分析、数量、言语(强化训练)
  • 【蒸蒸日上】军八武将篇——标1
  • 8 webUI中-Controlnet(控制与约束)的应用分类与使用方法
  • 【语法】markdown非常用场景
  • Netty HashedWheelTimer设计原理:从时间轮算法到源码实现
  • 跨平台 RTSP/RTMP 播放器工程化实践:低延迟与高稳定性的挑战与突破
  • 【数据分享】东北大鼠疫传播与死亡空间数据
  • Vue透传 Attributes(详细解析)2
  • 恶补DSP:2.F28335的定时器系统
  • 买返商城网站源码多平台购物返现搭建图解源码二开
  • 万象生鲜配送系统 2025 年 8 月 15 日更新日志
  • 八月月报丨MaxKB在教育及教学科研领域的应用进展
  • Hadoop学习
  • 达梦数据库-实时主备集群部署详解(附图文)手工搭建一主一备数据守护集群DW
  • HyDE vs HyPE:AI检索界的‘假想敌’革命,如何让RAG系统从‘找资料’变成‘懂你心’?”
  • Firefox 142 引入 CRLite 用于私有证书撤销
  • 【AI应用】部署AI向量数据库Milvus