嵌入式 Linux 啟動流程詳解 (以 ARM + U-Boot 為例)

嵌入式 Linux 啟動流程詳解 (以 ARM + U-Boot 為例)

對于嵌入式開發者而言,深入理解系統的啟動流程至關重要。這不僅有助于進行底層驅動開發和系統移植,還能在遇到啟動失敗等問題時,快速定位和解決。本文將詳細分解基于 ARM 架構的嵌入式 Linux 系統最常見的啟動流程:BootROM -> U-Boot -> Kernel -> RootFS。過段時間仔細研究一下Uboot,看看能不能給手上這塊3506移植個Uboot試試。


在這里插入圖片描述

啟動流程總覽

嵌入式設備的啟動過程是一個環環相扣的鏈條,前一級加載器負責初始化基礎硬件,并加載下一級更復雜的程序,直到最終啟動完整的 Linux 操作系統。

graph TDsubgraph SoC 內部芯片A[電源開啟] --> B(BootROM);endsubgraph 引導加載程序 (Bootloader)B --> |從 Flash/SD卡 加載| C[U-Boot SPL];C --> |初始化DDR| D[U-Boot 主體];endsubgraph 內核與用戶空間D --> |執行 bootcmd| E[加載 Linux 內核 (zImage)];D --> |執行 bootcmd| F[加載設備樹 (DTB)];E & F --> G{啟動內核};G --> H[內核初始化硬件];H --> I[掛載根文件系統 (RootFS)];I --> J[執行第一個用戶進程 /sbin/init];J --> K[啟動系統服務與應用];end

1. BootROM - 芯片內的第一行代碼

BootROM 是整個啟動鏈的起點。

  • 是什么:一段固化在 SoC (System on Chip) 芯片內部的只讀存儲器 (ROM) 中的程序。它由芯片制造商編寫,用戶無法修改,是上電后 CPU 執行的第一段代碼
  • 核心職責
    1. 最小化硬件初始化:進行最基礎的硬件設置,如配置內部時鐘、初始化用于加載下一階段代碼的存儲接口(如 SD 卡控制器、eMMC、SPI Flash 等)。
    2. 加載外部引導程序:根據預設的啟動介質順序(通常由一組 BOOT_MODE 引腳的電平狀態決定),從外部存儲設備(Flash, eMMC, SD Card)中查找并加載第二階段的引導加載程序(通常是 U-Boot 的一個小型版本 SPL)到芯片內部的 SRAM 中。
    3. 移交控制權:加載完成后,將 CPU 的執行權限交給這段剛剛加載進來的代碼。

BootROM 的工作非常單一,就是為更強大的 Bootloader 搭建一個最小化的運行環境。


2. U-Boot - 通用引導加載程序

U-Boot (Universal Boot Loader) 是嵌入式領域應用最廣泛的開源引導加載程序。它功能強大,通常分兩個階段執行,以適應嵌入式系統 SRAM 較小的限制。

2.1 第一階段: U-Boot SPL (Secondary Program Loader)

  • SPL 是什么:一個精簡版的 U-Boot,主要目的是初始化 DDR 內存。由于 BootROM 加載 SPL 時使用的是芯片內部的 SRAM,而 SRAM 通常很小(幾十到幾百 KB),無法容納完整的 U-Boot。
  • 核心職責
    1. 初始化 DDR 控制器:這是 SPL 最重要的任務。DDR 內存是運行 Linux 內核和應用程序所必需的大容量內存空間。
    2. 加載 U-Boot 主體:DDR 初始化完成后,SPL 會從外部存儲設備中將完整的 U-Boot 鏡像 (u-boot.img) 加載到 DDR 內存中。
    3. 跳轉執行:將控制權移交給位于 DDR 中的 U-Boot 主體。

2.2 第二階段: U-Boot 主體

這是我們通常所說的 U-Boot,它功能完善,為啟動 Linux 內核提供了所有必要的準備。

  • 核心職責
    1. 全面的硬件初始化:初始化系統所需的各種外設,如串口(用于打印啟動日志和提供命令行交互)、網絡接口(用于網絡啟動和調試)、存儲設備(eMMC, NAND)等。
    2. 設置內核啟動參數 (bootargs):這是 U-Boot 的一個關鍵功能。它會設置一個名為 bootargs 的環境變量,然后將其傳遞給 Linux 內核。這個參數字符串告訴內核一些重要的初始配置,例如:
      • console=ttyS0,115200:指定內核使用哪個串口作為控制臺,以及波特率。
      • root=/dev/mmcblk0p2 rootwait:指定根文件系統的位置(例如在 SD 卡的第 2 個分區),并讓內核等待設備就緒。
      • rootfstype=ext4:指定根文件系統的類型。
    3. 加載內核和設備樹:根據 bootcmd 環境變量中定義的命令(或手動輸入),從存儲介質(或通過網絡 TFTP)中將 Linux 內核鏡像 (zImage) 和設備樹文件 (.dtb) 加載到 DDR 內存的指定地址。
    4. 啟動內核:執行 bootzbootm 命令,將設備樹文件的內存地址傳遞給內核,然后跳轉到內核的入口點,正式開始 Linux 系統的啟動。

3. Linux Kernel - 操作系統的核心

內核接管控制權后,標志著真正的操作系統開始運行。

  1. 內核自解壓zImage 是一個壓縮的鏡像,所以第一步是在內存中將自己解壓出來。
  2. 解析設備樹 (DTB):內核會讀取 U-Boot 傳遞過來的 DTB 文件。DTB 描述了板級的所有硬件信息,內核根據這些信息來初始化對應的驅動程序。這使得內核代碼可以與硬件解耦,一份內核源碼可以適配不同的開發板。
  3. 初始化硬件:內核開始全面初始化由 DTB 描述的所有硬件設備,并建立起驅動模型、內存管理、進程調度等核心子系統。
  4. 掛載根文件系統 (RootFS):內核根據 bootargs 中的 root 參數,找到并掛載根文件系統。
    • 在開發階段,常常使用 NFS (Network File System),方便快速修改和調試。
    • 在量產產品中,根文件系統通常存放在 eMMC 或 Flash 的一個分區上,格式為 ext4, squashfs (只讀壓縮), ubifs (用于 NAND Flash) 等。
  5. 啟動 init 進程:根文件系統被掛載后,內核會創建并運行第一個用戶空間的進程 /sbin/init(其 PID 永遠為 1)。內核的初始化工作到此結束,后續的用戶空間初始化全權交由 init 進程處理。

4. Init 與用戶空間

init 進程是所有用戶空間進程的“始祖”。它的任務是根據配置文件,將系統帶入一個可用的狀態。

  • 常見的 init 程序:
    • BusyBox init:在資源受限的嵌入式系統中非常流行。它解析 /etc/inittab 文件,按順序執行其中的腳本來啟動系統服務。
    • SystemV init:傳統的 init 系統,同樣使用 /etc/inittab 和運行級別 (Runlevel) 腳本 (/etc/rc.d/)。
    • systemd:現代 Linux 發行版的主流選擇,功能強大,并行啟動速度快,但在嵌入式領域有時被認為過于復雜和龐大。
  • 執行流程init 進程會運行一系列啟動腳本,這些腳本會:
    • 掛載其他必要的文件系統(如 /proc, /sys, /tmp)。
    • 配置網絡。
    • 啟動系統日志、SSH 服務等后臺守護進程。
    • 最終,啟動核心的應用程序

當用戶的應用程序成功運行起來后,整個嵌入式 Linux 系統的啟動流程便宣告完成。

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

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

相關文章

在前端開發中,html中script 的type分別有哪幾種?分別什么情況用到?

以下是 HTML 中<script>標簽type屬性的常見取值、說明及使用場景&#xff1a;type 值說明使用場景不寫&#xff08;空值&#xff09;HTML5 中默認等同于text/javascript&#xff0c;表示普通 JavaScript 腳本絕大多數傳統 JavaScript 代碼&#xff0c;包括內聯腳本和外部…

2025職教技能大賽汽車制造與維修賽道速遞-產教融合實戰亮劍?

各位職教同仁&#xff0c;2025年世界職業院校技能大賽總決賽爭奪賽&#xff08;汽車制造與維修賽道&#xff09;國內賽區的戰報新鮮出爐&#xff01;本次大賽以“技炫青春 能創未來”為主題&#xff0c;聚焦汽車產業鏈高質量發展需求&#xff0c;在真實場景中比拼技能&#xff…

日志 | Spring Boot 日志配置通用規律(AI問答)

Spring Boot 日志配置通用規律。想看特定日志&#xff0c;怎么打開日志開關 文章目錄一、一句話總結二、AI問答版提問詞AI的響應&#x1f4ca; Spring Boot 日志配置通用規律1. 基本語法結構2. 日志級別&#xff08;從詳細到簡潔&#xff09;&#x1f3af; 常用日志配置分類1. …

DJANGO后端服務啟動報錯及解決

1.報錯信息[2025-09-05 17:08:54 0800] [23438] [INFO] Worker exiting (pid: 23438) [2025-09-05 17:08:54 0800] [23440] [ERROR] Exception in worker process Traceback (most recent call last):File "/www/SOP/lib64/python3.11/site-packages/gunicorn/arbiter.py&…

Qt 中的 Q_OBJECT 宏詳解 —— 從源碼到底層機制的全面剖析

Qt 中的 Q_OBJECT 宏詳解 —— 從源碼到底層機制的全面剖析 文章目錄Qt 中的 Q_OBJECT 宏詳解 —— 從源碼到底層機制的全面剖析摘要一、Q_OBJECT 宏是什么&#xff1f;二、Q_OBJECT 宏背后的源碼三、moc 工具的作用四、信號與槽調用流程五、沒有 Q_OBJECT 會怎樣&#xff1f;六…

GD32自學筆記:5.定時器中斷

定時器中斷功能主要是兩點&#xff1a;1.怎么配置的定時器中斷時間間隔&#xff1b;2.中斷里長什么樣一、定時器中斷配置函數直接在bsp_basic_timer.c里找到下面函數&#xff1a;void basic_timer_config(uint16_t pre,uint16_t per) {/* T 1/f, time T * pre,pertime (pre …

[Godot入門大全]目錄

1 免責聲明 資源分享免責聲明&#xff1a; 本平臺/本人所分享的各類資源&#xff08;包括但不限于文字、圖片、音頻、視頻、文檔等&#xff09;&#xff0c;均來源于公開網絡環境中的可分享內容或已獲授權的傳播素材。 本平臺/本人僅出于信息交流、資源共享之目的進行傳播&…

使用 StringRedisTemplate 實現 ZSet 滾動查詢(處理相同分數場景)

1. 為什么需要改進當 ZSet 中存在相同分數 (score) 的元素時&#xff0c;單純使用分數作為偏移會導致數據漏查或重復。例如&#xff1a;多條記錄具有相同時間戳&#xff08;作為分數&#xff09;分頁查詢時可能跳過相同分數的元素或重復查詢相同分數的元素改進方案&#xff1a;…

【Android】安裝2025版AndroidStudio開發工具開發老安卓舊版App

為了開發老舊的安卓App&#xff0c;這里記錄一下2025版AndroidStudio的安裝過程&#xff0c;如果卸載以后&#xff0c;可以按照此文章的步驟順利重新安裝繼續使用。 文章目錄安裝包Android SDK新建項目新建頁面構建項目Gradle下載失敗構建失敗構建完成編譯失敗安裝失敗關于APP在…

Python跳過可迭代對象前部元素完全指南:從基礎到高并發系統實戰

引言&#xff1a;跳過前部元素的核心價值在數據處理和系統開發中&#xff0c;跳過可迭代對象的前部元素是常見且關鍵的操作。根據2024年數據處理報告&#xff1a;92%的數據清洗需要跳過文件頭部85%的日志分析需要忽略初始記錄78%的網絡協議處理需跳過頭部信息65%的機器學習訓練…

ConcurrentHashMap擴容機制

ConcurrentHashMap的擴容為了提高效率&#xff0c;是多線程并發的每個線程控制一部分范圍節點的擴容(根據cpu與數組長度確定控制多大范圍)有兩個核心參數sizeCtl&#xff1a;標記擴容狀態 負數時代表正在擴容&#xff0c;存儲量參與擴容的線程數&#xff0c;正數代表出發擴容的…

Spring Cloud Gateway 進行集群化部署

如果將 Gateway 單獨部署為一個服務而不做任何高可用處理&#xff0c;它確實會成為一個單點故障&#xff08;SPOF, Single Point of Failure&#xff09;。如果這個唯一的 Gateway 實例因為服務器宕機、應用崩潰、部署更新或其他任何原因而不可用&#xff0c;那么整個系統的所有…

計算機網絡:以太網中的數據傳輸

以太網中&#xff0c;數據的傳輸依賴于一系列標準化的技術規范&#xff0c;核心包括幀結構封裝、介質訪問控制機制和物理層編碼技術&#xff0c;具體如下&#xff1a; 1. 以“幀&#xff08;Frame&#xff09;”為基本傳輸單元 以太網在數據鏈路層將網絡層的數據包&#xff08;…

元器件--USB TypC接口

USB TypC接口下圖這些都是USB接口A口與B口的區別USB A口和B口最初由USB-IF在1996年引入。根據當時的USB協議&#xff0c;A口主要用于主設備&#xff08;如電腦&#xff09;&#xff0c;而B口則用于從設備&#xff08;如打印機和攝像頭&#xff09;。隨著USB-C接口的日益普及&am…

多線程之HardCodedTarget(type=OssFileClient, name=file, url=http://file)異常

多線程之HardCodedTarget(typeOssFileClient, namefile, urlhttp://file)異常 摘要&#xff1a; 文檔描述了多線程環境下調用Feign客戶端OssFileClient時出現的HardCodedTarget異常。異常發生在異步保存文件到ES時&#xff0c;Feign調用未返回預期結果而直接打印了客戶端對象。…

計算機視覺(十二):人工智能、機器學習與深度學習

人工智能 (AI)&#xff1a;宏大的目標 人工智能是最廣泛、最宏大的概念&#xff0c;它的目標是讓機器能夠模仿人類的智能行為&#xff0c;例如&#xff1a; 推理&#xff1a;像下棋程序一樣&#xff0c;通過邏輯來做決策。規劃&#xff1a;為實現一個目標而制定步驟&#xff0c…

容器元素的滾動條回到頂部

關閉再打開后&#xff0c;容器元素的滾動條回到頂部解決方法&#xff1a;1、通過打開開發者工具&#xff08;F12&#xff09;&#xff0c;找到滾動條所屬元素為 el-textarea__inner&#xff0c;其父類 class"el-textarea content"2、代碼&#xff0c;通過元素的方法 …

分布式專題——2 深入理解Redis線程模型

1 Redis 簡介 1.1 Redis 是什么&#xff1f; Redis 全稱 Remote Dictionary Server&#xff08;遠程字典服務&#xff09;&#xff0c;是一個開源的高性能 Key-Value 數據庫&#xff1b; 官網&#xff1a;Redis - The Real-time Data Platform&#xff1b; 引用官網上的?個…

simd學習

如何查看cpu是否支持simd&#xff1f;# 檢查特定指令集 grep -o avx2 /proc/cpuinfo | head -1 # 檢查AVX2 grep -o sse4 /proc/cpuinfo | head -1 # 檢查SSE4 grep -o avx512 /proc/cpuinfo | head -1 # 檢查AVX512gcc編譯選項&#xff0c;增加支持simd-mavx2 -D__AVX2__SS…

LabVIEW汽車發動機振動測試

以某型號四缸汽油發動機為測試對象&#xff0c;借助 LabVIEW 平臺與高精度數據采集硬件&#xff0c;開展發動機全工況振動測試。通過實時采集缸體、曲軸箱關鍵部位振動信號&#xff0c;分析振動特征與故障關聯&#xff0c;驗證發動機運行穩定性&#xff0c;為后期優化設計提供數…