Linux 之八 完整嵌入式 Linux 环境、(交叉)编译工具链、CPU 体系架构、嵌入式系统构建工具
??最近,工作重心要從裸機開發轉移到嵌入式 Linux 系統開發,由于之前對嵌入式 Linux 環境并不是很了解,因此,第一步就是需要了解如何搭建一個完整的嵌入式 Linux 環境。現在將學習心得記錄為此文。
嵌入式 Linux 環境
??嵌入式 Linux 環境與我們熟悉的 PC 環境還是有很大區別的,要搭建出一套完整的嵌入式 Linux 環境需要做的工作相當多。下圖是我根據學習整理的一個嵌入式 Linux 環境示意圖:
-
BootLoader:通常使用的是 U-Boot,就是一個復雜點的裸機程序,與我們通常編寫的 ARM 裸機程序沒有本質區別。BootLoader 需幫助內核實現重定位,BootLoader 還要給內核提供啟動參數。
BootLoader 是無條件啟動的,從零開始啟動的。
-
Linux Kernel: 本身也是一個復雜的裸機程序。與裸機程序相比,內核運行起來后,在軟件上分為內核層和應用層,分層后兩層的權限不同,內存訪問和設備操作的管理上更加精細(內核可以隨便訪問各種硬件,而應用程序只能被限制地訪問硬件和內存地址)。
內核是不能開機自動完全從零開始啟動的,需要 BootLoader 幫忙。
-
裸機程序編譯工具鏈: 這個編譯工具鏈(名字是我自己起的)編譯出特定于架構的純裸機程序以在指定架構上運行。一般由內核廠家提供,我們最為熟知的就是 ARM 提供的 GNU Arm Embedded Toolchain 中的 arm-none-eabi-*、Keil 中的 armcc、IAR。
通常采用交叉編譯。
-
linux 程序編譯工具鏈: 這個編譯工具鏈(名字是我自己起的)用于編譯出在我們的嵌入式 Linux 環境中運行的用戶程序。通常這個編譯工具鏈需要我們根據自己的嵌入式 Linux 環境自己編譯。如果是直接買的 SoC 或者開發套件,SoC 或者開發套件廠家會自己編譯好然后提供給客戶。
- 通常采用交叉編譯。
- 嵌入式 linux 編譯套件往往不是通用的!
- linux 程序編譯工具鏈也可以編譯裸機程序,例如編譯裸機 U-Boot、Linux Kernel。 但是通常不會使用 linux 程序編譯工具鏈來進行純裸機開發。
-
文件系統: 其中主要就是根文件系統(RootFS),包括 Linux 啟動時所必須的目錄和關鍵性的文件,例如,Linux 啟動時都需要有 init 目錄下的相關文件。Linux 啟動時,第一個必須掛載的是根文件系統,若系統不能從指定設備上掛載根文件系統,則系統會出錯而退出啟動。成功之后可以自動或手動掛載其他的文件系統。
根文件系統是第一個需要使用我們自己的編譯套件來編譯的程序。
-
用戶 APP: 這個就是我們的嵌入式 Linux 中運行的應用程序了。肯定是需要使用我們自己制作的 linux 程序編譯工具鏈來產生。
??以上就是完整的嵌入式 Linux 環境各個部分的基本情況。從搭建嵌入式 Linux 環境的角度來說,我們需要自己編譯 BootLoader、Linux Kernel、文件系統、linux 程序編譯工具鏈 這四大部分;從使用者角度來說,通常會直接購買以上完整的嵌入式環境,然后在以上環境上開發用戶 APP,基本不會涉及以上四大部分的修改(二次開發除外)。
??在上面我們說的嵌入式環境四大部分種,最麻煩的應該就是構建自己的 linux 程序編譯工具鏈了。
CPU 體系架構
??當前全球公認為主流的 CPU 體系架構有 x86、PowerPC、ARM、RISC-V 和 MIPS 等。早年, x86 和 PowerPC 專注于桌面計算機、服務器等領域,ARM、RISC-V 和 MIPS 則在嵌入式領域發力。如今,x86、PowerPC 也布局了嵌入式領域,ARM、RISC-V 和 MIPS 也開始布局桌面計算機和服務器。
我對于這些指令集沒有深入研究,以下僅作為擴展知識了解一下!
x86
??x86 是一個復雜指令集計算機(CISC)指令集體系結構家族,最初是由 Intel 基于 Intel 8086 微處理器及其 8088 變體開發的。該名字就源自于 Intel 的 80x86 系列處理器。
??英特爾 8086 微處理器中的 x86 是16 位的,1985 年,英特爾發布了 32 位 80386。現在,我們通常使用 i386 表示 32 位 x86 架構(有時候也直接使用 x86 表示)。 在 1999 年至 2003 年,AMD 將這種 32 位架構擴展到 64 位,并在早期文檔中將其稱為 x86-64,后來稱為 AMD64。英特爾很快以 IA-32e 的名義采用了 AMD 的架構擴展,后來使用 EM64T 的名稱,最后使用 Intel64。現在,我們仍然使用 x86-64 或 AMD64 來表示 64 位的 x86 架構(有時候也直接使用 x64 表示)。
PowerPC
??PowerPC(Performance Optimization With Enhanced RISC – Performance Computing,有時簡稱稱 PPC)是 1991 年 Apple-IBM-Motorola聯盟( AIM)基于早期的 IBM POWER 架構創建的精簡指令集計算機(RISC)指令集架構(ISA)。從 2006 年開始被命名為 Power ISA(PowerPC ISA + PowerPC Book E),而 PowerPC 則作為某些 PowerPC 架構的處理器的商標而存在?;景l展過程:POWER ? PowerPC ? Power ISA。
ARM
??ARM 架構是由 ARM 公司推出的基于精簡指令集計算機(RISC)指令集架構(ISA)。ARM 架構版本從 ARMv3 到 ARMv7 支持 32 位空間和 32 位算數運算,大部分架構的指令為定長 32 位(Thumb 指令集支持變長的指令集,提供對 32 位和 16 位指令集的支持),而 2011 年發布的 ARMv8-A 架構添加了對 64 位空間和 64 位算術運算的支持,同時也更新了 32 位定長指令集。
??ARM 公司除了 ARM 指令集相關產品,也提供了一些列的開發軟件,例如 Keil、DS-5 等。
RISC-V
??RISC-V 是一個基于精簡指令集(RISC)原則的開源的指令集架構(ISA),其中的 V 表示第 5 代。RISC-V 于 2010 年誕生于美國加州大學伯克利分校并行計算實驗室(Parallel Computing Laboratory) 的 David A. Patterson 教授指導的團隊。
??目前,于 2015 年成立的 RISC-V 基金會(現在被稱為 RISC-V International)擁有,維護和發布與 RISC-V 定義相關的知識產權。RISC-V 官方還提供了一系列的工具,例如 RISC-V GNU Toolchain 等。指令集手冊,軟件工具等基本都托管在 Github 上。
MIPS
??MIPS(Microprocessor without Interlocked Pipeline Stages)是由美國 MIPS 計算機系統公司開發的一種采取精簡指令集(RISC)的指令集架構(ISA)。早期的 MIPS 架構只有 32 位的版本,隨后才開發 64 位的版本。在 MIPS V 之后分為了 MIPS32 和 MIPS64。
2021 年 3 月,MIPS 宣布 MIPS 架構的開發已經結束,因為該公司正在向 RISC-V 過渡。
(交叉)編譯工具鏈
??軟件程序的編譯過程由一系列的步驟完成,每一個步驟都有一個對應的工具。這些工具緊密地工作在一起,前一個工具的輸出是后一個工具的輸入,像一根鏈條一樣,我們稱這些工具為編譯工具鏈。
??在當前平臺(例如 x86 架構的 PC)下,直接編譯出來程序(或者庫文件),其可以直接在當前的平臺運行(或使用)。這個過程就叫做本地編譯,使用的編譯工具叫做本地編譯工具鏈(簡稱編譯工具鏈)。例如 PC 上的 VC、GCC、LLVM、TCC 等。
??在當前平臺下(例如 x86 架構的 PC)下,直接編譯出來程序(或者庫文件),其不可以直接在當前的平臺運行(或使用),必須放到目標平臺上(例如 ARM)才可以運行(或使用),這個過程就叫做交叉編譯,使用的編譯工具叫做交叉編譯工具鏈。例如PC 中的 armcc、iar、特定架構的 GNU、特定架構的 LLVM 等。
這里的平臺指的是 CPU 架構或者操作系統
??交叉編譯工具鏈又可以根據是否支持 Linux 系統分為 裸機程序交叉編譯工具鏈 和 Linux 程序交叉編譯工具鏈 這兩大類。我們上面的舉例中,armcc、iar 都屬于裸機交叉編譯工具鏈;而特定架構的 GNU、特定架構的 LLVM 則根據需要可以支持 Linux 系統,也可以不支持 Linux 系統,因此它既有裸機程序交叉編譯工具鏈,也有 Linux 程序交叉編譯工具鏈。
GNU 交叉編譯工具鏈
??我們接觸最多交叉編譯工具鏈就是特定架構的 GNU,例如 Arm GNU Toolchain 就分為僅支持裸機的 arm-none-eabi 和 支持 linux 系統的 arm-none-linux 這兩大類。特定架構的 GNU 交采編譯工具鏈也是目前我們使用最多的交叉編譯工具鏈,網上所說的交叉編譯工具鏈基本就是指的 GCC。
由于 ARM 的絕對市場地位,導致了在網上搜索交叉編譯工具鏈,基本都和 ARM 有關系。其他架構,例如 MIPS、RISC-V 也有 GCC 交叉編譯工具鏈,但是由于市場占有率低我們接觸較少,網上資料也非常少。
??在我們構建自己的 GCC (交叉)編譯工具鏈的時候,編譯(交叉)編譯工具鏈使用的平臺、編譯出的(交叉)編譯工具鏈運行的平臺、使用編譯出的(交叉)編譯工具鏈編譯出的程序運行的平臺三者可以完全不同。其中關鍵的一步是設置 configure 的參數,該命令有三個參數 --build、--host、--target 非常重要,下圖是 Windows 上的 MinGW 編譯器配置信息:
- --build:這個參數指出了編譯(交叉)編譯工具鏈使用的平臺。如果我們不顯示指定這個參數的值,那么這個參數的值就會由 config.guess 自動識別。
- --host:這個參數指出了編譯出的(交叉)編譯工具鏈運行的平臺。這個參數的值一般就等于 --build 的值。
- --target:這個參數指出了使用編譯出的(交叉)編譯工具鏈編譯出的程序運行的平臺。這個選項只有在建立交叉編譯環境的時候用到,正常編譯和交叉編譯都不會用到。
??本地編譯工具鏈一般就是指的 --build = --host = --target 的情況,交叉編譯工具鏈一般是--build = --host ≠ --target 的情況?;竞苌俪霈F--build ≠ --host 的情況。
命名規則
??一般來說,交叉編譯工具鏈的命名規則是:arch [-vendor] [-os] [-(gnu)abi]-*。但是,關于這個規則,我并沒有找到在哪份官方資料上有介紹,實際有些交叉編譯工具鏈也確實不符合上面的命名規則。如果有誰在官方資料上見到過此規則的詳細描述,一定要私信告訴我。
- arch: 體系架構,如 ARM、MIPS、RISC-V
- vendor: 工具鏈提供商,沒有 vendor 時,用 none 代替。
- os: 目標操作系統,沒有 os 支持時,也用 none 代替,表示裸機。如果同時沒有 vendor 和 os 支持,則只用一個 none 代替。例如 arm-none-eabi 中的 none 表示既沒有 vendor 也沒有 os 支持。
- none
- C 庫通常是 newlib
- 提供不需要操作系統的 C 庫服務
- 允許為特定硬件目標提供基本系統調用
- 可以用來構建 Bootloader 或 Linux Kernel,不能構建 Linux 用戶空間代碼
- linux
- 用于 Linux 操作系統的開發
- linux 特有的 C 庫的選擇:glibc、uClibc-ng、musl
- 支持 Linux 系統調用
- 可以用來構建 Linux 用戶空間代碼,但也可以構建裸機代碼,如 Bootloader 或 Linux Kernel
- none
- abi: 應用二進制接口(Application Binary Interface)
- gnu: 這個其實是早期 AArch32 架構使用的名字,后來該名字為 gnueabi
- gnueabi: 其實就是嵌入式應用二進制接口(Embedded Application Binary Interface,EABI)
- elf: 這個通常用在 64 位裸機架構的編譯工具鏈中
??由于 ARM 的絕對市場地位,導致了在網上搜索交叉編譯工具鏈,基本都和 ARM 有關系。因此,這里的命名規則更多的是指 Arm GNU Toolchain 的命名。
組成部分
??GUN 交叉編譯工具鏈中有三個核心組件:Binutils、GCC、C library,如果需要支持 Linux,則還有個 Linux kernel headers。在源代碼組織上他們是相互獨立的,需要單獨進行交叉編譯。
- Binutils:包括一些二進文件相關的工具
- 主要工具
- ld 鏈接器
- as 匯編器
- 調試/分析工具和其他工具
- addr2line、ar、c++filt、gold、gprof、nm、objcopy、objdump、ranlib、readelf、size、strings、strip
- 需要針對每種 CPU 架構進行配置
- 交叉編譯非常簡單,不需要特殊的依賴項。
- 主要工具
- gcc:GNU Compiler Collection
- C、C++、Fortran、Go 等編譯器前端
- 各種 CPU 架構的編譯器后端
- Provides:
-
編譯器本身。例如 cc1 for C、cc1plus for C++
-
編譯器調用程序。gcc、g++ 不但調用編譯器本身,也調用 binutils 中的 匯編器、連接器
不要被 gcc 這個名字誤導,它其實是個 wrapper,會根據輸入文件調用一系列其他程序。國外資料中被稱為 compiler driver,國內有些資料稱為 引導器。
-
目標庫:libgcc(gcc 運行時)、libstdc ++(c ++ 庫)、libgfortran(fortran運行時)
-
標準 c++ 庫的頭文件
-
- 構建 gcc 比構建 binutils 要復雜的多
- Linux Kernel headers:構建需要支持 Linux 系統時必須提供。這些頭文件定義了用戶空間與內核之間的接口(系統調用、數據結構等)。
- 為了構建一個 C 庫,需要 Linux 內核頭文件中系統調用號的定義、各種結構類型和定義。
- 在內核中,頭文件被分開:
- 用戶空間可見的頭文件,存儲在 uapi 目錄中:include/uapi/、arch/<ARCH>/include/uapi/asm
- 內部的內核頭文件
- 在安裝過程中需要使用
- 安裝包括一個清理過程,用于從頭文件中刪除特定于內核的結構體
- 從 Linux 4.8 開始,安裝 756 個頭文件
- 內核到用戶空間 ABI 通常是向后兼容的。Kernel headers 的版本必須等于或者小于目標 Linux 的版本
- C library:
-
提供 POSIX 標準函數的實現,以及其他幾個標準和擴展
-
基于 Linux 系統調用
-
幾個可用的實現
-
glibc:The GNU C Library 是 Linux C 庫的事實標準,我們常見的 Linux 發行版中都使用它。支持眾多的架構和操作系統,但是不支持沒有 MMU 的平臺,不支持靜態鏈接。早些年由于硬件限制及 glibc 本身太大基本不能直接用于嵌入式,如今貌似也可以了。
-
uClibc-ng:以前叫 uClibc,始于 2000 年,支持非常靈活的配置。支持架構很多(包括一些 glibc 不支持的),但是僅支持 Linux 操作系統。支持多種沒有 MMU 的架構,如 ARM noMMU、Blackfin 等,支持靜態鏈接。
STM32F MCU 沒有 MMU,其嵌入式 Linux 環境中編譯工具鏈就是用的它。
-
musl:始于 2011 年,開發非常積極,最近添加了對于 noMMU 的支持。它非常小,尤其是在靜態鏈接時。兼容性好,并且嚴格遵循 C 標準。
-
bionic:安卓系統使用
-
其他一些特殊用途的:newlib(用于裸機)、dietlibc、klibc
musl 的作者對于 Linux 常用的這幾個庫做了一個對比,以下是對比情況圖:
-
-
在編譯和安裝之后,提供了:
- 動態鏈接器 ld.so
- C 庫本身 libc.so,及其配套庫:libm、librt、libpthread、libutil、libnsl、libresolv、libcrypt
- C 庫的頭文件:stdio.h、string.h 等等。
-
??GUN 將編譯器和 C 庫分開放在兩個軟件包里,好處是比較靈活,方便在工具鏈中可以選擇不同的 C 庫。但是,也帶來了編譯器和 C 庫的循環依賴問題:編譯 C 庫需要 C 編譯器,但是 C 編譯器又依賴 C 庫。理論上編譯器是不應該依賴 C 庫的,它應該只負責將源代碼翻譯為匯編代碼即可,但實際上并非如此。
??C99 標準定義了兩種實現:一種稱為 hosted 實現,一種稱為 freestanding 實現。其中,hosted 實現支持完整的 C 標準,包括語言標準和庫標準,它用于編譯在有宿主系統的環境下運行的程序。freestanding 實現僅支持完整的語言標準,對于庫標準它只要求支持部分庫標準。
構建(交叉)編譯工具鏈分為好多步,而且單是編譯 gcc 就要多次。
ABI、EABI、OABI、GNU EABI
??應用二進制接口(Application Binary Interface,ABI)定義了一個系統中函數的參數如何傳送、如何接受函數返回值、數據類型的大小、布局和對齊、應用程序應如何對操作系統進行系統調用、對象文件,程序庫等的二進制格式等細節。ABI 允許編譯好的目標代碼在使用兼容 ABI 的系統中無需改動就能運行。
??嵌入式應用程序二進制接口 (Embedded Application Binary Interface,EABI) 指定嵌入式軟件程序的文件格式、數據類型、寄存器用法、堆棧幀組織和函數參數傳遞的標準約定,以便與嵌入式操作系統一起使用。廣泛使用的 EABI 有 PowerPC、Arm EABI、MIPS EABI。
??在很多地方有 GNU EABI 的這樣的叫法,例如,在 ARM 提供的 GNU 工具鏈中有 arm-none-linux-gnueabi 的命名。這里的 GNU EABI 其實就是 EABI。之所以叫這個名字是因為 GNU 一貫作風是要求帶有 GNU 字樣。例如 GNU 要求把 Linux 稱為 GNU/Linux,但是實際情況大家都直接叫 Linux。
??OABI (其中的 O,理解為 Old 或 Obsolete)是 ARM 系列的最開始使用的應用程序二進制接口。OABI 假設 CPU 擁有一個浮點單元處理器(實際很多沒有),導致編譯器生成的程序總是嘗試與浮點單元通信以進行浮點運算,由于沒有浮點運算單元,內核出現異常,異常機制會自動再使用軟件模擬浮點進行計算,這導致了一些額外開銷。
??EABI 被創造出來以解決 OABI 的這個問題。但是,EABI 沒有簡單的方法來讓二進制發行版同時支持軟浮點和硬浮點,因此,ARM 的交叉編譯器分為 ARMEL 和 ARMHF 這兩種。因此,有個 arm-none-linux-gnueabihf 表示支持硬浮點。
嵌入式系統啟動
??宏觀上來看,系統的啟動分為 Boot 執行階段和系統執行階段,Boot 階段為系統運行準備必要條件,然后將 CPU 的控制權交給系統,系統接管 CPU ,然后做相應初始化后開始運行;從微觀來看,系統啟動從上電開始,經過了很多階段。
??芯片一上電就會根據設定的啟動方式,從固定的位置開始讀取代碼并執行。這個固定的位置根據芯片而定,例如,STM32 的 MCU 支持 RAM、Flash、BootLoader 三個位置啟動。下圖是一個典型的嵌入式 Linux 系統啟動流程:
嵌入式系統構建工具
??構建一整套嵌入式 Linux 環境是一件很龐大的事情,我們可以選擇自己動手,根據上面嵌入式 Linux 環境,一點一點來構建其中的各個部分。實際情況是,為了簡化搭建工作量,誕生了一些嵌入式系統構建工具。這些工具通過各種自動化手段,只需要我們輸入基本命令,就可以自動構建出以上說的完整嵌入式環境。
Buildroot
??Buildroot 是 Linux 平臺上的一個用于構建嵌入式 Linux 系統的框架。整個 Buildroot 是由 Makefile 腳本和 Kconfig 配置文件構成的。使用它可以和編譯 Linux 內核一樣,通過使用 Kbuild/Kconfig 系統編譯出一個完整的可以直接燒寫到機器上運行的 Linux 系統軟件(包含boot、kernel、rootfs 以及 rootfs 中的各種庫和應用程序、交叉編譯工具鏈)。
??Buildroot 支持的架構有 ARC、ARM、AArch64、Black?n、csky、m68k,Microblaze、MIPS(64)、NIOS II、OpenRisc、PowerPC(64)、SuperH、SPARC、x86、x86 64、Xtensa.
Yocto
??Yocto 全稱是 Yocto Project(官方簡稱 YP) 是 Linux 基金會在 2010 年推出的一個開源的協作項目。提供模板、工具和方法以創建定制的 Linux 系統和嵌入式產品,而無需關心硬件體系。從歷史上看,該項目是從 OpenEmbedded 項目發展而來的。
??Yocto Project 這個名字(或者我們常簡稱的 Yocto)是指的這個項目本身或者一個組織,Poky 官方定義為 Yocto Project 的參考發行版,它才是我們真正使用的構建系統工具(更確切的說這就是一個可以構建出嵌入式 Linux 的 DEMO)。實際情況中,我們一般會對 Poky 進行自定義(刪除 meta-poky 等,添加自己的 meta-xxx)來實現自己的嵌入式 Linux 系統構建工具包。如下是我們在用的一個目錄結構:
??這里還有個問題,Yocto Project 對于 OpenEmbedded 的引用是打散重新組合的(OpenEmbedded 本身就是有多個部分組成),并不是完整的把 OpenEmbedded 拿過來。從 Yocto Project 的角度來看,Yocto Project 的結構就是如下所示:
OpenEmbedded
??OpenEmbedded (簡稱 OE)是一個構建自動化框架和交叉編譯環境,用于為嵌入式設備創建 Linux 發行版。OpenEmbedded 由成立于 2003 年的 OpenEmbedded 社區開發,其誕生遠早于 Yocto Project。2011 年 3 月,它與 Yocto Project 合作(實際就是合并了),并開始以 OpenEmbedded-Core 項目作為項目發展的名稱(簡稱 OE-Core),之前的稱為 OpenEmbedded-Classic(簡稱 OE-Classic 或 oe-dev),OpenEmbedded 這個名字就用來代指整個 OpenEmbedded 項目。
??注意,在一些老文檔中,OpenEmbedded 這個名字有可能還是指的舊的 OpenEmbedded 。例如,OpenEmbedded 的原始代碼倉庫并沒有改名為 OpenEmbedded-Classic。OpenEmbedded 項目的代碼倉庫見 https://git.openembedded.org/。
??之所以更名是因為與 Yocto Project 合并之后的開發團隊對 OpenEmbedded 的整個結構進行了比價大改進。 OpenEmbedded-Classic 的所有自動構建的處方(Recipes)都放在一起,隨著發展越來越難以維護;而在新的 OpenEmbedded-Core,其結構由許多 layers 組成(OpenEmbedded 維護了一個可以與 OE-Core 一起使用的層列表),讓用戶可以更容易加入定制的自動構建處方(Recipes)。OE-Classic 不再維護,也基本沒有使用了!現在的 OpenEmbedded 也可以理解為基于 OE-Core 的一個實現(BitBake + OpenEmbedded-Core)+ 一組元數據)。
??OpenEmbedded-Core 可以獨立使用,也被集成在 Angstrom、SHR、Yocto Project 等系統中來使用。實際情況是,很少見單獨使用 OE-Core 的情況,OpenEmbedded 基本就成了 Yocto Project 中的一部分(其他基本死的差不多了),其文檔等全部都引用 Yocto Project 中對應文檔。
PTXdist
??PTXdist 是一個固件鏡像構建工具,是 Pengutronix 在 2001 年開發的一個構建系統。采用了 Linux 內核中的配置系統 Kconfig 來選擇和配置每個包,規則集合則基于 GNU Make 和 Bash。
OpenWRT
??OpenWRT 是一個針對嵌入式設備的 Linux 操作系統。OpenWrt 不是一個單一且不可更改的固件,而是提供了具有軟件包管理功能的完全可寫的文件系統。
??OpenWRT 是一個高度模塊化、高度自動化的嵌入式Linux系統,擁有強大的網絡組件和擴展性,常常被用于工控設備、電話、小型機器人、智能家居、路由器以及 VOIP 設備中。
測試環境
??正好手里有一塊前幾年的 STM32F769I-EVAL 的評估板,后續,我就以手里的 STM32F769I-EVAL 的評估板為載體,盡量不使用已有的嵌入式構建工具,來一步一步搭建這個嵌入式 Linux 環境。如下圖所示的這個:
??這塊評估板的功能應該是非常全了,價格也是不便宜。ST 官網對于這塊評估板的介紹參見 Evaluation board with STM32F769NI MCU。
??熟悉 ST 的開發板的都知道,ST 的開發板主要有 ST 官方的 Nucleo 系列、Discovery Kits 系列、Evaluation 系列以及第三方開發板這些組成。其中,ST 自家開發板中 Evaluation 系列是功能最全的,也是價格最高的。第三方開發板差異就比加大了。
??嵌入式環境與我們熟悉的 PC 環境還是有很大區別的。尤其是對于部分芯片,它沒有 MMU,也就不能使用虛擬內存相關的所有技術。也就意味著,嵌入式中的地址都是實際的物理地址。
??其次,嵌入式環境的另一個大特點就是資源非常緊張,這就導致了我們可能需要將最終的多部分的可執行程序放到不同的地方。舉個例子,STM32 的 MCU 中,往往不能存放 Linux Kernel,我們需要將 Linux Kernel 放到一些外部存儲器中。
??對于 ARM 平臺,ARM 給出了兩個概念:加載域 和 執行域,加載域對應加載地址,執行域對應了一個執行地址。關于 ARM 的分散加載機制,可以參見博文 ARM 之十三 armlink(Keil) 分散加載機制詳解 及 分散加載文件的編寫 即可。
??進一步具體到 STM32 芯片,我們的程序是放到內部的 FLASH 上的,FLASH 就是加載域,FLASH 上的具體地址就是加載域地址。同時,ST 芯片的設計可以從 FLASH 上執行代碼(速度相對較慢),此時的加載域與執行域是同一個;還有一種更高效的方式是將代碼放到 RAM 中執行(存放還是在 FLASH),此時 RAM 就是執行域,程序在 RAM 中的地址就是執行域地址。
搭建過程
??工欲善其事,必先利其器。第一步就是搭建 LINUX 系統開發環境,為此特地在筆記本上安裝了 Ubuntu,具體使用的桌面開發環境是 Ubuntu 20.04.3 LTS。至于為啥選擇 Linux 系統,而不是直接使用 Windows 系統想必大家都清楚為啥。
??接下來準備好一個目錄,后續所有的操作均在此目錄中進行。我的操作是新建 /home/zcshou/STM32LINUX 這個目錄,用于存放整個要為 STM32 嵌入式 Linux 環境編譯的源代碼,后續都在這個目錄中進行。如下圖所示:
??最開始我想按照上面說的嵌入式環境的各個部分來分別寫幾篇博文來完整介紹整個搭建過程,然而寫著寫著內容越來越多,最終超過了 CSDN 編輯器的限制!最終決定把內容拆分成多篇文章。具體搭建過程就是如下幾步:
參考
總結
以上是生活随笔為你收集整理的Linux 之八 完整嵌入式 Linux 环境、(交叉)编译工具链、CPU 体系架构、嵌入式系统构建工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 之七 SSH、SSL、Ope
- 下一篇: U-Boot 之一 零基础编译 U-Bo