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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明

發(fā)布時間:2024/10/14 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??在之前的博文 Linux 之八 完整嵌入式 Linux 環(huán)境介紹及搭建過程詳解 中我們說了要一步步搭建整個嵌入式 Linux 運行環(huán)境,今天就開始編譯 U-Boot。我所使用的硬件平臺及整個要搭建的嵌入式 Linux 環(huán)境見博文 Linux 之八 完整嵌入式 Linux 環(huán)境介紹及搭建過程詳解,這里的編譯都是基于以上環(huán)境的,就不過多說明了。

??這篇博文我們僅僅關(guān)注編譯過程本身,想要吃透 U-Boot,有太多東西需要學(xué)習(xí)!最開始我想放到一篇文章中,寫著寫著內(nèi)容越來越多,最終超過了 CSDN 編輯器的限制。。。最終決定把內(nèi)容拆分成多篇文章。你可能需要:

  • U-Boot 之二 詳解使用 eclipse + J-Link 進行編譯及在線調(diào)試
  • U-Boot 之三 U-Boot 源碼文件解析及移植過程詳解
  • U-Boot 之四 構(gòu)建過程(Kconfig 配置 + Kbuild 編譯)詳解
  • U-Boot 之五 詳解 U-Boot 及 SPL 的啟動流程
  • 編譯過程

    ??注意,這篇文章中使用的示例是 STM32f769-Disco 的配置,還沒有更換移植的 STM32f769-eval。STM32f769-eval 的 完整移植參考 U-Boot 之三 U-Boot 源碼文件解析及移植過程詳解 即可。

    編譯環(huán)境

    ??Ubuntu 20.04.3 LTS 準(zhǔn)備就緒之后,還有一些工具需要安裝。第一個就是 GCC,GCC 就使用 Ubuntu 自帶的 9.3.0 版即可。在編譯 U-Boot 的過程中,我們還需要安裝其他一些依賴工具,這個在后面用到的時候缺啥裝啥就可以(出現(xiàn)各種錯誤的時候再安裝相應(yīng)工具即可)。

    ??U-Boot 本身沒有提供對于我使用的 STM32F769-EVAL 板子的支持,我這里就是用它支持的 STM32f769-Disco 板子來進行編譯。如果不出意外,編譯之后運行肯定會有問題,到時候我們在一個一個解決問題即可。在博文 U-Boot 之三 U-Boot 源碼文件解析及移植過程詳解 中我詳細介紹了如何將 U-Boot 移植到新板子。

    ??這里介紹一下安裝依賴包的一些方法。正常我們應(yīng)該是先使用 find 命令查找依賴是否存在。因為存在一種情況是,依賴文件本身存在但是沒有在環(huán)境變量 LD_LIBRARY_PATH 里,如果不存在直接安裝即可。

  • 直接安裝的情況。一般使用命令 sudo apt update -> apt-cache search xxxx -> sudo apt install xxxx,具體示例(僅僅是個示例,安裝了沒啥用哈)如下:

    這樣我們可以查看響應(yīng)的依賴包的具體說明,然后根據(jù)需要來安裝。
  • 沒有在環(huán)境變量 LD_LIBRARY_PATH 里的情況,目前有兩種方法:
  • 直接把依賴的動態(tài)庫拷貝到上面執(zhí)行的可執(zhí)行命令時顯示被找到的庫的目錄下。
  • 把依賴的動態(tài)庫所在的目錄添加到環(huán)境變量 LD_LIBRARY_PATH 里:export LD_LIBRARY_PATH=/path_to_lib/:/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH。
  • 過程

    ??在開始編譯之前,我們先介紹兩個命令:make clean 用于清空編譯中間文件 和 make distclean 用于清除所有編譯產(chǎn)生的文件。如果我們想要重新編譯,可以使用以上兩個命令清理環(huán)境(這兩個命令在 U-Boot 根目錄的 Makefile 中有詳細的定義,在博文 U-Boot 之四 構(gòu)建過程(Kconfig 配置 + Kbuild 編譯)詳解 中會有說明)。

  • 第一步肯定是獲取 U-Boot 的源代碼,我這里直接使用了當(dāng)前最新存檔版:u-boot-2021.10.tar.bz2。這里需要重點注意,我最開始直接使用 Git 獲取了最新的源代碼,結(jié)果編譯之后運行直接 HardFault,分析好久沒找到原因,最后決定使用一個穩(wěn)定發(fā)布版試試,結(jié)果沒有問題。。。

    ??成功下載并解壓源代碼之后(注意我這里將解壓后的文件名命名為了 u-boot),我們需要進入 u-boot 目錄下,使用命令:cd u-boot。此后就在 u-boot 目錄下進行各種操作。

  • 第二步就是生成配置,直接使用命令:make stm32f769-disco_defconfig。不出意外的話會出現(xiàn)以下錯誤:

  • /bin/sh: 1: bison: not found

    ??這個錯誤是由于我們沒有安裝 bison 這個工具。Bison 是一個通用解析器生成器。GUN 軟件之一,官網(wǎng) https://www.gnu.org/software/bison/。Ubuntu 下直接使用命令:sudo apt install bison 即可(這個不是最新版,如果需要最新版需要自己從源碼安裝)。

  • /bin/sh: 1: flex: not found

    ??這個錯誤是由于我們沒有安裝 flex 這個工具。flex 是一個詞法分析器。用來將一個 .l 文件生成一個 .c 程序文件。源代碼托管于 Github:https://github.com/westes/flex。Ubuntu 下直接使用命令:sudo apt iinstall flex 即可。

  • 正常完成如下所示:

  • 第三步修改配置(裁剪)。直接使用命令:make menuconfig。不出意外的話會出現(xiàn)以下錯誤:

  • Unable to find the ncurses package

    ??這個錯誤是由于我們沒有安裝 ncurses 這個工具。ncurses(new curses)是一套編程庫,它提供了一系列的函數(shù)以便使用者調(diào)用它們?nèi)ド苫谖谋镜挠脩艚缑妗UN 軟件之一,官網(wǎng):https://invisible-island.net/ncurses/。Ubuntu 下直接使用命令:sudo apt iinstall libncurses-dev 即可。安裝成功之后,重新 make menuconfig,就會進入下面的界面:

    我們需要做的就是選擇其中的 SPL / TPL 菜單項,然后回車,在其中下翻頁找到 Activate Falcon Mode 項,將選擇去掉。

    ??其中還有很多項,這個就需要根據(jù)自己需要來具體進行裁剪了。當(dāng)然有個前提是,修改了配置很大可能還需要配套修改對應(yīng)的源代碼,因為之所以修改肯定是為了適應(yīng)自己開發(fā)板。
  • Your display is too small to run Menuconfig!

    這個錯誤提示很明顯,就是終端界面太小,把終端拖大一些就好了。
  • 第四步就是真正的編譯了,直接使用命令:CROSS_COMPILE=arm-none-eabi- ARCH=arm make -j8 不出意外的話會出現(xiàn)以下錯誤:

  • /bin/sh: 1: arm-none-eabi-gcc: not found

    這個錯誤是由于我們沒有安裝 GCC for ARM 導(dǎo)致的。也就是沒有編譯 U-Boot 使用的編譯器。解決方法也非常簡單,就是安裝 GCC for ARM 即可。

    ??這里有個需要注意的點,如果大家搜索 Ubuntu 下安裝 GCC for ARM,很多文章都過推薦使用 apt 命令來安裝,類似于:sudo apt-get install gcc-arm-none-eabi,這個版本并不是最新的(貌似使用這個舊版本也可以,我選擇了使用最新版)。更重要的是,ARM 之前已經(jīng)宣布不再更新 Launchpad 上的 GCC for ARM 了(具體見 Launchpad 上的說明)。 其只在 ARM 的官網(wǎng)提供編譯好的壓縮包及源代碼的壓縮包。

    這里簡單來講解一下直接從 ARM 官網(wǎng)下載壓縮包的安裝方法:

  • 下載最新版的 Linux x86_64 Tarball。目前最新的是 gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 。GCC for ARM 下載地址:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads
  • 將壓縮包解壓。我這里將其解壓到了 /usr/share/ 目錄下。直接使用命令:tar -xjvf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -C /usr/share/。等待解壓完成,/usr/share/gcc-arm-none-eabi-10.3-2021.10 目錄下就是最新的 GCC for ARM 的各種可執(zhí)行程序、庫等文件了。
  • 此時我們需要將 /usr/share/gcc-arm-none-eabi-10.3-2021.10 添加到系統(tǒng)環(huán)境變量這樣才能正常在終端中使用各種命令。具體有兩種方法(我采用了第二種):
  • 第一種是創(chuàng)建符號連接sudo ln -s /usr/share/gcc-arm-none-eabi-your-version/bin/arm-none-eabi-gcc /usr/bin/arm-none-eabi-gcc sudo ln -s /usr/share/gcc-arm-none-eabi-your-version/bin/arm-none-eabi-g++ /usr/bin/arm-none-eabi-g++ sudo ln -s /usr/share/gcc-arm-none-eabi-your-version/bin/arm-none-eabi-gdb /usr/bin/arm-none-eabi-gdb sudo ln -s /usr/share/gcc-arm-none-eabi-your-version/bin/arm-none-eabi-size /usr/bin/arm-none-eabi-size
  • 第二種是在 .bashrc 文件(在 Linux 系統(tǒng)普通用戶目錄(cd /home/xxx)或 root 用戶目錄(cd /root)下,用指令 ls -al 可以看到該隱藏文件,一般使用用戶目錄下的即可)最后面增加以下內(nèi)容:# GCC for ARM export PATH="$PATH:/usr/share/gcc-arm-none-eabi-10.3-2021.10/bin"
  • 可能需要重啟我們之前已經(jīng)打開的終端以上配置才會生效。
  • ??這里有一點需要注意,通過壓縮包安裝不能解決依賴關(guān)系,需要我們自己運行嘗試,看看少啥安啥。目前已知的依賴是 ncures5(會報錯:error while loading shared libraries: libncurses.so.5),其需要安裝 sudo apt install libncurses5(貌似應(yīng)該是需要 32 位的,我們上面安裝的 libncurses-dev 應(yīng)該是 64 位的)。
    至于需不需要其他的依賴,大家自行嘗試,我這里是沒有提示需要其他任何組件。

  • fatal error: openssl/evp.h:

    這個錯誤主要是由于 U-Boot 代碼使用了 openssl 中的相代碼,而我們的環(huán)境中沒有安裝 openssl。Ubuntu 下直接使用命令:sudo apt install libssl-dev 即可。
  • 正常編譯完成之后。我們需要的文件就有了。我們真正需要的是根目錄下的 u-boot.bin 和 spl 目錄下的 u-boot-spl.bin。

  • 其他一些問題。我在試用 make CHANGELOG 命令時出現(xiàn)錯誤 unrecognized command line option ‘-mno-unaligned-access’,不知道為啥,也沒找到如何解決。

  • 使用說明

    ??經(jīng)過上面的編譯之后,我們需要的 U-Boot 就編譯出來了。U-Boot 編譯完成后實際包含兩部分:spl/u-boot-spl.bin 和 u-boot.bin。下圖是針對 STM32F769 的一個布局映射圖:

    • spl/u-boot-spl.bin 負責(zé)初始化 sdram,配置時鐘,引導(dǎo)加載 U-Boot。需要將 SPL 燒寫在 0x08000000 地址,即內(nèi)部 flash首地址
    • u-boot.bin 是 uboot 主程序,負責(zé) relocate 向量表及自身。并完成開發(fā)板的基本初始化,然后引導(dǎo)內(nèi)核。需要將 SPL 燒寫在 0x08008000 地址。

    燒寫完之后重啟,就會看到如下信息:

    U-Boot SPL 2021.10 (Dec 24 2021 - 20:53:15 +0800) Trying to boot from XIPU-Boot 2021.10 (Dec 24 2021 - 20:53:15 +0800)Model: STMicroelectronics STM32F769-DISCO board DRAM: 16 MiB stm32fx_rcc_clock rcc@40023800: set_rate not implemented for clock index 4 stm32fx_rcc_clock rcc@40023800: set_rate not implemented for clock index 4 stm32fx_rcc_clock rcc@40023800: set_rate not implemented for clock index 4 Flash: 1 MiB MMC: sdio2@40011c00: 0 Loading Environment from nowhere... OK In: serial Out: serial Err: serial Net: Warning: ethernet@40028000 (eth0) using random MAC address - fa:d8:b5:97:81:15 eth0: ethernet@40028000 Hit SPACE in 3 seconds to stop autoboot. MMC: no card present U-Boot >

    Flash: 1 MiB

    ??通過 STM32F769 的手冊可以知道,它的 FLASH 大小是 2M,這里 U-Boot 顯示為 1M,明顯是不對的!關(guān)于 FLASH 的初始化可以在文件:drivers\mtd\stm32_flash.c 找到如下接口:

    unsigned long flash_init(void) {unsigned long total_size = 0;u8 i, j;for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {flash_info[i].flash_id = FLASH_STM32;flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 20);flash_info[i].size = sect_sz_kb[0];for (j = 1; j < CONFIG_SYS_MAX_FLASH_SECT; j++) {flash_info[i].start[j] = flash_info[i].start[j - 1]+ (sect_sz_kb[j - 1]);flash_info[i].size += sect_sz_kb[j];}total_size += flash_info[i].size;}return total_size; }

    其中,宏 CONFIG_SYS_MAX_FLASH_BANKS 很重要。在前面的移植章節(jié)我們已經(jīng)說過,STM32F769 是復(fù)用了 STM32F746 的相關(guān)文件的。那么,最終我們會在在 include\configs\stm32f746-disco.h 中找到該宏的定義:

    對比這個 STM32F769 和 STM32F746 這兩個 CPU,STM32F746 只有一個 BANK,但是 STM32F769 卻有兩個 BANK。那么是不是把他改成 2 就可以了呢?答案是不可以!我們繼續(xù)分析上面的代碼。

    ??我們再看第二個宏值 CONFIG_SYS_MAX_FLASH_SECT,它被定義為 8,接下來的 for 循環(huán)就是把這 8 個扇區(qū)的大小加起來,每個扇區(qū)的值放在了 arch\arm\include\asm\arch-stm32f7\stm32.h 文件中的 sect_sz_kb 變量中,如下所示:

    static const u32 sect_sz_kb[CONFIG_SYS_MAX_FLASH_SECT] = {[0 ... 3] = 32 * 1024,[4] = 128 * 1024,[5 ... 7] = 256 * 1024 };

    這個就很清楚了,就是 SMT32 的 FLASH 的扇區(qū)大小分配。知道了代碼的實現(xiàn),我們再來看看 STM32 手冊手冊中對于 FLASH 的定義,如下圖所示:

    通過上面的圖我們可以看到,STM32F769 的 FLASH 本身支持單 BANK 和 雙 BANK 模式,不過雙 BANK 模式,每個扇區(qū)的大小與 單 BANK 不一樣。默認情況是 單 BANK 模式的。因此,我們最終的處理方案是 CONFIG_SYS_MAX_FLASH_BANKS 保持為 1,把宏 CONFIG_SYS_MAX_FLASH_SECT 改為 12 ,并且必須要修改 sect_sz_kb 。

    Warning: ethernet@40028000 (eth0) using random MAC address

    ??每塊網(wǎng)卡都有一個MAC 地址,MAC 地址是一個 6 字節(jié)(48bit)的數(shù)據(jù)。前 3 字節(jié)稱為 OUI,是由 IEEE 組織注冊給網(wǎng)絡(luò)設(shè)備生產(chǎn)商的;每個廠商擁有一個或多個 OUI,彼此不同。后三字節(jié)則是由網(wǎng)絡(luò)設(shè)備生產(chǎn)商分配給自己生產(chǎn)的每一個擁有 MAC 地址的設(shè)備,互不重復(fù)。
    ??U-Boot 在啟動過程中提示使用了隨機 MAC 地址,這是因為如果 MAC 地址相同的兩塊開發(fā)板在同一局域網(wǎng)中,會互相影響。那么,如果我們想要自己固定一個固定的 MAC 地址應(yīng)該如何操作呢?如下圖所示默認開啟了不設(shè)置 MAC 地址時使用隨機地址:

    知道了為何會有這個隨機 MAC 地址后,我們就可以根據(jù)源代碼針對性進行修改。這里我提供我所使用的的兩種方法:

  • 環(huán)境變量中設(shè)置 MAC 地址。具體方法是:找到 .\include\configs\stm32f746-disco.h(注意替換自己板子使用的頭文件),然后在以下內(nèi)容中新增 "ethaddr=ea:2f:4b:f7:ac:ab\0" \:#include <config_distro_bootcmd.h> #define CONFIG_EXTRA_ENV_SETTINGS \"kernel_addr_r=0xC0008000\0" \"fdtfile=stm32f746-disco.dtb\0" \"fdt_addr_r=0xC0408000\0" \"scriptaddr=0xC0418000\0" \"pxefile_addr_r=0xC0428000\0" \"ramdisk_addr_r=0xC0438000\0" \"ethaddr=ea:2f:4b:f7:ac:ab\0" \BOOTENV
  • 修改設(shè)備樹,增加 MAC 地址。體方法是:找到 .\arch\arm\dts\stm32f7-u-boot.dtsi(注意替換自己板子使用的設(shè)備樹),然后在以下內(nèi)容中新增 local-mac-address = [ea 2f 4b f7 ac ab];: mac: ethernet@40028000 {compatible = "st,stm32-dwmac";reg = <0x40028000 0x8000>;reg-names = "stmmaceth";clocks = <&rcc 0 STM32F7_AHB1_CLOCK(ETHMAC)>,<&rcc 0 STM32F7_AHB1_CLOCK(ETHMACTX)>,<&rcc 0 STM32F7_AHB1_CLOCK(ETHMACRX)>;interrupts = <61>, <62>;interrupt-names = "macirq", "eth_wake_irq";local-mac-address = [ea 2f 4b f7 ac ab];snps,pbl = <8>;snps,mixed-burst;pinctrl-0 = <&ethernet_mii>;phy-mode = "rmii";phy-handle = <&phy0>;status = "okay";mdio0 {#address-cells = <1>;#size-cells = <0>;compatible = "snps,dwmac-mdio";phy0: ethernet-phy@0 {reg = <0>;};};};
  • ??我們需要注意的是,如果選擇了手動修改 MAC 地址,必須自己保證 MAC 不能重復(fù)。一個比較常用的方法是:網(wǎng)卡生產(chǎn)商的 OUI + 芯片的唯一 ID 組成 MAC。注意,部分網(wǎng)卡中會有專門記錄 MAC 地址的地方,我們只需要讀取即可。

    set_rate not implemented for clock index 4

    ??這個其實并不是個錯誤,應(yīng)該算是源代碼中的一個 BUG,通過搜索該提示文字關(guān)鍵字,我們最終可以找到函數(shù) static ulong stm32_set_rate(struct clk *ckl, ulong rate),如下圖所示:

    由于 stm32_set_rate 被調(diào)用了多次,而每次調(diào)用第一個 if 條件存在不成立的情況,因此就會一直打印該提示信息。

    MMC: no card present

    ??STM32F769-EVAL 開發(fā)板上是有 SD 卡的。但是這里顯示 沒有卡。不出意外的話,這里是由于 STM32F769-Disco 與 STM32F769-EVAL 在這方面配置不同導(dǎo)致。下圖是兩款開發(fā)板關(guān)于 SD 卡的說明:

    從中我們可以看出,兩款開發(fā)板使用的 SDMMC 并不相同!EVAL 開發(fā)板有兩個 SD 卡插槽:SD1 -> SDMMC1,SD2 -> SDMMC2。而 Discovery 板子只有一個 SD卡插槽:SD -> SDMMC2。關(guān)鍵在于 SDMMC2 的管腳使用是不一樣的!這里我們需要更改對應(yīng)的引腳。

    SD 目前還是有問題,后續(xù)再解決一下!

    參考

  • https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossa
  • https://james-hui.com/2021/07/02/building-a-small-uboot-linux-and-rootfs-for-arm-cortex-m7/
  • https://www.cnblogs.com/dylancao/p/8621789.html
  • https://wowothink.com/1e031f74/
  • https://blog.csdn.net/linuxweiyh/article/details/99331659
  • https://loee.xyz/2021/04/27/uboot-%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90/
  • https://www.twblogs.net/t/5d26d62ebd9eee1ede06f20d
  • https://mrchen.love/Article/ID/57
  • https://blog.csdn.net/weixin_39890452/article/details/114470827
  • https://www.cnblogs.com/cslunatic/archive/2013/03/28/2986146.html
  • https://wowothink.com/146db8db/
  • https://www.pianshen.com/article/70672050376/
  • https://my.oschina.net/u/4232364/blog/3134261
  • https://adrianalin.gitlab.io/popsblog.me/posts/build-linux-for-stm32f769i-disco-using-buildroot/
  • 與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。