Linux驱动开发(三)---设备树

前文回顾

《Linux驱动开发(一)—环境搭建与hello world》

《Linux驱动开发(二)—驱动与设备的分离设计》

继续宣传一下韦老师的视频

70天30节Linux驱动开发快速入门系列课程【实战教学、技术讨论、直播答疑】

在这里插入图片描述

设备树

前面的设备分离模式,将模块分为了驱动部分和设备部分,设备部分目前也是c语言编写的,但是这样就为内核引入了大量的代码,有点惹怒了linus,然后就引入了设备树这个东西。大佬就是大佬,可靠。

Linux驱动开发(三)---设备树_第1张图片

简单来说,就是通过配置文件的方法,代替device部分的c代码,来描述了设备的信息,参数等。
那么简单一下介绍一下设备树的格式,设备树使用的语言叫DTS语法,可以参考博客《一文搞定 Linux 设备树》

DTS( device tree source)文件通过DTC工具编译为DTB(device tree blob)文件,系统启动时候,会通过解析dtb文件,自动来创建节点和设备。

这些基本知识点还是要掌握,至少要能看得懂一个dts文件的内容大概是什么意思。
Linux驱动开发(三)---设备树_第2张图片

代替device模块

多说无益,还是介绍怎么用DTS配置文件,替换掉device模块。
首先在DTS根节点下增加一个DTS节点,并且要保证其能够生成一个device,而且最重要的是要匹配上对应的driver。
一个例子
Linux驱动开发(三)---设备树_第3张图片
这个comoatible就是我们所要查找的驱动的标记字符串,内容随意,一般都是“厂商,驱动名字”。

这个DTS编译之后,系统启动的时候进行解析,就能够创建对应的节点,然后创建对应的device。是不是很智能,并且还提供了一个pin的参数,其实可以任意提供数据,只要定义好,例如:

	myled_ok: myled_for_test_ok {
		compatible = "100ask,led";
		pin = "gpio5_3";
		para_A = "hello";
		para_B = "world";
	};

Linux驱动开发(三)---设备树_第4张图片

那么,和之前的文章一样,关键点来了,驱动如何和这个device匹配上,那么就需要驱动引入另一个参数of_device_id 。


static const struct of_device_id dts_device_ids[] = {
    { .compatible = "100ask,led", },
    {/* sentinel */}
};


/* A. 实现platform_driver  */
static struct platform_driver led_driver = {
    .probe      = led_probe,
    .remove     = led_remove,
    .driver     = {
        .name   = "100ask_led",
		.of_match_table = dts_device_ids,
    },
    .id_table = led_id_table,
};

这个driver结构中的of_match_table ,里面就提供了,匹配的参数,里面可以定义多个,匹配的就是节点中的compatible 参数。
这样一来。设备和驱动就又匹配上了,自然就可以快乐的执行到driver中的probe函数了。
Linux驱动开发(三)---设备树_第5张图片

参数传递

那么新的问题又来了,之前参数通过device中的resource传递,这下没了resource,多了一个pin参数,那怎么处理呢,方法来了
在probe函数中,入参为platform_device pdev,这个pdev内部有标记,表明是普通的模块device还是设备树创建的device。

前者可以通过platform_get_resource得到参数数据
后者可以通过设备树接口来访问节点,然后得到参数。
例如

if (!pdev->dev.of_node)  /* 普通的platform_device */
	{
		res = platform_get_resource(pdev, IORESOURCE_IRQ, i++);
		if (!res)
			return -EINVAL;
		minor = g_ledcnt;
		leds_desc[minor].pin = res->start;
	}
	else
	{
		of_property_read_string(pdev->dev.of_node, "pin", &tmp_str);
		printk("pin = %s\n", tmp_str);
		minor = g_ledcnt;
		leds_desc[minor].pin = tmp_str[6] - '0';
	}

of_property_read_string就可以读出节点数据中的pin参数。
真是上有政策,下有对策,灵活选择。
Linux驱动开发(三)---设备树_第6张图片
获取参数还可以通过如下几种接口

功能 函数
查找节点 of_find_node_by_path 函数,通过指定全路径来查找指定节点。
提取属性值 of_find_property 函数 ,获取到的值保存到了 property 结构体中。
读整数u32 of_property_read_u32
读整数u64 of_property_read_u64
读某个整数u32 of_property_read_u32_index
读某个整数u64 of_property_read_u64_index
读取属性中数组数据 of_property_read_variable_u8_array
of_property_read_variable_u16_array
of_property_read_variable_u32_array
of_property_read_variable_u64_array
读取属性中字符串值 of_property_read_string 函数。
直接内存映射 of_iomap 函数,获取内存地址所对应的虚拟地址

注意事项

内核中已经有了很多驱动,这些驱动需要的参数,叫什么,其实都已经定义好了,所以我们再增加DTS的时候,需要了解驱动需要定义那些参数,对应提供好即可。
Linux驱动开发(三)---设备树_第7张图片

参考文档

补充知识点可以参考阅读下面博客
《ARM 设备树》

结束语

昨天行程码带星的取消了,大家都开始高兴,说明国家的大趋势已经开始要精准防疫了,不会再一个小区高风险,整个城市受限制了。
希望这个夏天能够去一下海边……
Linux驱动开发(三)---设备树_第8张图片
公司里的技术专家辞职了,可能是受不了各种奇葩的规矩吧,一个从华为出来的人,怕是怎么也理解不了老板的脑回路,对比起华为,我们这里更社会。
Linux驱动开发(三)---设备树_第9张图片
其实这就是人生啊,哪有一帆风顺,都是跌跌撞撞。
Linux驱动开发(三)---设备树_第10张图片

你可能感兴趣的:(驱动开发,操作系统,linux知识,驱动开发,linux)