Linux设备树实例分析Word文档格式.docx
《Linux设备树实例分析Word文档格式.docx》由会员分享,可在线阅读,更多相关《Linux设备树实例分析Word文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
![Linux设备树实例分析Word文档格式.docx](https://file1.bdocx.com/fileroot1/2022-12/14/76e0ef4f-615a-46f9-a998-120260bc9607/76e0ef4f-615a-46f9-a998-120260bc96071.gif)
=
"
100as,leddrv"
;
pin
GROUP_PIN(5,
3)>
};
修改后的设备树文件内容如:
在内核根目录下使用如下命令编译设备树源文件:
makedtbsV=1
然后把设备树文件与可加载的led驱动模块、led应用程序上传到板子里:
上传成功的文件如下:
运行测试:
实验过程分析
这个实验的led驱动同样依赖的是总线设备驱动模型。
描述设备有两种方法:
一种是直接用platform_device结构体来指定,另一种是用设备树来指定。
在本次的实验中我们就是用设备树来描述设备。
之前我们用platform_device结构体来指定设备信息时,platform_driver是直接从platform_device结构体里拿资源的,如:
现在我们用设备树来指定设备信息时,platform_driver是如何获取相关资源的呢大致过程如下:
这里我们还需要注意的一点是:
并不是所有的设备树节点都可以转换为platform_device。
下面看看几条规则:
根节点下含有compatile属性的子节点能转换为platform_device;
含有特定compatile属性(它的值是"
simple-bus"
"
simplemfd"
isa"
arm,amba-bus"
四者之一)的节点的子节点能转换为platform_device;
I2C、SPI总线节点下的子节点
不不不能转换为platform_device,这些总线下的子节点,应该交给对应的总线驱动程序来处理。
下面看一个例子:
接下来,我们简单来看一下platform_device与platform_driver匹配的函数:
这里,我们来看第二种匹配方式(使用设备树时的匹配方式)。
下面看看具体如何匹配:
其中过程①优先匹配,其次是过程②,最后是过程③。
但是,实际上现在主要使用的是过程①的匹配,即匹配compatible属性。
过程②与过程③已经过时了,Linux内核不推荐使用这两种匹配方法。
在本次实验中,我们的匹配示意图如下:
实验代码
1、应用程序:
int
main(int
argc,
char
**argv)
fd;
status;
/*
1.
判断参数
*/
if
(argc
!
3)
printf("
Usage:
%s
dev>
on
off>
\n"
argv[0]);
return
-1;
}
2.
打开文件
fd
open(argv[1],
O_RDWR);
(fd
==
-1)
can
not
open
file
%s\n"
argv[1]);
3.
写文件
(0
strcmp(argv[2],
on"
))
status
1;
write(fd,
&
status,
1);
else
0;
close(fd);
运行测试命令:
./ledtest
/dev/100ask_led0
on
off
intmain(intargc,char**argv)形式的main函数相关笔记:
main()函数有哪几种形式。
2、驱动层
这一层主要是放一些通用的驱动操作函数,核心代码如:
驱动程序入口函数:
open、write函数:
其它代码:
其中led的操作结构体如下:
3、硬件层:
这一层主要是一些寄存器相关的操作,及platform_driver相关。
与上一个实验代码不同的部分就是这个文件。
(1)驱动初始化函数:
(2)probe函数:
当设备树的compatible属性与platform_driver中的设备匹配表中的compatible成员互相匹配时会执行此函数获取设备信息。
这里的pin属性与compatible属性(标准属性)类别不同,pin属性是个自定义属性。
我们可以使用of_property_read_u32函数来获取这些自定义属性的内容。
这些函数大多在文件
include/linux/
中可以找到:
(3)led寄存器操作相关的代码:
寄存器物理地址
CCM_CCGR1_BASE
(0X020C406C)
SW_MUX_GPIO5_IO03_BASE
(0X02290014)
GPIO5_DR_BASE
(0X020AC000)
GPIO5_GDIR_BASE
(0X020AC004)
映射后的寄存器虚拟地址指针
static
void
__iomem
*CCM_CCGR1;
*SW_MUX_GPIO5_IO03;
*GPIO5_DR;
*GPIO5_GDIR;
初始化LED,
which-哪个LED
*/
board_demo_led_init
(int
which)
{
group,
pin;
unsigned
val;
group
GROUP(g_ledpins[which]);
PIN(g_ledpins[which]);
printk("
init
gpio:
%d,
%d\n"
pin);
/*100ask_IMX6uLL_BoardLED:
GPIO5_3*/
((5
group)
(3
pin))
相关寄存器物理地址与虚拟地址之间的映射
/*1、地址映射:
时钟寄存器
CCM_CCGR1
ioremap(CCM_CCGR1_BASE,
4);
/*2、地址映射:
模式寄存器
SW_MUX_GPIO5_IO03
ioremap(SW_MUX_GPIO5_IO03_BASE,
/*3、地址映射:
数据寄存器
GPIO5_DR
ioremap(GPIO5_DR_BASE,
地址映射:
方向寄存器
GPIO5_GDIR
ioremap(GPIO5_GDIR_BASE,
使能GPIO5时钟
val
readl(CCM_CCGR1);
读出当前CCM_CCGR1配置值
~(3
30);
清除以前的设置
|=
设置新值
writel(val,
CCM_CCGR1);
设置GPIO5_IO03的为IO模式
writel(5,
SW_MUX_GPIO5_IO03);
设置GPIO5_IO03方向为输出
readl(GPIO5_GDIR);
~(1
3);
(1
GPIO5_GDIR);
This
is
100ask_IMX6ULL_Board!
);
控制LED,
which-哪个LED,
status:
1-亮,0-灭
board_demo_led_ctl
which,
status)
点灯
status)
led
on>
>
readl(GPIO5_DR);
GPIO5_DR);
灭灯
else
val|=
else{}
4、Makefile文件
运行测试
这在文章开头的体验设备树一节中也有演示测试结果:
同时,在目录/sys/firmware/devicetree/base下,我们可以查看设备树节点:
可以看到,我们创建的设备树节点100ask_led@0也在该目录下。
100ask_led@0节点本身就是一个文件夹,可以使用cd命令进入该文件夹查看该节点的属性信息:
属性值是字符串时,用cat命令可以打印出来;
属性值是数值时,用hexdump命令可以打印出来。