《原子嵌入式Linux驱动开发详解与实战》第四章设备树相关学习
[复制链接]
到设备树这里我感觉我学的很费劲了,没做过LINUX驱动相关,做过一些应用层的,我真的还不了解这设备树操作起来为什么这么复杂,我开始以为原厂提供一些DTS等 我们直接简单调用几个函数就行,没想到各种操作,一阵懵
在图中,树的主干就是系统总线, IIC 控制器、 GPIO 控制器、 SPI 控制器等都是接到系统主线上的分支。IIC 控制器有分为 IIC1 和 IIC2 两种,其中 IIC1 上接了 FT5206 和 AT24C02 这两个 IIC 设备, IIC2 上只接了 MPU6050 这个设备。
设备树源文件扩展名为.dts,但是我们在前面移植 Linux 的时候却一直在使
用.dtb 文件,那么 DTS 和 DTB 这两个文件是什么关系呢? DTS 是设备树源码文件, DTB 是将
DTS 编译以后得到的二进制文件。将.c 文件编译为.o 需要用到 gcc 编译器
设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键—值对。
节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。属性分为:
compatible 属性:“兼容性”属性,compatible 属性用于将设备和驱动绑定起来
model 属性:描述设备模块信息
status 属性:字符串是设备的状态信息
#address-cells 和#size-cells 属性:无符号 32 位整形, #address-cells 和#size-cells 这两个属性可以用在任何拥有子节点的设备中,用于描述子节点的地址信息
reg 属性:reg 属性一般用于描述设备地址空间资源信息
首先修改设备树文件
打开dts文件,添加节点
下面开始编写驱动程序了
这时候需要了解几个函数
of_find_node_by_name 函数通过节点名字查找指定的节点
of_find_node_by_type 函数通过 device_type 属性查找指定的节点
of_find_compatible_node 函数根据 device_type 和 compatible 这两个属性查找指定的节点
of_find_matching_node_and_match 函数通过 of_device_id 匹配表来查找指定的节点
of_find_node_by_path 函数通过路径来查找指定的节点
of_find_property 函数用于查找指定的属性
of_property_count_elems_of_size 函数用于获取属性中元素的数量
of_property_read_string 函数用于读取属性中字符串值
of_n_addr_cells 函数用于获取#address-cells 属性值
of_size_cells 函数用于获取#size-cells 属性值
太多了 有点难
有了上面一些函数的介绍,下面的获取设备树的相关信息才有点头目
注册设备驱动
就和之前的差不太多
237 /* 注册字符设备驱动 */
238 /* 1、创建设备号 */
239 if (dtsled.major) { /* 定义了设备号 */
240 dtsled.devid = MKDEV(dtsled.major, 0);
241 register_chrdev_region(dtsled.devid, DTSLED_CNT,
DTSLED_NAME);
242 } else { /* 没有定义设备号 */
243 alloc_chrdev_region(&dtsled.devid, 0, DTSLED_CNT,
DTSLED_NAME); /* 申请设备号 */
244 dtsled.major = MAJOR(dtsled.devid); /* 获取分配号的主设备号 */
245 dtsled.minor = MINOR(dtsled.devid); /* 获取分配号的次设备号 */
246 }
247 printk("dtsled major=%d,minor=%d\r\n",dtsled.major,
dtsled.minor);
248
249 /* 2、初始化 cdev */
250 dtsled.cdev.owner = THIS_MODULE;
251 cdev_init(&dtsled.cdev, &dtsled_fops);
252
253 /* 3、添加一个 cdev */
254 cdev_add(&dtsled.cdev, dtsled.devid, DTSLED_CNT);
255
256 /* 4、创建类 */
257 dtsled.class = class_create(THIS_MODULE, DTSLED_NAME);
258 if (IS_ERR(dtsled.class)) {
259 return PTR_ERR(dtsled.class);
262 /* 5、创建设备 */
263 dtsled.device = device_create(dtsled.class, NULL, dtsled.devid,
NULL, DTSLED_NAME);
|