Linux DTS笔记
DTS概念
Device Tree是一种描述硬件的数据结构,由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中):CPU的数量和类别,内存基地址和大小,总线和桥,外设连接,中断控制器和中断使用情况,GPIO控制器和GPIO使用情况,Clock控制器和Clock使用情况。 通常由.dts文件以文本方式对系统设备树进行描述,经过Device Tree Compiler(dtc)将dts文件转换成二进制文件binary device tree blob(dtb),.dtb文件可由Linux内核解析,有了device tree就可以在不改动Linux内核的情况下,对不同的平台实现无差异的支持,只需更换相应的dts文件,即可满足,当然这样会增加内核的体积。
一、头(header)
头主要描述设备树的一些基本信息,例如设备树大小,结构块偏移地址,字符串块偏移地址等。偏移地址是相对于设备树头的起始地址计算的。
struct boot_param_header {
__be32 magic; //设备树魔数,固定为0xd00dfeed
__be32 totalsize; //整个设备树的大小
__be32 off_dt_struct; //保存结构块在整个设备树中的偏移
__be32 off_dt_strings; //保存的字符串块在设备树中的偏移
__be32 off_mem_rsvmap; //保留内存区,该区保留了不能被内核动态分配的内存空间
__be32 version; //设备树版本
__be32 last_comp_version; //向下兼容版本号
__be32 boot_cpuid_phys; //为在多核处理器中用于启动的主cpu的物理id
__be32 dt_strings_size; //字符串块大小
__be32 dt_struct_size; //结构块大小
} ;
二 结构块(struct block)
设备树结构块是一个线性化的结构体,是设备树的主体,以节点node的形式保存了目标单板上的设备信息。 在结构块中以宏OF_DT_BEGIN_NODE标志一个节点的开始,以宏OF_DT_END_NODE标识一个节点的结束,整个结构块以宏OF_DT_END结束。一个节点主要由以下几部分组成
节点开始标志:一般为OF_DT_BEGIN_NODE
节点路径或者节点的单元名(version<3以节点路径表示,version>=0x10以节点单元名表示)
填充字段(对齐到四字节)
节点属性。每个属性以宏OF_DT_PROP开始,后面依次为属性值的字节长度(4字节)、属性名称在字符串块中的偏移量(4字节)、属性值和填充(对齐到四字节)
如果存在子节点,则定义子节点
节点结束标志OF_DT_END_NODE。
三 字符串块
通过节点的定义知道节点都有若干属性,而不同的节点的属性又有大量相同的属性名称,因此将这些属性名称提取出一张表,当节点需要应用某个属性名称时直接在属性名字段保存该属性名称在字符串块中的偏移量
·### 四 machine_desc结构
内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。machine_desc结构体通过MACHINE_START宏来初始化,在代码中, 通过在start_kernel->setup_arch中调用setup_machine_fdt来获取
struct machine_desc {
unsigned int nr; /* architecture number */
const char *name; /* architecturename */
unsigned long atag_offset; /* tagged list (relative) */
const char *const *dt_compat; /* array of device tree* 'compatible' strings */
unsigned int nr_irqs; /* number of IRQs */
#ifdef CONFIG_ZONE_DMA
phys_addr_t dma_zone_size; /* size of DMA-able area */
#endif
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
unsigned char reserve_lp0 :1; /* never has lp0 */
unsigned char reserve_lp1 :1; /* neverhas lp1 */
unsigned char reserve_lp2 :1; /* never has lp2 */
enum reboot_mode reboot_mode; /* default restart mode */
struct smp_operations *smp; /* SMP operations */
bool (*smp_init)(void);
void (*fixup)(structtag *, char **,struct meminfo *);
void (*init_meminfo)(void);
void (*reserve)(void);/* reserve mem blocks */
void (*map_io)(void);/* IO mapping function */
void (*init_early)(void);
void (*init_irq)(void);
void (*init_time)(void);
void (*init_machine)(void);
void (*init_late)(void);
#ifdef CONFIG_MULTI_IRQ_HANDLER
void (*handle_irq)(struct pt_regs *);
#endif
void (*restart)(enum reboot_mode, const char *);
};
本字符串(null 终止)用双引号来表示:string-property = “a string”
“Cells”是由尖括号分隔的32位无符号整数:cell-property = <0xbeef 123 0xabcd1234>
二进制数据是用方括号分隔:binary-property = [0x01 0x23 0x45 0x67];
不同格式的数据可以用逗号连接在一起:mixed-property = “a string”, [0x01 0x23 0x45 0x67], <0x12345678>;
逗号也可以用来创建字符串列表:string-list = “red fish”, “blue fish”;