device_node和platform_device的生成流程

1. machine_desc的匹配

《這篇》有介紹DT_MACHINE_START的一些初始化操作,匹配上就會在后續的初始化中調用DT_MACHINE_START的成員來初始化系統的設備樹,時鐘,中斷等

start_kernelsetup_arch(&command_line);mdesc = setup_machine_fdt(atags_vaddr) //返回成功匹配的machine_desc....unflatten_device_tree(); //將設備樹解析成device_node

1.1 setup_machine_fdt

early_init_dt_verify校驗設備樹,和初始化設備樹指針;然后of_flat_dt_match_machine匹配MACHINE_START定義machine_desc和設備樹

const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
{const struct machine_desc *mdesc, *mdesc_best = NULL;#if defined(CONFIG_ARCH_MULTIPLATFORM) || defined(CONFIG_ARM_SINGLE_ARMV7M)DT_MACHINE_START(GENERIC_DT, "Generic DT based system").l2c_aux_val = 0x0,.l2c_aux_mask = ~0x0,MACHINE_ENDmdesc_best = &__mach_desc_GENERIC_DT;
#endifif (!dt_virt || !early_init_dt_verify(dt_virt))return NULL;mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);if (!mdesc) {const char *prop;int size;unsigned long dt_root;early_print("\nError: unrecognized/unsupported ""device tree compatible list:\n[ ");dt_root = of_get_flat_dt_root();prop = of_get_flat_dt_prop(dt_root, "compatible", &size);while (size > 0) {early_print("'%s' ", prop);size -= strlen(prop) + 1;prop += strlen(prop) + 1;}early_print("]\n\n");dump_machine_table(); /* does not return */}/* We really don't want to do this, but sometimes firmware provides buggy data */if (mdesc->dt_fixup)mdesc->dt_fixup();early_init_dt_scan_nodes();/* Change machine number to match the mdesc we're using */__machine_arch_type = mdesc->nr;return mdesc;
}

1.2 early_init_dt_verify

將設備樹指針給到initial_boot_params,供后續直接對設備樹操作的api使用

bool __init early_init_dt_verify(void *params)
{if (!params)return false;/* check device tree validity */if (fdt_check_header(params))return false;/* Setup flat device-tree pointer */initial_boot_params = params;of_fdt_crc32 = crc32_be(~0, initial_boot_params,fdt_totalsize(initial_boot_params));return true;
}

1.3 of_flat_dt_match_machine

of_flat_dt_match去匹配設備樹跟machine_desc的dt_compat成員

const void * __init of_flat_dt_match_machine(const void *default_match,const void * (*get_next_compat)(const char * const**))
{const void *data = NULL;const void *best_data = default_match;const char *const *compat;unsigned long dt_root;unsigned int best_score = ~1, score = 0;dt_root = of_get_flat_dt_root();while ((data = get_next_compat(&compat))) {score = of_flat_dt_match(dt_root, compat);if (score > 0 && score < best_score) {best_data = data;best_score = score;}}if (!best_data) {const char *prop;int size;pr_err("\n unrecognized device tree list:\n[ ");prop = of_get_flat_dt_prop(dt_root, "compatible", &size);if (prop) {while (size > 0) {printk("'%s' ", prop);size -= strlen(prop) + 1;prop += strlen(prop) + 1;}}printk("]\n\n");return NULL;}pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());return best_data;
}

1.4 of_flat_dt_match

of_fdt_is_compatible通過設備樹指針initial_boot_params找到兼容屬性

static int __init of_flat_dt_match(unsigned long node, const char *const *compat)
{unsigned int tmp, score = 0;if (!compat)return 0;while (*compat) {tmp = of_fdt_is_compatible(initial_boot_params, node, *compat);if (tmp && (score == 0 || (tmp < score)))score = tmp;compat++;}return score;
}

1.5 of_fdt_is_compatible

通過fdt_getprop直接獲取compatible 屬性,并比較字符串來看匹配上沒

static int of_fdt_is_compatible(const void *blob,unsigned long node, const char *compat)
{const char *cp;int cplen;unsigned long l, score = 0;cp = fdt_getprop(blob, node, "compatible", &cplen);if (cp == NULL)return 0;while (cplen > 0) {score++;if (of_compat_cmp(cp, compat, strlen(compat)) == 0)return score;l = strlen(cp) + 1;cp += l;cplen -= l;}return 0;
}

2. device_node的生成

通過上面賦值的initial_boot_params,去將設備樹解析成device_node結構的樹

void __init unflatten_device_tree(void)
{__unflatten_device_tree(initial_boot_params, NULL, &of_root,early_init_dt_alloc_memory_arch, false);/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */of_alias_scan(early_init_dt_alloc_memory_arch);unittest_unflatten_overlay_base();
}

2.1 unflatten_dt_nodes

通過populate_node填充device_node

static int unflatten_dt_nodes(const void *blob,void *mem,struct device_node *dad,struct device_node **nodepp)
{struct device_node *root;int offset = 0, depth = 0, initial_depth = 0;
#define FDT_MAX_DEPTH	64struct device_node *nps[FDT_MAX_DEPTH];void *base = mem;bool dryrun = !base;if (nodepp)*nodepp = NULL;/** We're unflattening device sub-tree if @dad is valid. There are* possibly multiple nodes in the first level of depth. We need* set @depth to 1 to make fdt_next_node() happy as it bails* immediately when negative @depth is found. Otherwise, the device* nodes except the first one won't be unflattened successfully.*/if (dad)depth = initial_depth = 1;root = dad;nps[depth] = dad;for (offset = 0;offset >= 0 && depth >= initial_depth;offset = fdt_next_node(blob, offset, &depth)) {if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))continue;if (!IS_ENABLED(CONFIG_OF_KOBJ) &&!of_fdt_device_is_available(blob, offset))continue;if (!populate_node(blob, offset, &mem, nps[depth],&nps[depth+1], dryrun))return mem - base;if (!dryrun && nodepp && !*nodepp)*nodepp = nps[depth+1];if (!dryrun && !root)root = nps[depth+1];}if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {pr_err("Error %d processing FDT\n", offset);return -EINVAL;}/** Reverse the child list. Some drivers assumes node order matches .dts* node order*/if (!dryrun)reverse_nodes(root);return mem - base;
}

2.2 populate_node

unflatten_dt_alloc分配節點,并通過populate_properties填充各屬性

static bool populate_node(const void *blob,int offset,void **mem,struct device_node *dad,struct device_node **pnp,bool dryrun)
{struct device_node *np;const char *pathp;unsigned int l, allocl;pathp = fdt_get_name(blob, offset, &l);if (!pathp) {*pnp = NULL;return false;}allocl = ++l;np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,__alignof__(struct device_node));if (!dryrun) {char *fn;of_node_init(np);np->full_name = fn = ((char *)np) + sizeof(*np);memcpy(fn, pathp, l);if (dad != NULL) {np->parent = dad;np->sibling = dad->child;dad->child = np;}}populate_properties(blob, offset, mem, np, pathp, dryrun);if (!dryrun) {np->name = of_get_property(np, "name", NULL);if (!np->name)np->name = "<NULL>";}*pnp = np;return true;
}

3. paltform_device的生成

3.1 init_machine

MACHINE_START中含有一個.dt_compat成員,根據設備樹的compatible屬性來--錨定具體的machine_desc,;后續也會用init_machine來通過of_platform_populate,構造platfoem_device

static void __init xxx_dt_init_machine(void)
{/* mmp_entry_vector_init(); */of_platform_populate(NULL, of_default_bus_match_table,xxx_auxdata_lookup, NULL);}static const char *XXX_dt_board_compat[] __initdata = {"id-xxx,id-yyy",NULL,
};DT_MACHINE_START(XXX_DT, "XXX (Device Tree Support)").map_io         = mmp_map_io,.init_irq       = irqchip_init,.init_time      = xxx_init_time,.reserve        = xxx_reserve,.init_machine   = xxx_dt_init_machine,.dt_compat      = xxx_dt_board_compat,.restart        = xxx_arch_restart,
MACHINE_END

3.2 什么時候生成

系統初始化跑完了,在最后會執行kernel_init這個1號進程;去初始化initcall,和其他的一些初始化操作,最后成為用戶層的init進程

start_kernelarch_call_rest_initkernel_initkernel_init_freeabledo_basic_setup()do_initcalls()static int __init customize_machine(void)
{/** customizes platform devices, or adds new ones* On DT based machines, we fall back to populating the* machine from the device tree, if no callback is provided,* otherwise we would always need an init_machine callback.*/if (machine_desc->init_machine)machine_desc->init_machine();return 0;
}
arch_initcall(customize_machine);

3.3 什么節點會被生成

1.一般情況下,只對設備樹中根的一級子節點進行轉換,也就是多級子節點(子節點的子節點)并不處理。

2.但是存在一種特殊情況,就是當某個根子節點的compatible屬性為"simple-bus"、"simple-mfd"、"isa"、"arm,amba-bus"時,當前節點中的一級子節點將會被轉換成platform_device節點。

3.節點中必須有compatible屬性。

const struct of_device_id of_default_bus_match_table[] = {{ .compatible = "simple-bus", },{ .compatible = "simple-mfd", },{ .compatible = "isa", },
#ifdef CONFIG_ARM_AMBA{ .compatible = "arm,amba-bus", },
#endif /* CONFIG_ARM_AMBA */{} /* Empty terminated list */
};

3.4 生成platfoem_device

終于到了產生platfoem_device地方:

(1)不再直接使用設備樹,而是使用前面生成的device_node?

(2)matches作為匹配表(of_default_bus_match_table); lookup作為platform_data(xxx_auxdata_lookup)

(3)生成細節見我們的《這篇》

int of_platform_populate(struct device_node *root,const struct of_device_id *matches,const struct of_dev_auxdata *lookup,struct device *parent)
{struct device_node *child;int rc = 0;root = root ? of_node_get(root) : of_find_node_by_path("/");if (!root)return -EINVAL;pr_debug("%s()\n", __func__);pr_debug(" starting at: %pOF\n", root);for_each_child_of_node(root, child) {rc = of_platform_bus_create(child, matches, lookup, parent, true);if (rc) {of_node_put(child);break;}}of_node_set_flag(root, OF_POPULATED_BUS);of_node_put(root);return rc;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37596.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37596.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37596.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

行列視報表系統制作的報表與廠級監控信息系統(SIS)系統中的報表有什么區別?

廠級監控信息系統是集過程實時監測、優化控制及生產過程管理為一體的廠級自動化信息系統&#xff0c;是處于DCS以及相關輔助程控系統與全廠管理信息系統之間的一套實時廠級監控信息系統&#xff0c;該產品也是本公司的一套獨立產品。 SIS系統中的報表只是其中的一個模塊&#…

混合云管道的未來:集成 MinIO、Tailscale 和 GitHub Actions

數據處理是現代軟件開發的基本實踐。它使團隊能夠自動收集、處理和存儲數據&#xff0c;確保高質量的數據和高效的處理。 在本文中&#xff0c;我們將探討如何建立一個全面的數據處理管道&#xff0c;重點介紹如何使用 Tailscale GitHub Action 進行安全網絡。此設置還將包含 …

植物大戰僵尸雜交版手機下載與安裝全攻略

植物大戰僵尸雜交版是一款深受玩家喜愛的策略冒險游戲&#xff0c;以其豐富的植物種類、多樣的關卡設計和趣味的玩法著稱。本文將為您提供詳細的下載與安裝教程&#xff0c;幫助您快速上手&#xff0c;享受游戲帶來的樂趣。 游戲簡介 植物大戰僵尸雜交版在傳統玩法的基礎上&a…

【機器學習】語音轉文字 - FunASR 的應用與實踐(speech to text)

本文將介紹 FunASR&#xff0c;一個多功能語音識別模型&#xff0c;包括其特點、使用方法以及在實際應用中的表現。我們將通過一個簡單的示例來展示如何使用 FunASR 將語音轉換為文字&#xff0c;并探討其在語音識別領域的應用前景。 一、引言 隨著人工智能技術的不斷發展&am…

linux的安全技術和防火墻

一、安全技術 1.入侵檢測系統&#xff1a;特點式不阻斷網絡訪問&#xff0c;主要式提供報警和事后監督&#xff0c;不主動介入&#xff0c;默默的看著你&#xff08;相當于360安全衛士&#xff09; 2.入侵防御系統&#xff1a;透明模式工作&#xff0c;對數據包&#xff0c;網…

平價高性價比藍牙耳機有哪些?盤點好用平價的藍牙耳機推薦

在當今快節奏的生活中&#xff0c;藍牙耳機已經成為人們日常生活中不可或缺的配件&#xff0c;它們不僅讓我們可以在行走、工作或者鍛煉時享受音樂&#xff0c;還提供了便利的通話功能。然而&#xff0c;市面上藍牙耳機種類繁多&#xff0c;價格相差甚遠&#xff0c;大家往往難…

走進開源企業 | 湖南大學OpenHarmony技術實訓活動在開鴻智谷順利舉辦!

6月24日-6月26日&#xff0c;2024開放原子校源行之湖南大學信息科學與工程學院師生走進開源企業實訓交流活動順利落下帷幕。湖南大學信息科學與工程學院的師生代表團一行90人參與了湖南開鴻智谷數字產業有限公司&#xff08;以下簡稱“開鴻智谷”&#xff09;與母公司拓維信息系…

HEC-HMS水文模型教程

原文鏈接&#xff1a;HEC-HMS水文模型教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247607904&idx5&sn1a210328a3fc8f941b433674d8fe2c85&chksmfa826787cdf5ee91d01b6981ebd89deac3e350d747d0fec45ce2ef75d7cb8009341c6f55114d&token90645021…

放射性單位請問放射性物質的單位cpm、dpm什么意思

放射性單位請問放射性物質的單位cpm、dpm什么意思?和Ci怎樣換算?現在做同位素,搞不清楚劑量了. &#xfffc; anse7esn 1年前 已收到2個回答舉報 &#xfffc;贊 渡海 幼苗 共回答了22個問題采納率&#xff1a;90.9% 舉報 放射性活度單位 放射性核素在單位時間內發生衰變…

vue項目手機錄音

手機實現錄音功能&#xff0c;安卓和蘋果都可。功能&#xff0c;點擊開始錄制錄音后&#xff0c;隨時可以停止錄音&#xff0c;如果不點擊停止最多錄制15秒。 頁面結構 <!--音頻--> <div class"audio-box"><audio id"audioPlayer"controlsc…

修改element-ui日期下拉框datetimePicker的背景色樣式

如圖&#xff1a; 1、修改背景色 .el-date-picker.has-sidebar.has-time { background: #04308D; color: #fff; border: 1px solid #326AFF } .el-date-picker__header-label { color: #ffffff; } .el-date-table th { color: #fff; } .el-icon-d-arrow-left:before { color: …

從零搭建Java酒店預訂系統:實戰指南_01

項目介紹 一、 項目概述 項目背景: 模擬真實酒店預訂流程,實現核心功能角色設定: 顧客、前臺、后勤管理(可選:管理員)技術選型: Java + Spring Boot + 數據庫(MySQL)+ 前端框架(Vue.js/React等)二、 需求分析與功能設計 功能模塊劃分: 用戶模塊:用戶注冊、登錄、…

Postgres14.4(Docker安裝)

Postgres14.4&#xff08;Docker安裝&#xff09; 一&#xff0c;Docker拉取鏡像 docker pull postgres:14.4 #檢查鏡像是否拉取成功 docker images | grep postgres二&#xff0c;新建掛載目錄&#xff0c;并運行容器 mkdir -p /data/postgre/data chmod 777 /data/postgre…

AQS同步隊列、條件隊列源碼解析

AQS詳解 前言AQS幾個重要的內部屬性字段內部類 Node同步隊列 | 阻塞隊列等待隊列 | 條件隊列 重要方法執行鏈同步隊列的獲取、阻塞、喚醒加鎖代碼流程解鎖 條件隊列的獲取、阻塞、喚醒大體流程 調用await()方法1. 將節點加入到條件隊列2. 完全釋放獨占鎖3. 等待進入阻塞隊列4. …

【Python】探索 Pandas 中的 where 方法:條件篩選的利器

那年夏天我和你躲在 這一大片寧靜的海 直到后來我們都還在 對這個世界充滿期待 今年冬天你已經不在 我的心空出了一塊 很高興遇見你 讓我終究明白 回憶比真實精彩 &#x1f3b5; 王心凌《那年夏天寧靜的海》 在數據分析中&#xff0c;Pandas 是一個強大且…

小程序安卓手機點擊uni-data-select 下拉框選擇器會出現藍色陰影

解決方法&#xff1a;在導入的包中找到uni-data-select.vue&#xff0c;接著找到.uni-stat__select樣式&#xff0c;把cursor: pointer去掉。 如果出現穿透問題&#xff0c;uni-select__selector的z-index加高&#xff0c;默認是2。

數據庫MyBatis傳遞數組或集合

應用場景 假設你有兩個表&#xff0c;一個是商品信息表&#xff08;表1&#xff0c;例如商品類別信息&#xff09;&#xff0c;另一個是庫存信息表&#xff08;表2&#xff0c;記錄每種商品的庫存數量&#xff09;。你想知道特定幾個商品類別 &#xff08;通過其ID標識&#xf…

其他OpenAI API和功能

文章目錄 嵌入嵌入如何為ML模型翻譯語言內容審核模型Whisper 和 DALL.E除了文本補全功能,OpenAl用戶還可以使用其他一些功能但如果你想深入了解所有API那么請查看OpenAl的APl reference 頁面。 嵌入 由于模型依賴數學函數,因此它需要數值輸入來處理信息。然而,許多元素(如…

zdppy_api+vue3+antd開發前后端分離的預加載卡片實戰案例

后端代碼 import api import upload import timesave_dir "uploads"async def rand_content(request):key api.req.get_query(request, "key")time.sleep(0.3)return api.resp.success(f"{key} " * 100)app api.Api(routes[api.resp.get(&qu…

UnityUGUI之二 CameraTargetTexture

在我們需要將3D物體呈現在2D視角時就可以使用TargetTexture&#xff0c;若想只顯示3D物體則需改變背景顏色&#xff0c;并且得再增加一個相機