正点原子【第四期】Linux之驱动开发学习笔记-5.1 设备树下的LED驱动实验
前言:
本文是根据哔哩哔哩网站上“正点原子【第四期】手把手教你学Linux系列课程之 Linux驱动开发篇”视频的学习笔记,该课程配套开发板为正点原子alpha/mini Linux开发板。在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
正点原子【第四期】手把手教你学 Linux之驱动开发篇_哔哩哔哩_bilibili
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
正点原子imx6ull-mini-Linux驱动之Linux I2C 驱动实验(21)-CSDN博客
uboot移植(4)--在NXP官方uboot适配ALPHA开发板网络_uboot sr8201f-CSDN博客
正文:
本文是 “正点原子【第四期】手把手教你学 Linux之驱动开发篇-1.1 Linux驱动开发与裸机开发的区别”。本节将参考正点原子的视频教程和配套的正点原子开发指南文档进行学习。
0. 概述
上一章我们详细的讲解了设备树语法以及在驱动开发中常用的OF函数,本章我们就开始第一个基于设备树的 Linux驱动 实验。本章在第四十二章实验的基础上完成,只是将其驱动开发改为设备树形式而已。
1 设备树 LED驱动原理
在《第四十二章 新字符设备驱动实验》中,我们直接在驱动文件 newchrled.c中定义有关寄存器物理地址,然后使用 io_remap 函数进行内存映射,得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对 GPIO的初始化。本章我们在第四十二章实验基础上完成,本章我们使用设备树来向 Linux内核传递相关的寄存器物理地址, Linux驱动文件使用上一章讲解的 OF函数从设备树中获所需的属性值,然后使用获取到的属性值来初始化相关的 IO。本章实验还是比较简单的,本章实验重点内容如下:
①、在 imx6ull-alientek-emmc.dts文件中创建相应的设备节点。
②、编写驱动程序 (在第四十二章实验基础上完成 ),获取设备树中的相关属性值。
③、使用获取到的有关属性值来初始化 LED所使用的 GPIO。
2 硬件原理图分析
本章实验硬件原理图参考8.3小节即可。
3 实验程序编写
本章实验在四十二章实验的基础上完成,重点是将驱动改为基于设备树的 .
3.1 修改设备树文件
在根节 点 ““/”下创建一个名为 alphaled”的子节点,打开 imx6ull-alientek-emmc.dts文件,在根节点“ “/”最后面输入如下所示内容
第 2、 3行,属性 #address-cells和 #size-cells都为 1,表示 reg属性中起始地址占用一个字长(cell),地址长度也占用一个字长 (cell)。
第 4行,属性 compatbile设置 alphaled节点兼容性为“ atkalpha-led”。
第 5行,属性 status设置状态为“ okay”。
第 6~10行, reg属性,非常重要! reg属性设置了驱动里面所要使用的寄存器物理地址,比如第 6行的“ 0X020C406C 0X04”表示 I.MX6ULL的 CCM_CCGR1寄存器,其中寄存器首地址为 0X020C406C,长度为 4个字节。
设备树修改完成以后输入如下命令重新编译一下 imx6ull-alientek-emmc.dts
make dtbs
编译完成以后得到 imx6ull-alientek-emmc.dtb,使用新的 imx6ull-alientek-emmc.dtb启动Linux内核。 Linux启动成功以后进入到 /proc/device-tree/目录中查看是否有“ alphaled”这个节点,结果如图 44.3.1.1所示:图
如果没有“ alphaled”节点的话请重点 查看 下面两点:
①、检查设备树修改是否成功,也就是alphaled节点是否为根节点“ “/”的子节点。
②、检查是否使用新的设备树启动的Linux内核。
可以进入到图44.3.1中的 alphaled目录中,查看一下都有哪些属性文件,结果如图 44.3.1.2所示:
3.2 LED灯驱动程序编写
设备树准备好以后就可以编写驱动程序了,本章实验在第四十二章实验驱动文件newchrled.c的基 础上修改而来。新建名为“ 4_dtsled”文件夹,然后在 4_dtsled文件夹里面创建vscode工程,工作区命名为“ dtsled”。工程创建好以后新建 dtsled.c文件,在 dtsled.c里面输入如下内容:
dtsled.c文件中的内容和第四十二章的 newchrled.c文件中的内容基本一样,只是 dtsled.c中包含了处理设备树的代码,我们重点来看一下这部分代码。
第 46行,在设备结构体 dtsled_dev中添加了成员变量 nd, nd是 device_node结构体类型指针,表示设备节点。如果我们要读取设备树某个节点的属性值,首先要先得到这个节点,一般在设备结构体中添加 device_node指针变量来存放这个节点。
第 160~166行,通过 of_find_node_by_path函数得到 alphaled节点,后续其他的 OF函数要使用 device_node。第 169~174行,通过 of_find_property函数获取 alphaled节点的 compatible属性,返回值为property结构体类型指针变量, property的成员变量 value表示属性值。
第 177~182行,通过 of_property_read_string函数获取 alphaled节点的 status属性值。
第 185~194行,通过 of_property_read_u32_array函数获取 alphaled节点的 reg属性所有值,并且将获取到的值都存放到 regdata数组中。第 192行将获取到的 reg属性值依次输出到终端上
。第 199~203行,使用“古老”的 ioremap函数完成内存映射,将获取到的 regdata数组中的寄存器物理地址转换为虚拟地址。
第 205~209行,使用 of_iomap函数一次性完成读取 reg属性以及内存映射, of_iomap函数是设备树推荐使用的 OF函数。
3.3 编写测试 APP
本章直接使用第四十二章的测试 APP,将上一章的 ledApp.c文件复制到本章实验工程下即可。
4 运行测试
4.1 编译驱动程序和测试 APP
1、编译驱动程序
编写 Makefile文件,本章实验的 Makefile文件和第四十章实验基本一样,只是将 obj-m变量的值改为 dtsled.o Makefile内容如下所示:
4.2 运行测试
将上一小节编译出来的 dtsled.ko和 ledApp这两个文件拷贝到 rootfs/lib/modules/4.1.15目录中,重启开发板,进入到目录 lib/modules/4.1.15中,输入如下命令加载 dtsled.ko驱动模块:
从图 44.4.2.1可以看出, alpahled这个节点找到了,并且 compatible属性值为“ atkalpha-ledstatus属性值为“ okay reg属性的值为“ 0X20C406C 0X4 0X20E0068 0X4 0X20E02F4 0X4 0X209C000 0X4 0X209C004 0X4”,这些都和我们设置的设备树一致。
驱动加载成功以后就可以使用 ledApp软件来测试驱动是否工作正常,输入如下命令打开LED灯: