1,设备树的引入
2,uboot本身对设备树的支持
3,对uboot中设备树节点解析代码的分析

(1)上一篇文章中提到函数 dm_init_and_scan(bool pre_reloc_only) 中有对设备树节点解析的函数dm_extended_scan_fdt()该函数的主要作用就是扫描设备树中的节点,并创立对应的设备驱动等结构的绑定工作。
先看对应的代码

int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
{
    ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
    //顾名思义,该函数就是扫描设备树并与设备驱动建立联系
    ret = dm_scan_fdt_ofnode_path("/clocks", pre_reloc_only);
    ret = dm_scan_fdt_ofnode_path("/firmware", pre_reloc_only);
    //上面这两个该函数扫描clocks节点和firmware节点
}

重点看第一个函数的具体实现过程

int dm_scan_fdt(const void *blob, bool pre_reloc_only)
{
#if CONFIG_IS_ENABLED(OF_LIVE)
    if (of_live_active())
        return dm_scan_fdt_live(gd->dm_root, gd->of_root,
                    pre_reloc_only);
    else
#endif
    return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
}

由于没有定义OF_LIVE宏,所以该函数最终调用的是dm_scan_fdt_node函数,那么接下来看该函数的实现过程

tatic int dm_scan_fdt_node(struct udevice *parent, const void *blob,
                int offset, bool pre_reloc_only)
{
    int ret = 0, err;
    //从偏移offset处开始一个个的扫描节点(node)
    for (offset = fdt_first_subnode(blob, offset); offset > 0; offset = fdt_next_subnode(blob, offset))
        {
        const char *node_name = fdt_get_name(blob, offset, NULL);
         /*chosen或者firmware节点本身不是一个设备,但是有可能包含其他设备节点,
         扫描其子节点*/
        if (!strcmp(node_name, "chosen") ||
            !strcmp(node_name, "firmware")) {
            pr_debug("parsing subnodes of \"%s\"\n", node_name);

err = dm_scan_fdt_node(parent, blob, offset,
                           pre_reloc_only);
            if (err && !ret)
                ret = err;
            continue;//没有子节点的话则继续扫描下一个节点
        }

if (!fdtdec_get_is_enabled(blob, offset)) {//忽略失能设备
            pr_debug("   - ignoring disabled device\n");
            continue;
        }
        err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL,
                     pre_reloc_only);
        if (err && !ret) {
            ret = err;
            debug("%s: ret=%d\n", node_name, ret);
        }
    }

if (ret)
        dm_warn("Some drivers failed to bind\n");

return ret;
}

int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
           bool pre_reloc_only)
{
    struct driver *driver = ll_entry_start(struct driver, driver);
    const int n_ents = ll_entry_count(struct driver, driver);
    const struct udevice_id *id;
    struct driver *entry;
    struct udevice *dev;
    bool found = false;
    const char *name, *compat_list, *compat;
    int compat_length, i;
    int result = 0;
    int ret = 0;

if (devp)
        *devp = NULL;
    name = ofnode_get_name(node);
    pr_debug("bind node %s\n", name);

compat_list = ofnode_get_property(node, "compatible", &compat_length);
    if (!compat_list) {
        if (compat_length == -FDT_ERR_NOTFOUND) {
            pr_debug("Device '%s' has no compatible string\n",
                 name);
            return 0;//这里直接返回,设备能bind的话,需要设备节点有 compatible 属性
        }

dm_warn("Device tree error at node '%s'\n", name);
        return compat_length;
    }
     //遍历compatible 字符串列表
    for (i = 0; i < compat_length; i += strlen(compat) + 1) {
        compat = compat_list + i;
        pr_debug("   - attempt to match compatible string '%s'\n",
             compat);

for (entry = driver; entry != driver + n_ents; entry++) {
            ret = driver_check_compatible(entry->of_match, &id,
                              compat);
            if (!ret)//遍历driver段表,找到相对应的driver
                break;
        }
        if (entry == driver + n_ents)
            continue;

if (pre_reloc_only) {
            if (!dm_ofnode_pre_reloc(node) &&
                !(entry->flags & DM_FLAG_PRE_RELOC))
                return 0;
        }

pr_debug("   - found match at '%s'\n", entry->name);
        ret = device_bind_with_driver_data(parent, entry, name,
                           id->data, node, &dev);
        if (ret == -ENODEV) {
            pr_debug("Driver '%s' refuses to bind\n", entry->name);
            continue;
        }
        if (ret) {
            dm_warn("Error binding driver '%s': %d\n", entry->name,
                ret);
            return ret;
        } else {
            found = true;
            if (devp)
                *devp = dev;
        }
        break;
    }

if (!found && !result && ret != -ENODEV)
        pr_debug("No match for node '%s'\n", name);

return result;
}

函数device_bind_with_driver_data()最终调用的是device_bind_common()函数。
————————————————
版权声明:本文为CSDN博主「liuduanfei」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/A_orz_/article/details/100657963

【u-boot】u-boot对设备树的节点解析(转)的更多相关文章

  1. 宋牧春: Linux设备树文件结构与解析深度分析(2) 【转】

    转自:https://mp.weixin.qq.com/s/WPZSElF3OQPMGqdoldm07A 作者简介 宋牧春,linux内核爱好者,喜欢阅读各种开源代码(uboot.linux.ucos ...

  2. 我眼中的Linux设备树(二 节点)

    二 节点(node)的表示首先说节点的表示方法,除了根节点只用一个斜杠"/"表示外,其他节点的表示形式如"node-name@unit-address".@前边 ...

  3. Linux设备树(二 节点)

    二 节点(node)的表示 首先说节点的表示方法,除了根节点只用一个斜杠“/”表示外,其他节点的表示形式如“node-name@unit-address”.@前边是节点名字,后边是节点地址.节点名字的 ...

  4. 宋牧春: Linux设备树文件结构与解析深度分析(1) 【转】

    转自:https://mp.weixin.qq.com/s/OX-aXd5MYlE_YoZ3p32qWA 作者简介 宋牧春,linux内核爱好者,喜欢阅读各种开源代码(uboot.linux.ucos ...

  5. linux 设备树及节点引用【转】

    本文转载自:http://blog.csdn.net/KjfureOne/article/details/51972854 1.ARM Linux社区为什么要引入设备树 Linux之父Linus To ...

  6. Linux设备树文件结构与解析深度分析

    Copy from :https://blog.csdn.net/woyimibayi/article/details/77574736 正文开始 1. Device Tree简介 设备树就是描述单板 ...

  7. 基于tiny4412的Linux内核移植 -- 设备树的展开

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  8. 基于tiny4412的Linux内核移植 -- 设备树的展开【转】

    转自:https://www.cnblogs.com/pengdonglin137/p/5248114.html#_lab2_3_1 阅读目录(Content) 作者信息 平台简介 摘要 正文 一.根 ...

  9. 最新内核3.4)Linux 设备树加载I2C client adapter 的流程(内核3.4 高通)【转】

    转自:https://blog.csdn.net/lsn946803746/article/details/52515225 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转 ...

随机推荐

  1. 【VS开发】【计算机视觉】OpenCV读写xml文件《C版本》

    一些简单的XML读写操作,记之于笔记以备忘 主要功能: 1. 创建XML 2. 向XML中存储或者是读取Int float型基本数据 3. 通过创建XML元素,存取复杂的结构如:结构体.矩阵 代码如下 ...

  2. 第十三章 字符串(一)之 String

    这一节来学习String的特性和方法. 一.String对象的不变性 不变性:String对象是由一个final char[] value 数组实现的,因此String对象是不可变的.任何看起来改变S ...

  3. 项目四:Java秒杀系统方案优化-高性能高并发实战

    技术栈 前端:Thymeleaf.Bootstrap.JQuery 后端:SpringBoot.JSR303.MyBatis 中间件:RabbitMQ.Redis.Druid 功能模块 分布式会话,商 ...

  4. linux常用终端命令(三)用户和权限

    三.用户权限相关命令 用户 和 权限的基本概念 用户管理 终端命令 组管理 终端命令 修改权限 终端命令 1.用户和权限的基本概念 1.1.基本概念 用户管理包括 用户 与 组 管理 linux系统中 ...

  5. 对CSRF(跨站请求伪造)的理解

    一.什么是CSRF? CSRF是Cross Site Request Forgery的缩写,翻译过来就是跨站请求伪造.那么什么是跨站请求伪造呢?让我一个词一个词的解释: 1.跨站:顾名思义,就是从一个 ...

  6. MySQL 数据库的备份和恢复

    1.DOS命令 mysqldump /*DOS命令生成文本文件*/ mysqldump -u username -h host -ppassword dbname [tbanme1,tbname2,. ...

  7. 使用kafka-eagle监控Kafka

    # 监控kafka集群,开启监控趋势图使用 # 有一个问题,需要在kafka-server-start.sh文件中配置端口,有如下三种办法 # 第一种:复制并修改kafka目录,比如kafka-1,k ...

  8. 怎样在 Vue 里面绑定样式属性 ?

    在 Vue 里绑定样式属性可以使用 v-bind:class="" 和 v-bind:style="" , 二者都可以接受 变量 / 数组 / 对象. 不同点是 ...

  9. 树莓派安装使用RXTX

    在RaspberryPi树莓派上使用RXTX(RXTX的源码安装)Linux 编译RXTX(JAVA串口开发)源码 如果为windows系统,则使用rxtx比较简单,到http://fizzed.co ...

  10. luogu题解P2502[HAOI2006]旅行--最小生成树变式

    题目链接 https://www.luogu.org/problemnew/show/P2502 分析 一个很\(naive\)的做法是从\(s\)到\(t\)双向BFS这当然会TLE 这时我就有个想 ...