日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

U-Boot 之三 U-Boot 源码文件解析及移植过程详解

發布時間:2024/10/14 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 U-Boot 之三 U-Boot 源码文件解析及移植过程详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??在之前的博文 Linux 之八 完整嵌入式 Linux 環境介紹及搭建說明 中我們說了要一步步搭建整個嵌入式 Linux 運行環境。我所使用的硬件平臺及整個要搭建的嵌入式 Linux 環境見博文 Linux 之八 完整嵌入式 Linux 環境介紹及搭建說明,這里的編譯都是基于以上環境的,就不過多說明了。

??這篇博文我們僅僅關注 U-Boot 源碼及移植過程本身,想要吃透 U-Boot,有太多東西需要學習!最開始我想放到一篇文章中,寫著寫著內容越來越多,最終超過了 CSDN 編輯器的限制。。。最終決定把內容拆分成多篇文章。你可能需要:

  • U-Boot 之一 零基礎編譯 U-Boot 過程詳解 及 編譯后的使用說明
  • U-Boot 之二 詳解使用 eclipse + J-Link 進行編譯及在線調試
  • U-Boot 之四 配置構建過程(Kconfig、Kuild)詳解
  • U-Boot 之五 詳解 U-Boot 及 SPL 的啟動流程
  • U-Boot

    ??說白了 U-Boot 其實就是一裸板程序,這個程序最主要的一個功能就是傳遞內核參數,跳轉內核。當然除了跳轉到內核,U-Boot 本身還實現了其他一些功能(U-Boot 命令),以方便大家進行各種操作。

    ??看過我之前的博文,或者使用過 STM32 實現過在線升級的人應該都知道,我們通常的在線升級是 IAP + APP 這個模式,其中的 IAP 一個主要功能就是跳轉到 APP,這就和 U-Boot 功能是一樣的。

    ??注意,本身無論是 U-Boot 還是 Linux Kernel,他們都支持多種架構的多種 CPU,也因此,代碼中會有各種架構各種 CPU 相關的代碼,我后續的內容主要以 STM32F769I 為例來進行說明。STM32F769I 采用的是 ARM Cortex-M7 的核心,指令集架構是 ARMv7m。

    ??在眾多支持中,ARM 是最麻煩的一個。因為 ARM 賣 IP 且市場占有率相當高,導致產生了非常多的 ARM 核心的廠商,這些廠商會有自己的改動,進一步導致了 U-Boot 的 ARM 架構文件夾(./arch/arm)下有非常多的 mach-xxx 文件夾。

    ??通過上面的圖我們可以知道,U-Boot 對于眾多架構的支持已經到達了開發板級別。對于一些常用的開發板,U-Boot 直接實現了對他們的支持,也就意味著 U-Boot 可以直接在這些開發板上運行。具體到 ST 系列則有以下這些被支持:

    正好 U-Boot 沒有提供對于我使用的 STM32F769i-EVAL 板子的支持,后續的移植章節我就添加對于 STM32F769i-EVAL 板子的支持。以此來介紹 U-Boot 的具體移植步驟。

    SPL/TPL

    ??SPL 即 Secondary Program Loader 的縮寫,中文就是第二段程序加載器。這里的第二段程序其實就是指的 U-Boot,也就是,SPL 是第一段程序,優先執行,然后他再去加載 U-Boot。那么 U-Boot 本身已經是一個bootloader了,為啥要有 SPL 這個東西的存在呢?

    ??這個主要原因是對于一些 MCU 來說,它的內部 SRAM 可能會比較小,小到無法裝載下一個完整的 U-Boot 鏡像,那么就需要SPL,它主要負責初始化外部 RAM 運行環境,并加載真正的 U-Boot 鏡像到外部 RAM 中來執行。這里其實還有個問題需要注意,U-Boot 在設計上需要將自身(并不一定是所有代碼)復制到 RAM 執行的!

    ??SPL 并不一定需要。具體需不需要 SPL 這個和芯片的設計有關系(或者說和使用的開發板有關系)。同樣以我這里使用 STM32F769i-EVAL 板子來說,就是需要 SPL 的。具體參看 使用章節的說明。

    ??TPL 即 Tertiary Program Loader 的縮寫,中文就是第三段程序加載器。根據官方文檔,TPL 本身屬于 SPL 的精簡,代碼就在 SPL 代碼中,通過宏 CONFIG_TPL_BUILD 來區分,而且,現在只有 powerpc 的 mpc85xx 有這個要求并將實現它。TPL 我之前也沒接觸過,不是很了解,有了解的歡迎評論區給出指導。

    源碼目錄說明

    ??U-Boot 源碼的的文檔全部位于源碼根目錄的 doc 目錄下。官方網站上也有非常詳細的文檔 http://www.denx.de/wiki/U-Boot/Documentation。不過,源碼根目錄下的 README 應該算是一個最詳細的介紹文檔了。源碼中各文件的層級結構可以參考下圖:

    下面是對 U-Boot 源代碼中各個目錄的一個簡介:

    /arch 特定于架構的文件.實現了不同體系結構的 CPU,指令集、設備樹底層抽象,利用鏈接綁定實現了符號入口相對位置保持不變,故才能實現將內核鏡像拷貝到內存然后進行引導的功能/arc 通用的架構文件/arm ARM 架構/lib 實現了初始化C運行時環境(棧/堆指針等的初始化)/dts 實現了設備樹的底層體系架構依賴的具體抽象剝離/cpu 不同的 ARM 指令集的 CPU 分開處理/mach-xxx 由于同樣的內核相同,各家芯片外設都不盡相同,所以將各自個性實現剝離實現于此,這主要體系在ARM體系的芯片,由于ARM公司售賣IP,各家芯片廠商在內核的基礎上延伸出各自不同的芯片,所以需要將差異性剝離實現/m68k m68k 架構/microblaze microblaze 架構/mips MIPS 架構/nds32 NDS32 架構/nios2 Altera NIOS2 架構/powerpc PowerPC 架構/riscv RISC-V 架構/sandbox 獨立于硬件的 "sandbox" 模式/sh SH 架構/x86 x86 架構/xtensa Xtensa 架構 /api 供外部應用程序使用的與架構或設備無關的 API.如標準化輸入輸出,顯示,網絡API、存儲API等,為cmd提供支持 /board 開發板依賴文件.實現了產業鏈下游,設備廠商的差異性,對于產品設計而言,需要將各自在boot階段需要嚴格初始化的實現放在這里,比如IO口的初始化,產品中大部分IO口必須顯式設置其初始狀態 /boot images and booting 文件 /cmd U-Boot 命令相關接口 /common 與架構無關的一些通用文件. 是 U-Boot 主體,如系統停留在U-Boot階段,CPU始終在執行一個死循環,run_main_loop(). /configs 開發板默認的配置文件。格式均為:開發板名_defconfig /disk 磁盤驅動器分區處理的代碼.實現了輕量級磁盤管理 /doc 文檔 (a mix of ReST and READMEs) /drivers 設備驅動.這里實現了boot階段必要的設備驅動,如網口、顯示等 /dts 實現了設備樹.用于構建 內部 U-Boot fdt 的 Makefile /env 環境支持 /examples 示例代碼 /fs 文件系統代碼 (cramfs, ext2, jffs2, etc.) /include 頭文件 /lib 通用于所有架構的庫例程.比如CRC算法,加密算法,壓縮算法,字符串操作等 /Licenses 各種許可證文件 /net 網絡代碼.實現網絡協議層 /post 上電自檢 /scripts 各種構建腳本和 Makefile 文件。跟 make menuconfig 配置界面的圖形繪制相關的文件,我們作為使用者無需關心這個文件夾的內容 /test 各種單元測試文件 /tools 里面包含一系列構建 U-Boot 使用的工具的源代碼

    編譯產生的最終文件

    ??成功編譯之后,就會在 U-Boot 源碼的根目錄下產生多個可執行二進制文件以及編譯過程文件,這些文件都是 u-boot.xxx 的命名方式。這些文件由一些列名為 .xxx.cmd 的文件生成,.xxx.cmd 這些文件都是由編譯系統產生的用于處理最終的可執行程序的。注意,這里寫文件有沒有與 make menuconfig 中的配置有關系。

    • u-boot: 這個文件是編譯后產生的 ELF 格式的 U-Boot 鏡像文件,后續的文件都是由它產生的!由 .u-boot.cmd 這個命令腳本產生。
    • u-boot-nodtb.bin: 這文件是使用編譯工具鏈的 objcopy 工具從 u-boot 這個文件中提取來的,它只包含可執行的二進制代碼。就是把 u-boot 這個文件中對于執行不需要的節區刪除后剩余的僅執行需要的部分。由 .u-boot-nodtb.bin.cmd 這個命令腳本產生。
    • u-boot.bin: 就是把 u-boot-nodtb.bin 重命名得到的。由 .u-boot.bin.cmd 這個命令腳本產生。
    • u-boot-dtb.bin: 在 u-boot-nodtb.bin 后面拼接上設備樹后形成的文件。由 .u-boot-dtb.bin.cmd 這個命令腳本產生。
    • u-boot.img: 在 u-boot-nodtb.bin 后面拼接上設備樹后形成的文件。由 .u-boot.img.cmd 這個命令腳本產生。
    • u-boot-nodtb.img: 由 .u-boot-nodtb.bin.cmd 這個命令腳本產生。
    • u-boot-dtb.img: 由 .u-boot.img.cmd 這個命令腳本產生。
    • u-boot.srec: S-Record 格式的鏡像文件。由 .u-boot.srec.cmd 這個命令腳本產生。
    • u-boot.sym: 編譯過程中的符號文件。由 .u-boot.sym.cmd 這個命令腳本產生。
    • u-boot.lds: 編譯使用的鏈接腳本文件。由 .u-boot.lds.cmd 這個命令腳本產生。
    • u-boot.map: 編譯的內存映射文件。

    Kconfig 及 Makefile 文件

    ??Kconfig 及 Makefile 文件幾乎在每個目錄下都會有,關于這些文件在博文 U-Boot 之四 配置構建過程(Kconfig、Kuild)詳解 中單獨進行說明。

    移植過程

    ??要使用 U-Boot,首先要確定 U-Boot 是否支持我們的使用芯片(開發板)。這就需要查看 ./config 目錄下有沒有對應的配置文件,或者說有沒有類似的配置文件。如果直接有(對于一些通用的平臺,U-Boot 已經添加好了一些默認配置),那么恭喜可以省事很多;如果沒有(如果是自己畫的板子,指定是沒有),后續就牽扯到自己移植修改代碼。

    ??正好 U-Boot 沒有提供對于我使用的 STM32F769i-EVAL 板子的支持,我這里就添加對于 STM32F769i-EVAL 板子的支持。以此來介紹移植過程。移植后的 U-Boot 代碼放到了Github 上:https://github.com/ZCShou/U-Boot-STM32。具體步驟如下:

  • 新增 CPU 架構相關的文件:arch/架構/cpu/xxxx。這個一般不需要添加,一般人也搞不了。唯一一種可能就是你用的芯片使用了比較新的架構,而 U-Boot 還不支持。例如,如果芯片使用了最新的 ARMv9 架構,U-Boot 目前還沒有支持!
  • 新增芯片(或許應該說是開發板)的設備樹文件:arch\arm\dts\xxxxx.dts,然后將新增的設備樹文件添加到 arch/arm/dts/Makefile 中。一般比較常見的 MCU,U-Boot 都是支持的,無需我們關心。通常,我們往往是將一個與我們芯片類似的做一些對應的更改以適用于自己。
    ??具體到我這里使用的 STM32F769i-EVAL 板子,使用的 STM32F769 設備樹沒有,但是有個類似的 STM32F769i-disco 的設備樹,所以我這里就依據 STM32F769i-disco 添加 STM32F769-eval 相關設備樹。具體更改如下:

    其中 stm32f769.dtsi 就是 stm32f746.dtsi 改名字,下面是各設備數文件的包含關系示意圖:

    這里有個重點注意事項就是 其中的 compatible 的內容,驅動使用該項的內容來進行匹配,隨意更改可能導致驅動無法識別!!舉例如下:
  • 定義目標 CPU 的 Kconfig 文件:arch/arm/mach-xxx/xxx/Kconfig,并將其添加到 arch/arm/mach-stm32/Kconfig 中。然后添加 CPU 相關的代碼文件 arch/arm/mach-imx/xxx 和 arch\arm\include\asm\xxx。同樣,對于常見的 MCU,U-Boot 都是支持的,無需我們關心,通常只需要根據我們的板子做一些對應的更改即可。
    ??具體到我這里使用的 STM32F769i-EVAL 板子,原來已經存在 arch/arm/mach-stm32/stm32f7/Kconfig 了,我只是在其中添加自己的更改,具體如下:

    這里可以看到,他又引用了 board/st/stm32f769-eval/Kconfig 這個后面步驟我們會建立它。
    ??至于 arch/arm/mach-xxx/xxx 和 arch\arm\include\asm\xxx 下的代碼文件都需要增加哪些,這個就需要參考其他 U-Boot 已支持的 CPU 來決定(主要是我們找到相關資料介紹需要增加哪些)。我這里不需要更改。
    ??這里也有一個注意事項,在我們添加了新的配置之后,原來 U-Boot 的配置系統中的配置項可能有依賴關系,要確保自己新增的配置也添加到依賴項里面,舉例如下:
  • 將新增的 CPU 的 Kconfig 文件添加他的到上一級:架構的 Kconfig 文件 arch\arm\Kconfig 中并且根據需要修改這架構級別的 Makefile 文件:arch/arm/Makefile。
    ??具體到我這里使用的 STM32F769i-EVAL 板子,原來已經存在 arch/arm/mach-stm32/Kconfig 了,這里也已經被添加到了 arch\arm\Kconfig 文件中,如下圖所示:

    至于 arch/arm/Makefile 由于我這里沒有任何新增文件,因此不需要改動。
  • 將架構的 Kconfig 文件 arch/arm/Kconfig 添加到它的上一級架構總的 Kconfig 文件 arch/Kconfig 中。

    ??具體到我這里使用的 STM32F769i-EVAL 板子,原來已經存在 arch/arm/Kconfig 了,這里我就不需要改動了。至此架構中的移植就完成了,接下來就開始具體添加一些板子相關的文件。
  • 新建 board 文件:board/my_vendor/my_board/my_board.c、board/my_vendor/my_board/Kconfig、board/my_vendor/my_board/Makefile 這三個問你件。其中,board/my_vendor/my_board/my_board.c 中的具體內容 U-Boot 都有規定,這個可以參考已經存在的類似的板子的相關文件。board/my_vendor/my_board/Makefile 用于編譯 board/my_vendor/my_board/my_board.c;board/my_vendor/my_board/Kconfig 用于 Kconfig 配置系統
    ??具體到我這里使用的 STM32F769i-EVAL 板子,我參考 stm32f746-disco 新建了 stm32f769-eval,然后修改了其中各文件的內容,具體如下:
  • 將我們新增的開發板的的 Kconfig 添加到架構一級的 Kconfig 文件 arch/arm/Kconfig 中:如下圖是 U-Boot 支持的開發板的 Kconfig 情況:

    ??這里需要注意,在 CPU 的 Kconfig 中有可能已經直接引用了開發板的 Kconfig,而 CPU 的 Kconfig 又被包含到了架構一級的 Kconfig 文件,因此,如果有這個包含關系,這里就不用再次引入開發板的 Kconfig 了。例如 STM32F769-disco 的包含關系如下:

    ??具體到我這里使用的 STM32F769i-EVAL 板子,我這里新增的 stm32f769-eval 也是以上這種情況。
  • 新增開發板默認的一些參數的頭文件:include/configs/xxxx.h。這里面存放了一些默認的配置項。
    ??具體到我這里使用的 STM32F769i-EVAL 板子,我直接依據 stm32f746-disco.h 新建了 stm32f769-eval.h,并修改了其中的內容:

    這個文件會在編譯過程中被引入到我們上面添加的板子相關文件(如果你直接搜索,會發現根本沒有引用它的地方)。
  • 新建 board defconfig 文件:configs/my_board_defconfig。具體內容同樣參考一個近似的,然后修改內容即可。
    ??具體到我這里使用的 STM32F769i-EVAL 板子,我直接依據 stm32f769-disco_defconfig 新建了 stm32f769-eval_defconfig,然后更改了其中的內容:
  • ??以上步驟基本把移植過程介紹了差不多,如果想要完整的移植到新板子,要修改的內容還有很多(例如,新增驅動,設備樹修改等等)。通常情況的移植往往是參考一個近似來對比添加更改。

    整理

    ??由于 U-Boot 源碼文件眾多,而具體到某一平臺(開發板)之后,其中的大多數文件我們根本不需要。為了學習的方便,剔除無用文件,僅僅保留我們需要的文件對于我們學習將有很大幫助。如果可以正常整理出需要的源代碼,那基本對于 U-Boot 的文件結構掌握差不多了。

    ??由于 U-Boot 很多文件是編譯過程中產生的,如何有效提取成了個問題。我在網上看到有個網友搞了一個可以根據編譯過程提取源代碼的腳本:https://github.com/tonyho/Generate_Kernel_Uboot_Project_forIDE,但是經過我嘗試,發現并不是很準確,但基本可以用。

    ??此外,如果使用的是 VSCode 來查看代碼,可以直接在 .vsoce/settings.json 中使用以下配置以使 VSCode 不顯示相關目錄及文件

    {"files.exclude": {"**/.git": true,"**/.svn": true,"**/.hg": true,"**/CVS": true,"**/.DS_Store": true,"**/.gitignore": true,"**/*.o": true,"**/*.su": true,"**/*.dtb": true,"**/*.cmd": true,"**/*mips*": true,"**/*powerpc*": true,"**/*riscv*": true,"Licenses": true,".git*": true,".stamp*": true,"*.yml": true,// 排除不使用的架構"arch/{arc,m68k,microblaze,mips,nds32,nios2,powerpc,riscv,sandbox,sh,x86,xtensa}": true,// 排除 arch/arm/ 中無關目錄及文件"arch/arm/mach-[^s]*": true,"arch/arm/mach-s[^t]*": true,"arch/arm/mach-st[^m]*": true,"arch/arm/mach-stm32[$^m]*": true,"arch/arm/mach-stm32/stm32[^f]*": true,"arch/arm/mach-stm32/stm32f[^7]*": true,// 排除 arch/arm/cpu/* 無關目錄及文件"arch/arm/cpu/{arm11,arm720t,arm920t,arm946es,arm1136,arm1176,armv7,arm926ejs,armv8,pxa,sa1100}": true,// 排除 arch/arm/dts/* 無關目錄及文件"arch/arm/dts/[^s|^M|^i]*": true,"arch/arm/dts/i[^n]*": true,"arch/arm/dts/s[^t]*": true,"arch/arm/dts/st[^m]*": true,"arch/arm/dts/stm32[^f]*": true,"arch/arm/dts/stm32f[^7]*": true,"arch/arm/dts/stm32f7[^6|^4|^-]*": true,"arch/arm/dts/stm32f746[^.]*": true,"arch/arm/dts/stm32f769-[^e]*": true,// 排除 arch/arm/include/asm 無關目錄及文件"arch/arm/include/asm/{arch-[t-z]*,arch-[b-r]*,*-common,xen,mach-imx,arch-sunxi,arch-stv0991,arch-stm32h7,arch-stm32f4,arch-stih410,arch-sa1100,arch-aspeed,arch-am33xx,arch-armada8k,arch-armada100,armv8}": true,// 排除 board/* 無關目錄及文件"board/[^s]*": true,"board/s[^t]*": true,"board/ste": true,"board/sto*": true,"board/st/st[^m]*": true,"board/st/stm32[^f]*": true,"board/st/stm32f[^7]*": true,"board/st/stm32f7[^6]*": true,// 排除 include/configs/* 無關目錄及文件"include/configs/[^s]*": true,"include/configs/s[^t]*": true,"include/configs/st[^m]*": true,"include/configs/stm[^3]*": true,"include/configs/stm32[^f]*": true,"include/configs/stm32f[^7]*": true,"include/configs/stm32f7[^6]*": true,// 排除 configs/* 中無關目錄及文件"configs/[^s]*": true,"configs/s[^t]*": true,"configs/st[^m]*": true,"configs/stm[^3]*": true,"configs/stm32[^f]*": true,"configs/stm32f[^7]*": true,"configs/stm32f7[^6]*": true,"configs/stm32f769-[^e]*": true,} }

    參考

  • https://qingmu.blog.csdn.net/article/details/109199081
  • https://blog.csdn.net/csdnxmj/article/details/95507165
  • 總結

    以上是生活随笔為你收集整理的U-Boot 之三 U-Boot 源码文件解析及移植过程详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。