龙芯平台下的设备树

news/2025/4/2 15:32:38/

设备树

设备树 (Device Tree) ,起源于Arm嵌入式设备. 是一种描述硬件的数据结构.
在最初调试多U多串的龙芯定制化工控平台时,使用过这个接口.

在linux内核中也有对应的设备树的介绍,与BIOS下的描述一一对应.
内核下会优先使用从BIOS内获取的设备树资源,如若没有,将使用内核下默认的设备树资源文件.

文章目录

    • 设备树
      • 设备树从哪里来到哪里去?
      • dts的组成
      • dtc 源码及使用
      • dtb的使用与解析
      • 尾声

设备树从哪里来到哪里去?

.dts(source) .dtb(binary) dtc(compiler) fdtdump(compiler) .dts(source) .dtb(binary)

dts就是所谓的source文件,dtb就是所谓的设备树的binary文件,dtc就是编译工具(编解码).

设备树,摘抄前人的一句话就是:画一棵电路板上CPU、总线、设备组成的树,Bootloader会将这棵树传递给内核,然后内核可以识别这棵树,并根据它展开出Linux内核中的platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ等资源,也被传递给了内核,内核会将这些资源绑定给展开的相应的设备。

dts的组成

dts代码示例: loongson3_ls7a.dts

platform {                                                                                                                                                                                                    compatible = "loongson,nbus", "simple-bus";                                                                                                                                                                 #address-cells = <2>;                                                                                                                                                                                       #size-cells = <1>;                                                                                                                                                                                          enable-lpc-irq;                                                                                                                                                                                             ranges = <0x000 0x00000000 0x000 0x00000000 0x20000000                                                                                                                                                      0x000 0x40000000 0x000 0x40000000 0x40000000                                                                                                                                                            0xe00 0x00000000 0xe00 0x00000000 0x80000000>;                                                                                                                                            uart0: serial@10080000 {                                                                                                                                                                                    device_type = "serial";                                                                                                                                                                                   compatible = "ns16550,loongson";                                                                                                                                                                          reg = <0 0x10080000 0x100>;                                                                                                                                                                               clock-frequency = <50000000>;                                                                                                                                                                             interrupts = <72>;                                                                                                                                                                                        interrupt-parent = <&platic>;                                                                                                                                                                             no-loopback-test;                                                                                                                                                                                         };             gpio: gpio@100e0000 {                                                                                                                                                                                       compatible = "loongson,ls7a-gpio";                                                                                                                                                                        reg = <0 0x100e0000 0xc00>;                                                                                                                                                                               gpio-controller;                                                                                                                                                                                          #gpio-cells = <2>;                                                                                                                                                                                        ngpios = <57>;                                                                                                                                                                                            conf_offset = <0x800>;                                                                                                                                                                                    out_offset = <0x900>;                                                                                                                                                                                     in_offset = <0xa00>;                                                                                                                                                                                      gpio_base = <16>;                                                                                                                                                                                         interrupts = <124>;                                                                                                                                                                                       interrupt-parent = <&platic>;                                                                                                                                                                             };                    

以上剪切了dts的片段,不难发现 Device Tree是由一系列的结点和属性(property)组成的,上图的片段很好的解释了平台上有哪些设备以及设备资源,最终bootloader给到linux的设备信息.

dtc 源码及使用

dts是自然语言,要转化为linux识别的语言dtb,这个转化过程就是通过dtc实现的.

之前,我在UEFI中使用dtc的时候,是编译好的x86工具,现在发现内核中有对应的源码,所以其余平台移植环境也相对应方便了,内核下dtc源码目录:scripts/dtc.
dts->dtb编译方式: dtc –I dts –O dtb –o xxx.dtb xxx.dts

dtb的使用与解析

在龙芯平台下,当使用2.3接口规范时,bios通过在末尾追加dtb的方式进行传递.
话不多说,上代码:

 #ifdef LS3A4000                                                                                                   esys->vers=2;                                                                                                 esys->nr_uarts = 7;                                                                                           esys->of_dtb_addr = PcdGet64(PcdFlashFdBaseAl)+ PcdGet32(PcdFlashFdSize);                                     if((*(volatile UINT32 *)esys->of_dtb_addr) != 0xedfe0dd0 ){                                                   //DEBUG((DEBUG_INFO,"not found dtb or dtb has a bad magic: 0x%x @ 0x%llx\n",*(volatile                        esys->of_dtb_addr = 0;                                                                                        }   
  • 1 在BIOS传递给kernel时,在传参规范中添加了 esys->of_dtb_addr = PcdGet64(PcdFlashFdBaseAl)+ PcdGet32(PcdFlashFdSize); 这段代码,标志dtb的二进制代码由此开始.
  • 2 dtb的第一个32位存取了标志位:(volatile UINT32 *)esys->of_dtb_addr) != 0xedfe0dd0 来判断dtb是否正常有效被追加.
  • 3 如何追加到flash的末尾? 本文使用了一个python脚本,方式不为一,脚本代码见下图:
import sys                                                                                                                                                                                                      
import getopt                                                                                                                                                                                                   def Usage():                                                                                                                                                                                                    print '\tUsage: python BaseTools/dtb.py -f UEFI.fd -d PLATFORM.dtb'                                                                                                                                         exit(1)                                                                                                                                                                                                     def WriteDtb(FileName,Dtb):                                                                                                                                                                                     try:                                                                                                                                                                                                        D = open(Dtb, 'rb')                                                                                                                                                                                     DtbContent = D.read()                                                                                                                                                                                   D.close()                                                                                                                                                                                               except IOError:                                                                                                                                                                                             print 'Can not open', Dtb                                                                                                                                                                               Usage()                                                                                                                                                                                                 try:                                                                                                                                                                                                        F = open(FileName, 'r+')                                                                                                                                                                                F.seek(0,2)                                                                                                                                                                                             F.write(DtbContent)                                                                                                                                                                                     F.close()                                                                                                                                                                                               except IOError:                                                                                                                                                                                             print 'Can not open', FileName                                                                                                                                                                          Usage()                                                                                                                                                                                                 if __name__ == '__main__':                                                                                                                                                                                      try:                                                                                                                                                                                                        Opt, Argv = getopt.getopt(sys.argv[1:],'f:d:')                                                                                                                                                          Opt = dict(Opt)                                                                                                                                                                                         except getopt.GetoptError:                                                                                                                                                                                  Usage()                                                                                                                                                                                                 if '-f' not in Opt or '-d' not in Opt:                                                                                                                                                                      Usage()                                                                                                                                                                                                 WriteDtb(Opt['-f'], Opt['-d'])  

尾声

到这里bios的dts->dtb再到linux内核下的传递就完成了,内核将解析我们传递的dtb获取平台或者处理器信息

彩蛋: 内核下如何解析?
举个例子,内核代码解析Lpc的一些信息:

static bool fw_support_fdt(void)                                                                                  
{                                                                                                                 return !!(esys && esys->vers >= 2 && esys->of_dtb_addr);                                                        
}static void pch_pic_lpc_init(void)                                                                                
{                                                                                                                 struct device_node *np;                                                                                         if (fw_support_fdt()) {                                                                                         np = of_find_compatible_node(NULL, NULL, "simple-bus");                                                       if (np) {                                                                                                     if (of_property_read_bool(np, "enable-lpc-irq")) {                                                          if (of_property_read_bool(np, "lpc-irq-low")) {                                                           writel(0, LS7A_LPC_INT_POL);                                                                            } else {                                                                                                  writel(-1, LS7A_LPC_INT_POL);                                                                           }                                                                                                                                                                                                                             }                                                                                                           }                                                                                                             }                                                                                                               }           

阅读代码,

  • 1 fw_support_fdt: 首先判断我们的版本号支持fdt(dtb),然后按照我们刚才传递的of_dtb_addr是个有效地址.
  • 2 of_find_compatible_node: 查询dts中有simple-bus的节点标识,找到platform的资源.
  • 3 在platform节点内查找enable-lpc-irq? 内核想知道BIOS传递的参数是否有操作lpc中断极性的描述.
  • 4 继续查找是否有lpc-irq-low的语法表达, 如果是,说明固件想要内核将Lpc的中断极性设置为低电平触发,即内核操作相应寄存器进行设置.

这些描述信息相当于复杂一些的自然语言,你应该有一个很好的理解,dts的源文件也可以自定义平台的资源进行描述.


http://www.ppmy.cn/news/866874.html

相关文章

龙芯网站python答案_浏览器编译说明 - 龙芯开源社区

Chromium60编译说明 系统说明 Fedora21系统(Loongson发布的loongnix系统版本为主)—-推荐 Deepin系统 其它系统也可进行源码编译&#xff0c;依赖库有所区别&#xff0c;其它过程都是一样的 代码下载 环境配置 1)安装依赖库 Loongnix系统 yum install gcc-c alsa-lib-devel nin…

龙芯1D处理器用户手册

龙芯1D是超声波热表、水表和气表测量专用SoC 芯片。该芯片集成超声波时间测量、超声波脉冲发生器、温度测量单元、CPU、串口、红外收发器、段式LCD 控制器、电压检测单元、空管检测单元、超声波换能器断线检测等功能部件&#xff0c;配合完善的编程、仿真、调试环境&#xff0c…

龙芯2k按键中断驱动_龙芯2k1000的中断设计

龙芯2k1000的中断设计 1.前言 2.龙芯2k1000的中断描述 2.1 mips设计上的通用中断处理 2.2 龙芯中断的设计 3.龙芯2k1000中断的产生与处理 4.龙芯2k1000中断处理概述 1.前言 中断与异常在任何体系架构的芯片上都不会完全一样。在arm的m系列芯片上需要理解NVIC&#xff0c;这个相…

龙芯派2亚克力外壳

0x0 龙芯派自带的亚克力顶板没有风扇的孔位&#xff0c;在长时间运行时亚克力板很烫&#xff0c;因此我设计了个带风扇孔位的亚克力顶板 效果如下&#xff1a; 风扇规格 4X4风扇 供电由龙芯派的GPIO上的5V管脚供电 使用方法 1.某宝搜索亚克力板定制 2. 将本文件发送给店家…

龙芯网站python答案_记龙芯服务器问题处理

信息 操作系统: Neokylin 7.0 mips64el 故障服务器 10.128.29.206 正常服务器 10.128.29.207 Q:开发同事说在安装完docker并重启docker后操作系统无法连接 A:排查步骤 1. 在办公环境使用笔记本测试联通性 ping 10.128.29.206 畅通 ssh 10.128.29.206 卡住 ssh 10.128.29.207 正…

Linux常用命令——emacs命令

在线Linux命令查询工具 emacs 功能强大的全屏文本编辑器 补充说明 emacs命令是由GNU组织的创始人Richard Stallman开发的一个功能强大的全屏文本编辑器&#xff0c;它支持多种编程语言&#xff0c;具有很多优良的特性。有众多的系统管理员和软件开发者使用emacs。 语法 e…

(数据结构)(C++)数组——约瑟夫环求解

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream>#define MaxSize 10using namespace std;void josephus(int n,int m)//一共n个人数到m的出列 {int p[MaxSize];int i,j,t;for(i0;i<n;i){p[i]i1;//构建初始序列&#xff08;1,2,3,4.....) } t0;//首次报数起始位…

飞利浦电池小课堂|电池也会“发烧”吗?

用了那么多电池 为什么有的电池会发热呢&#xff1f; 电池发热会爆炸吗&#xff1f; 科普小知识 由于短路等多种原因导致电池发生化学反应、发热&#xff0c;十分危险&#xff01; 那么&#xff0c;哪些操作会导致电池发热呢&#xff1f; 1.和金属制品一起保管&#xff1a;…