小張學linux核心 七 裝置樹的使用

2021-10-07 22:01:41 字數 3449 閱讀 1046

在很久之前的版本,uboot還需要傳machine id和引數區位址給核心,但現在只傳遞裝置樹(fdt)的位址給核心了,這些引數全在fdt中做了。uboot將裝置樹bin檔案和kernel載入到記憶體,然後將fdt位址傳給kernel,跳到kernel位址執行。fdt為平坦裝置樹,即數作為乙個乙個節點順序存在bin檔案中,不再保持樹的形狀。

我們來看看裝置樹bin檔案dtb的檔案結構

分頭部引數區,記憶體保留對映區,裝置樹結構區,和字串區。當然我們只需要關注裝置樹的節點儲存區,字串區儲存的是屬性的名稱字串,因為好多屬性都是共有的,可以復用。

頭部引數區:

struct boot_param_header ;
來看看節點的結構

節點其實開頭結尾和屬性開頭結尾的magic word

#define fdt_magic   0xd00dfeed  /* 4: version, 4: total size */

#define fdt_tagsize sizeof(uint32_t)

#define fdt_begin_node 0x1 /* start node: full name */

#define fdt_end_node 0x2 /* end node */

#define fdt_prop 0x3 /* property: name off,

size, content */

#define fdt_nop 0x4 /* nop */

#define fdt_end 0x9

#define fdt_v1_size (7*sizeof(uint32_t))

#define fdt_v2_size (fdt_v1_size + sizeof(uint32_t))

#define fdt_v3_size (fdt_v2_size + sizeof(uint32_t))

#define fdt_v16_size fdt_v3_size

#define fdt_v17_size (fdt_v16_size + sizeof(uint32_t))

好了,了解了dtb的檔案結構,我們來實戰下編譯dtb檔案並解析。

dts檔案如下:

/dts-v1/;

/ ; };

};

注意開頭的/dts-v1/;宣告,不然編不過

使用dtc工具將其編譯:

dtc -o dtb -b 0 -o demo.dtb demo.dts
我們使用核心中libfdt庫進行解析 。

既然是裝置樹,我們可以以目錄樹的方式來解析,如以上節點可以通過/memory/cma來訪問,上**,讀取和修改reg屬性的值。

#include #include #include #include #include #include #include "libfdt.h"

#define dtb_file_name "demo.dtb"

unsigned long get_file_size(const char *path)

else

return filesize;

} int main()

dtb_size = get_file_size(dtb_file_name);

if (dtb_size < 0)

printf("dtb file: %s size:%d\n", dtb_file_name, dtb_size);

dtb_buf = malloc(dtb_size);

if (null == dtb_buf)

memset(dtb_buf, 0, dtb_size);

ret = read(fd, dtb_buf, dtb_size);

if (ret != dtb_size)

ret = fdt_check_header(dtb_buf);

if (ret != 0)

else

int nodeoffset = fdt_path_offset(dtb_buf, "/memory/cma");

if (nodeoffset < 0)

int len;

const void *nodep = fdt_getprop(dtb_buf, nodeoffset, "reg", &len);

if (len == 0 || nodep == null)

unsigned int *p_data = (unsigned int *)nodep;

printf("ddr0: start: %#x, len:%#x ddr1: start: %#x, len:%#x\n",

ntohl(p_data[0]), ntohl(p_data[1]), ntohl(p_data[2]), ntohl(p_data[3]));

unsigned int val[4] = ;

val[0] =htonl(0x600000);

val[1] = htonl(0x100000);

val[2] = htonl(0x800000);

val[3] = htonl(0x200000);

ret = fdt_setprop(dtb_buf, nodeoffset, "reg", val, 16);

if (ret != 0)

nodep = fdt_getprop(dtb_buf, nodeoffset, "reg", &len);

if (len == 0 || nodep == null)

p_data = (unsigned int *)nodep;

printf("affter ddr0: start: %#x, len:%#x ddr1: start: %#x, len:%#x\n",

ntohl(p_data[0]), ntohl(p_data[1]), ntohl(p_data[2]), ntohl(p_data[3]));

exit:

if (!dtb_buf)

if (fd >= 0)

return 0;

}

執行結果:

詳細工程見我的github:

裡面包含makefile,及核心**makefile修改,生成libfdt庫。

小張學linux核心 五 cfs排程類和rt排程類

今天我們來學習排程類cfs和rt排程類。簡述 cfs是絕對公平排程演算法,理想情況下,優先順序相同的兩個task,執行時間應該各佔cpu的50 同理3個則cpu利用率為1 3。但是cfs中弱化了優先順序的概念而是使用權重weight來決定任務的執行時間。例如 3個任務a,b,c權重分別1,2,3 則...

小張學linux核心之資料結構 1 hlist

閱讀linux原始碼時,經常會遇到hlist的使用,hlist,看名稱是雜湊鍊錶的意思,那我們學過hash表,是將一串長的資料物件對映到乙個陣列中,已陣列下標來訪問它所對應的資訊。在學習linux字元驅動時,也接觸到雜湊桶的知識。相同主裝置號對應乙個hash表的槽位,子裝置號則是這個槽位所掛的鍊錶上...

Linux核心 裝置樹操作常用API

核心中用下面的這個結構描述裝置樹中的乙個節點,後面的api都需要乙個device node物件作為引數傳入。include of.h struct device node struct device node 47 節點名 48 裝置型別 50 全路徑節點名 54 父節點指標 55 子節點指標 of...