查看: 3528|回复: 0

清风徐来——Zephyr实战篇(3)之DeviceTree

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3304

    主题

    6551

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32091
    最后登录
    2024-5-8
    发表于 2021-9-3 10:04:59 | 显示全部楼层 |阅读模式
    "清风徐来"前期回顾:


    新型物联网操作系统Zephyr介绍
    Zephyr实战篇(1)之环境搭建
    Zephyr实战篇(2)之西(工具)
    Zephyr实战篇(3)之DeviceTree(本文)

    看过前几篇系列文章的小伙伴们应该对这两个新名词不会很陌生,因为这哥俩儿几乎已经贯穿了Zephyr的所有构建阶段。可以说,他们是ZephyrOS的特殊之处,也是ZephyrOS构建系统的基础,通俗点讲,DeviceTree负责ZephyrOS中硬件资源的描述/管理,而Kconfig负责软件代码的管理。


    现在我们开始聊聊DeviceTree,当然,还是先从他是谁聊起。
    DeviceTree(设备树)发源于PowerPC架构,为了消除代码中冗余的各种device注册代码而产生,现在已经成为了Linux的通用机制。
    DeviceTree的结构非常简单,由两种元素组成:Node(节点)、Property(属性)。作为一种用来描述板载硬件资源的层级数据结构。Zephyr使用他来表示支持板子上的可用资源,当然,还包括一些硬件的初始化配置信息。
    本篇所涉及的DeviceTree仅针对于ZephyrOS中所使用的DeviceTree概念,与原生Linux上使用的DeviceTree会有些许不同,特别体现在设备树文件的使用上。
    在Linux下,设备树文件通常会被DTC编译为DTB文件,放到外部存储设备,在启动时,DTB文件会由Bootloader送给内核使用。
    但是,对于资源有限设备,这套机制可能过于庞大。因此,Zephyr采用了一种builtin的方式来使用设备树文件,其过程如下:
    12.png
    首先我们看到,有两种格式的文件作为输入,其中一种叫做Devicetree源文件,这些文件可以理解为设备树文件本身;第二种是Devicetree binding文件,这些文件负责描述设备树文件中的内容,包括数据类型等。


    随后,构建系统会将他们解析处理为C头文件,这里还有一个比较重要的文件,叫做devicetree.h,里面定义了一些工具宏,辅助我们获取设备树节点信息,这样一来,所有包含了devicetree.h的源文件,都可以借助这些宏来访问设备树信息,后面会举例说明。


    接下来,我们来聊聊一个设备树的基本构成:
    13.png
    上图里我们定义了一个最简单的设备树节点,下面来分开说明我们在这里都定义了什么:


    /dts-1/: 指示DTS的版本信息


    / :代表这是一个根节点


    a-node: 一个子节点, 在其中又包含了一个子节点,a-sub-node


    subnode_label: 子节点的label,可以在其他设备树文件中被引用


    foo:一个属性参数,并且有一个值,3,目前支持三种参数类型:
    a) 32-bit整形:<>
    b) 字符串: “hello_world”
    c) 字节: [00 01 1b]


    以上这几个要素就构成了一个最简单的设备树文件,下面我们来看看一个真正反映物理硬件层级的例子,以I2C为例,当I2C控制器拥有下面这一拓扑结构时:
    14.png
    其对应的设备树结构就类似于:
    15.png
    再看一个真正的I2C节点定义的例子,这里的属性就用来描述或是硬件节点配置信息,例如i2c地址。
    16.png
    这一拓扑结构下,对应的设备树文件就是这个样子:
    17.png
    我们来展开说明一下,设备树中的一些重要属性:
    compatible:用来说明当前节点指代了什么硬件设备
    node:设备名字


    reg:用来指定设备的地址,一般由两部分构成,<地址 长度>,例如针对于i2c设备地址就是其对应到i2c控制器中的slave地址。针对于i2c控制器来说,这个地址是其寄存器地址。长度信息可以省略
    status:字符串用来描述当前节点是否有效,包括“okay”,“disabled”, “reserved”, “fail”
    interrupts:描述中断信息,中断号,中断优先级等


    当然,Zephyr的设备树中,往往还会有一个叫做chosen的节点,这个节点往往是赋予节点一个特殊功能,例如挂载uart0为zephyr的控制台输出:
    18.png
    这里我们还看到了一个叫做aliases的节点,这个节点用于为现有节点起一个别名,以供程序调用。




    说完设备树,相信大家一定还记得一个叫做bingding的文件,他是和设备树文件一起作为输入,生成最终的C头文件的,那么他是用来做什么的呢?


    我们知道,设备树是用来描述硬件构成和硬件层级结构的,但是他不会告诉Zephyr构建系统哪些属性/定义是有用的。那么此时就需要bingding文件了,首先他是一个yaml格式的文件,提供了设备树所需要的另一半信息,即属性定义以及哪些属性是必须的,这样一来,构建系统才可以生成正确的代码,同时要注意,bingding文件的名字要和设备树节点定义时的compatible属性中的名字一模一样:
    19.png
    这里是一个ITCM设备树节点对应的bingding文件,指示我们的ITCM节点拥有一个属性,reg,其描述了ITCM的地址和长度。


    最后我们来看看我们要如何使用devicetree.h中提供的工具宏才获取设备树节点信息,假设我们有这么一个设备树节点:
    20.png
    最终会生成类似这样的宏字段:
    21.png
    我们就以获取这个寄存器地址为例进行说明,想要获取寄存器的基地址,我们只需要在程序中调用DT_INST_REG_ADDR(0)即可,0代表的是第一个I2C实例,因为我们的芯片往往会有多个I2C控制器。访问其他信息大致雷同,比如我们想获取中断号信息,可以使用DT_INST_IRQn(0)来获取中断号。其他API还请大家自行探索,小编就不一一举例了。

    简单总结一下,小编今天主要和大家分享了Zephyr中设备树的概念,包括什么是设备树,设备树节点定义,以及最后如何在程序中,通过devicetree.h中提供的API获取设备树节点信息。还是一些比较基础的内容,大家可以自行深入探索。

    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-8 10:13 , Processed in 0.128603 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表