背景

讲完设备树的有关概念以及语法以后,我们接下来就让 我们的驱动 使用 设备树。

ref : 《内核学习笔记14:内核设备树学习》《u-boot对设备树的支持》

测试代码

本文使用的设备树节点如下:

  1. // 专门用于测试dts的示例,没实例用途
  2. // 名称可以有“,”、“-”,如“ll,i2c-enable”
  3. myfoo {
  4. compatible = "ll,jimkent-foo";
  5. status = "okay"; // string
  6. enable; // bool,无须值
  7. myvalue = <250>; // 默认是32位,如果使用8位读取,结果为0
  8. value = /bits/ 8 <88>; // 8位单独赋值
  9. value16 = /bits/ 16 <166>; // 16位单独赋值
  10. a-cell = <1 2 3 4 5>; // 数组
  11. // 子节点
  12. foo {
  13. label = "foo";
  14. note = "this is foo";
  15. };
  16. bar {
  17. label = "bar";
  18. note = "this is bar";
  19. };
  20. };
  21. // 其中compatible与驱动使用的名称必须一致(这样才能匹配上)。其它内容比较简单,分别是字符串、布尔类型、不同位数的数值、数组、子节点。

驱动实例如下:

  1. /**
  2. * @file foo_drv.c
  3. * @author Late Lee <latelee@163.com>
  4. * @date Wed Jun 7 22:21:19 2019
  5. *
  6. * @brief 测试dts示例
  7. *
  8. * @note 读取dts的值,学习dts。代码有部分警告,不影响
  9. */
  10. #include <linux/module.h>
  11. #include <linux/kernel.h> /**< printk() */
  12. #include <linux/init.h>
  13. #include <linux/types.h> /**< size_t */
  14. #include <linux/errno.h> /**< error codes */
  15. #include <linux/string.h>
  16. #include <linux/of.h>
  17. #include <linux/of_device.h>
  18. static int foo_remove(struct platform_device *dev)
  19. {
  20. printk(KERN_NOTICE "remove...\n");
  21. return 0;
  22. }
  23. static int foo_probe(struct platform_device *dev)
  24. {
  25. int ret = 0;
  26. struct device_node* np = dev->dev.of_node;
  27. struct device_node* child = NULL;
  28. const char* str = NULL;
  29. bool enable = false;
  30. u8 value = 0;
  31. u16 value16 = 0;
  32. u32 value32 = 0;
  33. // 测试dts读取API
  34. if(np == NULL)
  35. {
  36. pr_info("of_node is NULL\n");
  37. return 0;
  38. }
  39. of_property_read_string(np, "status", &str); // 读字符串
  40. enable = of_property_read_bool(np, "enable"); // bool类型,可判断某字段存在不存在
  41. of_property_read_u32(np, "myvalue", &value32); // 一般地,都使用u32读取数值
  42. of_property_read_u8(np, "value", &value);
  43. of_property_read_u16(np, "value16", &value16);
  44. u32 data[3] = {0};
  45. u32 tag = 0;
  46. // a-cell是一个数组,默认读第1个。
  47. of_property_read_u32(np, "a-cell", &tag);
  48. // 也可以读取指定大小的数组(不一定是全部的)
  49. of_property_read_u32_array(np, "a-cell", data, ARRAY_SIZE(data));
  50. printk("of read status: %s enable: %d value: %d %d %d\n", str, enable, value, value16, value32);
  51. printk("of read tag: %d data: %d %d %d\n", tag, data[0], data[1], data[2]);
  52. // 获取子节点个数
  53. int count = of_get_available_child_count(np);
  54. // 遍历所有子节点,按格式读取属性
  55. int index = 0;
  56. for_each_available_child_of_node(np,child)
  57. {
  58. const char* label = of_get_property(child,"label",NULL) ? : child->name;
  59. const char* note = of_get_property(child,"note",NULL) ? : child->name;
  60. printk("of read: label: %s note: %s\n", label, note);
  61. }
  62. return ret;
  63. }
  64. static struct of_device_id foo_of_match[] = {
  65. { .compatible = "ll,jimkent-foo", },
  66. { /* sentinel */ }
  67. };
  68. static struct platform_driver foo_driver = {
  69. .driver = {
  70. .name = "foo",
  71. .of_match_table = of_match_ptr(foo_of_match),
  72. },
  73. .probe = foo_probe,
  74. .remove = foo_remove,
  75. };
  76. static int __init foo_drv_init(void)
  77. {
  78. int ret = 0;
  79. ret = platform_driver_register(&foo_driver);
  80. if (ret)
  81. {
  82. pr_info("platform_driver_register failed!\n");
  83. return ret;
  84. }
  85. pr_info("Init OK!\n");
  86. return ret;
  87. }
  88. static void __exit foo_drv_exit(void)
  89. {
  90. platform_driver_unregister(&foo_driver);
  91. }
  92. module_init(foo_drv_init);
  93. module_exit(foo_drv_exit);
  94. MODULE_AUTHOR("Late Lee");
  95. MODULE_DESCRIPTION("Simple platform driver");
  96. MODULE_LICENSE("GPL");
  97. MODULE_ALIAS("platform:foo");

示例的代码是一个简单的模板,除了学习dts外,没什么用处。但是可以以此展开复杂的、有实际用途的驱动。

与以前的platform驱动不同,platform_driver中指定of_match_tablefoo_of_match结构体的.compatible必须与设备树的compatible一致。

本驱动涉及到的读取设备树节点信息的函数如下,更多函数,参考内核源码的include/linux/of.h头文件:

  1. of_property_read_string // 读取字符串
  2. of_property_read_bool // 判断某个字段是否存在,无须赋值
  3. of_property_read_u8 // 读取8比特
  4. of_property_read_u16 // 读取16比特
  5. of_property_read_u32 // 读取32比特

如果存在多个子节点,用of_get_available_child_count获取个数(可用于开辟内存),然后调用for_each_available_child_of_node遍历所有子节点,注意,of_get_propertyof_property_read_string有相同效果。只是用法不同而已。

设备树DTS 学习:4-编写实战的更多相关文章

  1. 设备树DTS 学习:2-设备树语法

    背景 通过上一讲了解完设备树DTS有关概念,我们这一讲就来基于设备树例程,学习设备树的语法规则. 参考:设备树详解dts.设备树语法详解.设备树使用总结 设备树框架 1个dts文件 + n个dtsi文 ...

  2. 设备树DTS 学习:1-有关概念

    背景 设备树在Linux驱动开发中是一种比较常用的架构. 参考:<设备树DTS使用总结> .<linux内核设备树及编译> Linux设备树 介绍 在Linux 2.6中,ar ...

  3. 设备树DTS 学习:Linux DTS文件加载过程

    背景 了解机制有利于对内核有更深的认识. wget https://mirrors.aliyun.com/linux-kernel/v3.x/linux-3.2.61.tar.xz 内核 在drive ...

  4. 设备树DTS 学习:3-常用的DTS 函数

    Linux内核中目前DTS相关的函数都是以of_前缀开头的,它们的实现位于内核源码的drivers/of下面 void __iomem*of_iomap(struct device_node *nod ...

  5. 设备树DTS 学习: uboot 传递 dtb 给 内核

    背景 得到 dtb 文件以后,我们需要想办法下载到 板子中,并给 Linux 内核使用. (高级版本的 uboot也有了 自己使用设备树支持,我们这里不讨论 uboot 使用的设备树) Linux 内 ...

  6. Linux dts 设备树详解(二) 动手编写设备树dts

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 前言 硬件结构 设备树dts文件 前言 在简单了解概念之后,我们可以开始尝试写一个 ...

  7. Linux 设备树 dts

    1. dtb反编译成dts文件命令:./kernel-4.4/scripts/dtc/dtc_overlay -I dtb -O dts out/target/product/m863ur100_p0 ...

  8. Linux dts 设备树详解(一) 基础知识

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 1 前言 2 概念 2.1 什么是设备树 dts(device tree)? 2. ...

  9. Android驱动之设备树简介

    目录 一.    设备树简介    2 1.    问题一:为什么需要设备树?    2 ①名词解释:    2 ②DT详细介绍:    2 ③DTS是DT的源文件,描述Device Tree中的设备 ...

随机推荐

  1. 指令——mdadm

    Mdadm命令详解 Linux内核中有一个md(multiple devices)模块在底层管理RAID设备,它会在应用层给我们提供一个应用程序的工具mdadm ,mdadm是linux下用于创建和管 ...

  2. UITextField的快速基本使用代码块

    概述 UITextField在界面中显示可编辑文本区域的对象. 您可以使用文本字段来使用屏幕键盘从用户收集基于文本的输入.键盘可以配置许多不同类型的输入,如纯文本,电子邮件,数字等等.文本字段使用目标 ...

  3. SpringBoot+JWT+SpringSecurity+MybatisPlus实现Restful鉴权脚手架

    若图片查看异常,请前往掘金查看:https://juejin.im/post/5d1dee34e51d4577790c1cf4 前言 JWT(json web token)的无状态鉴权方式,越来越流行 ...

  4. 七 Spring的IOC的注解方式

    Spring的IOC的注解方式入门 引入注解约束,配置组件扫描 类上的注解: @Conponent  @Controller @Service @Repository 普通属性的注解   @value ...

  5. Windows驱动开发-DPC定时器

    DCP是一种使用更加灵活的定时器,可以对任意间隔时间进行定时.DPC定时器的内部使用了一个定时器对象KTIMER,当你设定了定时器之后,从设定开始起经过这个时间之后操作系统会将一个DPC定时器的例程插 ...

  6. 布线问题&魔法花园_最短路径

    布线问题 问题描述:印刷电路板将布线区域划分成n×m个方格阵列,精确的电路布线问题要求确定连接方格a到方格b的最短布线方案:布线时,电路只能沿着直线或直角(方格)布线:已经布线的方格被锁定,即不允许其 ...

  7. Linux命令:vmstat命令

    vmstat:虚拟内存状态查看命令 命令选项 vmstat 1         #每秒钟刷新1次 vmstat 1 3      #每秒刷新1次,只刷3次 vmstat -s        #显示内存 ...

  8. Codeforces Round #584 - Dasha Code Championship - Elimination Round (rated, open for everyone, Div. 1 + Div. 2)C

    #define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;string s;pair<int,in ...

  9. Xcode 8 修改已创建工程的 organizion name

    在创建工程时,会需要填写公司信息,对于已创建的工程,新建文件时,公司信息显示为刚开始创建的公司信息.如果需要对公司名称进行修改,需进行以下 可以 打开 工程名.xcodeproj 文件 (显示包内容) ...

  10. nodejs的C++扩展中实现异步回调

    在nodejs的官方网站中有关于C++扩展的详细说明,其中包含了从"hello world"到对象封装的一系列示例.其中的“callback”节是关于回调函数的,美中不足的是,这个 ...