|
??最近,有個需求需要驗證一下嵌入式 LINUX 系統(tǒng)在 STM32上使用效果,正好手里有一塊前幾年的 STM32F769I-EVAL 的評估板,如下圖所示的這個:  這塊評估板的功能應(yīng)該是非常全了,價格也是不便宜(應(yīng)該算是挺貴)。ST 官網(wǎng)對于這塊評估板的介紹參見 Evaluation board with STM32F769NI MCU。 ??熟悉 ST 的開發(fā)板的都知道,ST 的開發(fā)板主要有 ST 官方的 Nucleo 系列、Discovery Kits 系列、Evaluation 系列以及第三方開發(fā)板這些組成。其中,ST 自家開發(fā)板中 Evaluation 系列是功能最全的,也是價格最高的。第三方開發(fā)板差異就比加大了。
嵌入式 Linux 環(huán)境
??在開始實際的移植編譯工作之前,有必要先來說一下我們要搭建的完整的 Linux 運行環(huán)境是啥樣的,以及包含那些部分。廢話不多說,直接上圖: 
- U-Boot 本質(zhì)就是就是一個復(fù)雜點的裸機程序(鏡像是 u-boot.bin),與我們通常編寫的 ARM 裸機程序沒有本質(zhì)區(qū)別。U-Boot 是無條件啟動的,從零開始啟動的。
- Linux Kernel 本身也是一個裸機程序(鏡像是 zImage),和 U-Boot、裸機程序無本質(zhì)區(qū)別。要說不同的地方,那就是內(nèi)核運行起來后,在軟件上分為內(nèi)核層和應(yīng)用層,分層后兩層的權(quán)限不同,內(nèi)存訪問和設(shè)備操作的管理上更加精細(xì)(內(nèi)核可以隨便訪問各種硬件,而應(yīng)用程序只能被限制地訪問硬件和內(nèi)存地址)。
??內(nèi)核是不能開機自動完全從零開始啟動的,內(nèi)核啟動需要別人幫忙。U-Boot 需幫助內(nèi)核實現(xiàn)重定位,U-Boot 還要給內(nèi)核提供啟動參數(shù)。 - 我們的嵌入式 Linux 中的應(yīng)用程序所需的編譯工具鏈也需要我們自己編譯,現(xiàn)有的就只有 ARM 提供的 Cortex-A 系列的(有些開發(fā)板廠商也提供自己編譯好的 Linux 編譯套件)。這里需要注意,嵌入式 linux 編譯套件往往不是通用的!
- 根文件系統(tǒng)包括 Linux 啟動時所必須的目錄和關(guān)鍵性的文件,例如 Linux 啟動時都需要有 init 目錄下的相關(guān)文件。Linux 啟動時,第一個必須掛載的是根文件系統(tǒng);若系統(tǒng)不能從指定設(shè)備上掛載根文件系統(tǒng),則系統(tǒng)會出錯而退出啟動。成功之后可以自動或手動掛載其他的文件系統(tǒng)。
- 這里的應(yīng)用程序必須使用我們自己編譯出的配套的編譯套件來編譯。根文件系統(tǒng)就是第一個需要使用我們自己的編譯套件來編譯的程序。
??嵌入式環(huán)境與我們熟悉的 PC 環(huán)境還是有很大區(qū)別的。尤其是對于部分芯片,它沒有 MMU,也就不能使用虛擬內(nèi)存相關(guān)的所有技術(shù)。也就意味著,嵌入式中的地址都是實際的物理地址。
??其次,嵌入式環(huán)境的另一個大特點就是資源非常緊張,這就導(dǎo)致了我們可能需要將最終的多部分的可執(zhí)行程序放到不同的地方。舉個例子,STM32 的 MCU 中,往往不能存放 Linux Kernel,我們需要將 Linux Kernel 放到一些外部存儲器中。
??對于 ARM 平臺,ARM 給出了兩個概念:加載域 和 執(zhí)行域,加載域?qū)?yīng)加載地址,執(zhí)行域?qū)?yīng)了一個執(zhí)行地址。關(guān)于 ARM 的分散加載機制,可以參見博文 ARM 之十三 armlink(Keil) 分散加載機制詳解 及 分散加載文件的編寫 即可。  ??進一步具體到 STM32 芯片,我們的程序是放到內(nèi)部的 FLASH 上的,F(xiàn)LASH 就是加載域,F(xiàn)LASH 上的具體地址就是加載域地址。同時,ST 芯片的設(shè)計可以從 FLASH 上執(zhí)行代碼(速度相對較慢),此時的加載域與執(zhí)行域是同一個;還有一種更高效的方式是將代碼放到 RAM 中執(zhí)行(存放還是在 FLASH),此時 RAM 就是執(zhí)行域,程序在 RAM 中的地址就是執(zhí)行域地址。
嵌入式系統(tǒng)啟動
??前面介紹了嵌入式系統(tǒng)的組成部分,接下來看看整個系統(tǒng)如何工作起來。一般 SoC 內(nèi)部會有個固化的引導(dǎo)程序,這個固化的 BootLoader 我在博文 STM32 之十四 System Memory、Bootloader 中有過詳細(xì)的介紹。這段程序的會初始化部分外設(shè)以與外部通信,具體可以參考官方手冊。 
嵌入式系統(tǒng)構(gòu)建工具
??構(gòu)建一整套嵌入式 Linux 系統(tǒng)是一件很龐大的事情,需要做很多工作。因此,誕生了一些嵌入式系統(tǒng)構(gòu)建工具,以幫助開發(fā)者簡化嵌入式系統(tǒng)的構(gòu)建過程,減少工作量。常用的嵌入式系統(tǒng)構(gòu)建工具有如下幾個:
- Buildroot: Linux 平臺上的一個用于構(gòu)建嵌入式 Linux 系統(tǒng)的框架。整個 Buildroot 是由 Makefile 腳本和 Kconfig 配置文件構(gòu)成的。使用它可以和編譯 Linux 內(nèi)核一樣,通過使用 Kbuild/Kconfig 系統(tǒng)編譯出一個完整的可以直接燒寫到機器上運行的 Linux 系統(tǒng)軟件(包含boot、kernel、rootfs 以及 rootfs 中的各種庫和應(yīng)用程序、交叉編譯工具鏈)。
??官方網(wǎng)站:https:///,提供了非常詳細(xì)的文檔。 - Yocto: Yocto Project 推出的一個開源的協(xié)作軟件,提供模板、工具和方法幫你創(chuàng)建定制的 Linux 系統(tǒng)和嵌入式產(chǎn)品,而無需關(guān)心硬件體系。適合嵌入式Linux開發(fā)人員使用,極大地簡化你的開發(fā)過程。Yocto 推薦使用 OpenEmbedded 構(gòu)建系統(tǒng)。
??Yocto Project 是 Linux 基金會的一個協(xié)作開源項目,其目標(biāo)是生成工具和流程,以便為嵌入式和物聯(lián)網(wǎng)軟件創(chuàng)建獨立于嵌入式硬件底層架構(gòu)的 Linux 發(fā)行版。官方網(wǎng)站:https://www./,提供了非常詳細(xì)的文檔。 - OpenEmbedded: 一個開源的嵌入式 Linux 系統(tǒng)構(gòu)建環(huán)境,它允許開發(fā)人員為嵌入式系統(tǒng)創(chuàng)建一個完整的 Linux 發(fā)行版。由OpenEmbedded 社區(qū)開發(fā),該社區(qū)于 2003 年正式成立。OpenEmbedded 的構(gòu)建系統(tǒng)基于 BitBake 構(gòu)建工具,其操作行為與 Gentoo Linux ebuilds 相似。
??官方網(wǎng)站:http://www./wiki/Main_Page,提供了非常詳細(xì)的文檔。 - PTXdist: Pengutronix 在 2001 年開發(fā)的一個構(gòu)建系統(tǒng),用于生成固件鏡像。采用了 Linux 內(nèi)核中的配置系統(tǒng) Kconfig 來選擇和配置每個包。
??官方網(wǎng)站:https://www./,提供了非常詳細(xì)的文檔。
??當(dāng)然,我們也可以選擇自己動手,根據(jù)上面嵌入式 Linux 環(huán)境,一點一點來構(gòu)建其中的各個部分。后續(xù),我就以手里的 STM32F769I-EVAL 的評估板為載體,盡量不使用已有的嵌入式構(gòu)建工具,來一步一步搭建這個嵌入式 Linux 環(huán)境。
搭建過程
??工欲善其事,必先利其器。第一步就是搭建 LINUX 系統(tǒng)開發(fā)環(huán)境,為此特地在筆記本上安裝了 Ubuntu,具體使用的桌面開發(fā)環(huán)境是 Ubuntu 20.04.3 LTS。至于為啥選擇 Linux 系統(tǒng),而不是直接使用 Windows 系統(tǒng)想必大家都清楚為啥。
??接下來準(zhǔn)備好一個目錄,后續(xù)所有的操作均在此目錄中進行。我的操作是新建 /home/zcshou/STM32LINUX 這個目錄,用于存放整個要為 STM32 嵌入式 Linux 環(huán)境編譯的源代碼,后續(xù)都在這個目錄中進行。如下圖所示:  ??最開始我想按照上面說的嵌入式環(huán)境的各個部分來分別寫幾篇博文來完整介紹整個搭建過程,然而寫著寫著內(nèi)容越來越多,最終超過了 CSDN 編輯器的限制!最終決定把內(nèi)容拆分成多篇文章。具體搭建過程就是如下幾步:
- 編譯 U-Boot。參見博文 U-Boot 之一 零基礎(chǔ)編譯 U-Boot 過程詳解 及 編譯后的使用說明
- 編譯 Linux Kernel。參見博文 Linux 之九 零基礎(chǔ)編譯嵌入式 Linux Kernel 過程詳解 及 編譯后的使用說明
- 編譯交叉編譯工具鏈。參見博文 Linux 之十 編譯自己的嵌入式 Linux 交叉編譯工具鏈
- 編譯 RootFS。參見博文 Linux 之十一 編譯嵌入式 Linux 下的 RootFS
參考
- https:///a/wf8KVWOhym
- https://www./article/qq_44034198/110872972
|