1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新
第四十四章 设备树下的LED驱动实验
上一章我们详细的讲解了设备树语法以及在驱动开发中常用的OF函数,本章我们就开始第一个基于设备树的Linux驱动实验。本章在第四十二章实验的基础上完成,只是将其驱动开发改为设备树形式而已。
44.1 设备树LED驱动原理 在《第四十二章 新字符设备驱动实验》中,我们直接在驱动文件newchrled.c中定义有关寄存器物理地址,然后使用io_remap函数进行内存映射,得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对GPIO的初始化。本章我们在第四十二章实验基础上完成,本章我们使用设备树来向Linux内核传递相关的寄存器物理地址,Linux驱动文件使用上一章讲解的OF函数从设备树中获取所需的属性值,然后使用获取到的属性值来初始化相关的IO。本章实验还是比较简单的,本章实验重点内容如下: ①、在imx6ull-alientek-emmc.dts文件中创建相应的设备节点。 ②、编写驱动程序(在第四十二章实验基础上完成),获取设备树中的相关属性值。 ③、使用获取到的有关属性值来初始化LED所使用的GPIO。 44.2 硬件原理图分析 本章实验硬件原理图参考8.3小节即可。 44.3 实验程序编写 本实验对应的例程路径为:开发板光盘-> 2、Linux驱动例程-> 4_dtsled。 本章实验在四十二章实验的基础上完成,重点是将驱动改为基于设备树的. 44.3.1 修改设备树文件 在根节点“/”下创建一个名为“alphaled”的子节点,打开imx6ull-alientek-emmc.dts文件,在根节点“/”最后面输入如下所示内容: 示例代码44.3.1.1 alphaled节点
1 alphaled {
2 #address-cells = ;
3 #size-cells = ;
4 compatible = "atkalpha-led";
5 status = "okay";
6 reg = ; /* GPIO1_GDIR_BASE */
11 };
第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所示:
图44.3.1.1 alphaled节点 如果没有“alphaled”节点的话请重点查看下面两点: ①、检查设备树修改是否成功,也就是alphaled节点是否为根节点“/”的子节点。 ②、检查是否使用新的设备树启动的Linux内核。 可以进入到图44.3.1中的alphaled目录中,查看一下都有哪些属性文件,结果如图44.3.1.2所示:
图44.3.1.2 alphaled节点文件 大家可以查看一下compatible、status等属性值是否和我们设置的一致。 44.3.2 LED灯驱动程序编写 设备树准备好以后就可以编写驱动程序了,本章实验在第四十二章实验驱动文件newchrled.c的基础上修改而来。新建名为“4_dtsled”文件夹,然后在4_dtsled文件夹里面创建vscode工程,工作区命名为“dtsled”。工程创建好以后新建dtsled.c文件,在dtsled.c里面输入如下内容: 示例代码44.3.2.1 dtsled.c文件内容
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 /***************************************************************
17 Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
18 文件名 : dtsled.c
19 作者 : 左忠凯
20 版本 : V1.0
21 描述 : LED驱动文件。
22 其他 : 无
23 论坛 : www.openedv.com
24 日志 : 初版V1.0 2019/7/9 左忠凯创建
25 ***************************************************************/
26 #define DTSLED_CNT 1 /* 设备号个数 */
27 #define DTSLED_NAME "dtsled" /* 名字 */
28 #define LEDOFF 0 /* 关灯 */
29 #define LEDON 1 /* 开灯 */
30
31 /* 映射后的寄存器虚拟地址指针 */
32 static void __iomem *IMX6U_CCM_CCGR1;
33 static void __iomem *SW_MUX_GPIO1_IO03;
34 static void __iomem *SW_PAD_GPIO1_IO03;
35 static void __iomem *GPIO1_DR;
36 static void __iomem *GPIO1_GDIR;
37
38 /* dtsled设备结构体 */
39 struct dtsled_dev{
40 dev_t devid; /* 设备号 */
41 struct cdev cdev; /* cdev */
42 struct class *class; /* 类 */
43 struct device *device; /* 设备 */
44 int major; /* 主设备号 */
45 int minor; /* 次设备号 */
46 struct device_node *nd; /* 设备节点 */
47 };
48
49 struct dtsled_dev dtsled; /* led设备 */
50
51 /*
52 * @description : LED打开/关闭
53 * @param - sta : LEDON(0) 打开LED,LEDOFF(1) 关闭LED
54 * @return : 无
55 */
56 void led_switch(u8 sta)
57 {
58 u32 val = 0;
59 if(sta == LEDON) {
60 val = readl(GPIO1_DR);
61 val &= ~(1
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?