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”;