首页 > 系统相关 >【IMX6ULL学习笔记】十四、Linux调用设备树

【IMX6ULL学习笔记】十四、Linux调用设备树

时间:2023-02-18 19:44:23浏览次数:43  
标签:uboot chosen 笔记 fdt Linux IMX6ULL 节点 bootargs

一、设备树在系统中的体现

Linux 内核启动的时候会解析设备树中各个节点的信息,并且在根文件系统的 /proc/device/tree 目录下根据节点名字创建不同文件夹,如图所示:
image
上图就是目录/proc/device-tree 目录下的内容,/proc/device-tree 目录下是根节点“/”的所有属性和子节点。

1、根节点“/”各个属性

根节点属性属性表现为一个个的文件(图中细字体文件),如图中的“#address-cells”、“#size-cells”、“compatible”、“model”和“name”这 5 个文件,它们在设备树中就是根节点的 5 个属性。可以输入 cat 命令来查看 model 和 cat compatible 这两个文件的内容:

cat model
cat compatible

image

2、根节点“/”各子节点

图中各个文件夹(图中粗字体文件夹)就是根节点“/”的各个子节点,比如 “aliases”、“backlight”、“chosen”和“clocks”等等。
/proc/device-tree 目录就是设备树在根文件系统中的体现,同样是按照树形结构组织的,进入/proc/device-tree/soc 目录就可以看到 soc 节点的所有子节点:
image
和根节点“/”一样,上图中的所有文件分别为 soc 节点的属性文件和子节点文件夹。

二、特殊节点

在根节点“/”中有两个特殊的子节点:aliases 和 chosen

1、aliases 子节点

打开 imx6ull.dtsi 文件,aliases 节点内容如下所示:

aliases {
    can0 = &flexcan1;
    can1 = &flexcan2;
    ethernet0 = &fec1;
    ethernet1 = &fec2;
    gpio0 = &gpio1;
    gpio1 = &gpio2;
......
    spi0 = &ecspi1;
    spi1 = &ecspi2;
    spi2 = &ecspi3;
    spi3 = &ecspi4;
    usbphy0 = &usbphy1;
    usbphy1 = &usbphy2;
};

单词 aliases 的意思是“别名”,因此 aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。不过一般会在节点命名的时加上label,然后通过 &label 来访问节点,这样也很方便,而且设备树里面大量的使用 &label 的形式来访问节点。

2、chosen 子节点

chosen 并不是一个真实的设备,chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数。一般 .dts 文件中 chosen 节点通常为空或者内容很少,imx6ull-alientek-emmc.dts 中 chosen 节点内容如下所示:

chosen {
    stdout-path = &uart1;
};

从示例代码中可以看出,chosen 节点仅仅设置了属性“stdout-path”,表示标准输
出使用 uart1。但是当我们进入到 /proc/device-tree/chosen 目录里面,会发现多了 bootargs 这个属性,如图所示:
image
输入 cat 命令查看 bootargs 这个文件的内容,结果如图所示:
image
从图可以看出,bootargs 这个文件的内容为“console=ttymxc0,115200……”,这个就是在 uboot 中设置的 bootargs 环境变量的值。
现在有两个疑点:
①、我们并没有在设备树中设置 chosen 节点的 bootargs 属性,那么图中 bootargs 这个属性是怎么产生的?
②、为何 bootargs 文件的内容和 uboot 中 bootargs 环境变量的值一样?它们之间有什么关系?
前面讲解 uboot 的时候说过,uboot 在启动 Linux 内核的时候会将 bootargs 的值传递给 Linux 内核,bootargs 会作为 Linux 内核的命令行参数,Linux 内核启动的时候会打印出命令行参数(也就是 uboot 传递进来的 bootargs 的值),如图所示:
image
既然 chosen 节点的 bootargs 属性不是我们在设备树里面设置的,那么只有一种可能,那就是 uboot 自己在 chosen 节点里面添加了 bootargs 属性!并且设置 bootargs 属性的值为 bootargs 环境变量的值。因为在启动 Linux 内核之前,只有 uboot 知道 bootargs 环境变量的值,并且 uboot 也知道.dtb 设备树文件在 DRAM 中的位置。
在 uboot 源码中全局搜索“chosen”这个字符串,在 common/fdt_support.c 文件中发现了“chosen”的身影,fdt_support.c 文件中有个 fdt_chosen 函数,此函数内容如下所示:

int fdt_chosen(void *fdt)
{
    int nodeoffset;
    int err;
    char *str; /* used to set string properties */

    err = fdt_check_header(fdt);
    if (err < 0) {
        printf("fdt_chosen: %s\n", fdt_strerror(err));
        return err;
    }

    /* find or create "/chosen" node. */
    nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
    if (nodeoffset < 0)
        return nodeoffset;

    str = getenv("bootargs");
    if (str) {
        err = fdt_setprop(fdt, nodeoffset, "bootargs", str,
        strlen(str) + 1);
        if (err < 0) {
            printf("WARNING: could not set bootargs %s.\n",
            fdt_strerror(err));
            return err;
        }
    }

    return fdt_fixup_stdout(fdt, nodeoffset);
}

第 14 行:调用函数 fdt_find_or_add_subnode 从设备树(.dtb)中找到 chosen 节点,如果没有找到的话就会自己创建一个 chosen 节点。
第 18 行:读取 uboot 中 bootargs 环境变量的内容。
第 20 行:调用函数 fdt_setprop 向 chosen 节点添加 bootargs 属性,并且 bootargs 属性值就是环境变量 bootargs 的内容。
整个流程是如图所示:
image
图中框起来的部分就是函数 do_bootm_linux 函数的执行流程,也就是说
do_bootm_linux 函数会通过一系列复杂的调用,最终通过 fdt_chosen 函数在 chosen 节点中加入了 bootargs 属性。而我们通过 bootz 命令启动 Linux 内核的时候会运行 do_bootm_linux 函数。

三、Linux 内核解析 DTB 文件

Linux 内核在启动的时候会解析 DTB 文件,然后在 /proc/device-tree 目录下生成相应的设备树节点文件。接下来我们简单分析一下 Linux 内核是如何解析 DTB 文件的,流程如图所示:
image
从图中可以看出,在 start_kernel 函数中完成了设备树节点解析的工作,最终实际工作的函数为 unflatten_dt_node。

标签:uboot,chosen,笔记,fdt,Linux,IMX6ULL,节点,bootargs
From: https://www.cnblogs.com/KuDianWanJia/p/17130705.html

相关文章

  • Linux基础 - 解压缩
     tarzcvftd2.tar.gz./testdir/--exclude=df.sh--exclude=a*  #备份时,排除文件和文件目录tar-N'2023-02-1918:00:00'-zcvf/tmp/r.tar.gz/root/   ......
  • 【量化读书笔记】【打开量化投资的黑箱】CH.05. 交易成本模型
    交易是有成本的,除非有足够的理由,否则便不应该进行交易。交易的原因增加盈利的期望值降低亏损的期望值对交易成本的估计过低,会导致交易过于频繁,损失扩大。过高......
  • linux交换分区
    开启swap虚拟交换内存会影响性能,如果内存足够用的话,不建议开启,开启swap主要是为了解决实际内存太小,内存容量不足的情况。swap分区在系统的物理内存不够用的时候,把硬盘空......
  • linux源码解析13- 反向映射RAMP详解
    1.什么是反向映射是一种物理地址反向映射虚拟地址的方法;正向映射:用户访问的虚拟地址,经过多级页表转化,最终映射到物理页面;反向映射:根据物理页面,找到所有映射到这个页面的......
  • 阅读笔记————架构漫谈
    今天阅读了架构漫谈这一博客对于架构的理解有更进一步 通过阅读架构漫谈这几篇文章,我对架构这个名词有了初步的认识。架构,顾名思义,就是结构,正如文中所介绍的那样原始社......
  • linux数据恢复方法
    1 块设备挂载目录后分区丢失后数据恢复方法1.1问题产生操作步骤:分区:fdisk/dev/sdb;n;然后一路回车;最后w保存;可以看到sdb有了一个分区sdb1格式化:mkext3.fs/dev/sdb1......
  • 配置LINUX服务器和GEO数据处理
    1.服务器端Anaconda安装&配置1.1下载Anaconda安装包wgethttps://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh1.2安装bashAnaconda3-2022.05......
  • 架构漫谈--读书笔记
    这几天阅读了王概凯老师的博客《架构漫谈》 架构实际上是解决人的问题。而架构在思考层面上是抽象的,因此做好架构的必备能力就是正确认识概念,概念混杂的后果就是灾难性的......
  • linux命令
    Linux的基础使用命令基本格式Linux执行命令的一般格式:命令名称[命令参数][命令对象]命令名称、命令参数、命令对象之间用空格分隔。命令参数则可以用长格式(-......
  • Linux 服务 | rsyslog
    rsyslog是实现日志功能的服务,用来采集日志信息。主配置文件/etc/rsyslog.conf中,可以设置日志的处理方式。MODULES默认开启的两个imuxsock、imjournalimuxsock......