嵌入式Linux系統構建

libq8發表於2024-11-25

參考資料

本篇內容主要參考 韋東山的《嵌入式Linux應用開發完全手冊V5.2_IMX6ULL_Pro開發板.pdf》

具體課程見 百問網嵌入式專家-韋東山嵌入式專注於嵌入式課程及硬體研發

實踐環境為百問網官方開發板 100ASK_IMX6ULL-Pro

目標系統組成

Linux系統啟動流程

一個有效的根檔案系統整合了第三方和內部的所有軟體元件。涉及元件的下載、提取、配置、編譯和安裝,並可能修復問題和調整配置檔案。

  • 一個基本的根檔案系統至少需要

    • 傳統的目錄層次結構,包括/bin、/etc、/lib、/root、/usr/bin、/usr/lib、/usr/share、/usr/sbin、/var、/sbin。
    • 一套基本實用程式,至少提供 init 程式、shell 和其他傳統的 UNIX 命令列工具。這通常由 BusyBox 提供。
    • 安裝在/lib 中的 C 庫和相關庫(執行緒庫、數學庫等)。一些配置檔案,如/etc/inittab,以及初始化指令碼/etc/init.d。
  • 在大多數嵌入式 Linux 系統通用的基礎之上,可以新增第三方或內部元件。

幾種解決方案:

  • 手動操作
  • 系統構建工具
  • 發行版或現成的檔案系統

元件構建工具

  • Makefile
  • autotools
  • CMake

系統構建工具

可以使用不同的工具來自動化構建目標系統的過程,包括核心,有時還包括工具鏈。

  • 以正確的順序自動下載、配置、編譯和安裝所有元件,有時在應用補丁修復交叉編譯問題之後。
  • 已經支援大量的包,應該符合您的主要要求,並且易於擴充套件。
  • 構建變得可重現,這允許輕鬆更改某些元件的配置、升級它們、修復錯誤等。

常見的系統構建工具

  • Buildroot,由社群開發,https://buildroot.org

    • 專案主要特點

      • 製作啟動映像
      • 從原始碼構建所有元件
      • 注重簡單
    • 支援:根檔案系統映像、核心、引導載入程式、工具鏈的自由組合

  • OpenWRT,最初是無線路由器 Buildroot 的一個分支,現在是一個更通用的專案,https://openwrt.org

  • OpenEmbedded,更靈活但也更復雜,http://www.openembedded.org 及其工業化版本 Yocto 專案。

發行版Linux系統

Linux系統

  • 一種自由和開放原始碼的類UNIX作業系統,核心建立於1991-10-5,加上使用者空間和應用程式之後成為Linux系統。

  • 遵循 GNU通用公共許可證(GPL),任何個人和機構都可以自由使用,修改和再發布。

    • GNU 是一個自由的作業系統,其內容軟體完全以GPL方式釋出(編譯套件 GCC,C庫 glibc,核心工具組 coreutils,偵錯程式 GDB等)

發行版Linux:Linux distribution(GNU/Linux 發行版,為一般使用者預先整合好Linux作業系統和各種應用軟體,以軟體包管理系統進行應用管理)

  • 商業發行版本:Ubuntu(支援x86,arm等不同的處理器架構),Red Hat(主要支援x86),SUSE
  • 社群發行版本:Debain,Fedora, Arch
  • 國內衍生Linux發行版本:Deepin,優麒麟

嵌入式Linux系統

嵌入式Linux系統框架

嵌入式Linux系統構建

開發環境搭建

基礎軟體安裝

百問網提供了 Ubuntu 配置命令指令碼,支援一鍵下載安裝

git clone https://e.coding.net/weidongshan/DevelopmentEnvConf.git

cd DevelopmentEnvConf

sudo ./Configuring_ubuntu.sh

配置交叉編譯工具鏈

工具鏈:一組程式設計工具,用於開發軟體,建立軟體產品。包括編譯器和連結器,C庫,偵錯程式,標頭檔案,二進位制實用程式等等

交叉編譯工具鏈:一組工具,用來將原始碼構建為可以執行在其他平臺的二進位制程式碼,將構建環境和目標環境分隔開(不同的CPU架構,ABI,OS,Clib)

SDK(software development kit):一個更廣泛的集合,除了工具鏈外,還包括為 Target 目標架構構建的庫、標頭檔案,以及示例程式碼、文件、開發指南等資源。

交叉編譯構建過程:

  • Build(構建機器),使用 GCC 的原始碼,製作交叉編譯工具鏈。
  • Host(主機),使用交叉編譯工具鏈,編譯出程式。
  • Target(目標機器),程式執行的地方。

本地工具鏈:build == host == target。

交叉編譯工具鏈:build == host!= target

系統定義描述了一個系統:CPU 架構、晶片廠商、作業系統、ABI、C 庫。

  • <arch>-<vendor>-<os>-<libc/abi>(完整名稱);
  • <arch>-<os>-<libc/abi>。

arm-foo-none-eabi,針對 ARM 架構的裸機工具鏈,來自供應商 foo。

arm-unknown-linux-gnueabihf,針對 ARM 架構的 Linux 工具鏈,使用來自未知供應商的 EABlhf ABI 和 glibc C 庫。

armeb-linux-uclibcgnueabi,針對 ARM big-endian 的 Linux 工具鏈架構,使用 EABl ABI 和 uClibc C 庫。

下載100ask_imx6ull 開發板的 BSP:

git clone https://e.coding.net/codebug8/repo.git

mkdir -p 100ask_imx6ull-sdk && cd 100ask_imx6ull-sdk

../repo/repo init -u https://gitee.com/weidongshan/manifests.git -b linux-sdk -m imx6ull/100ask_imx6ull_linux4.9.88_release.xml --no-repo-verify

../repo/repo sync -j4

交叉編譯工具鏈配置

交叉工具鏈的主要內容

配置過程主要是設定 PATH, ARCH 和 CROSS_COMPILE 三個環境變數:

export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
  • 永久生效:修改使用者配置檔案 vim ~/.bashrc
  • 臨時生效:直接執行命令,只對當前終端有效

系統構建

Bootloader: Uboot

Bootloader 是在作業系統執行之前執行的一段程式碼,用於引導作業系統,並支援下載和除錯。

U-Boot 是一個開源的主引導載入程式,並含有多種命令以便除錯系統。它適用於多種計算機體系結構,包括 ARM,RISC-V 和 x86。

不同的開發板對應不同的配置檔案,配置檔案位於 u-boot 原始碼的“configs/”目錄。

對於 IMX6ULL Pro 版,u-boot 的編譯過程如下(編譯 uboot前必須先配置好工具鏈等開發環境):

cd /home/book/100ask_imx6ull-sdk/Uboot-2017.03
make distclean
make mx6ull_14x14_evk_defconfig 
make

編譯完成之後生成 u-boot-dtb.imx,可以燒在 TF 卡、EMMC 上

# 將u-boot-dtb.imx 檔案燒寫到 EMMC 上:
echo 0 > /sys/block/mmcblk1boot0/force_ro 
dd if=u-boot-dtb.imx of=/dev/mmcblk1boot0 bs=512 seek=2 
echo 1 > /sys/block/mmcblk1boot0/force_ro

Linux Kernel 和模組

編譯驅動程式之前要先編譯核心:

  • 驅動程式要用到核心檔案
  • 編譯驅動時用的核心、開發板上執行到核心,要保持一致
  • 同理,更換板子上的核心後,板子上的其他驅動也要更換

流程說明

  1. 獲取配套的交叉編譯工具鏈

    • SOC原廠提供:NXP ST Rockchip Amlogic Allwinnertech等。
    • 社群下載:Linrao Debian ARM Bootlin
  2. 下載kernel原始碼

    • 獲取Linux Kernel主線LTS原始碼

      • Git方式獲取:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
      • 壓縮包版下載:https://mirrors.edge.kernel.org/pub/linux/kernel/
    • 獲取晶片原廠Kernel原始碼

  3. Host下配置開發環境

    • 安裝必要依賴包
    • 解壓配置合適的工具鏈
  4. 指定編譯板子配置檔案

    make BOARDNAME_defconfig

  5. 編譯

    • 編譯核心映象 make -jN
    • 編譯裝置樹 make dtbs
    • 編譯安裝模組驅動 make modules

編譯核心

原始碼映象

  • vmlinux,未壓縮的原始核心映像,ELF 格式,用於除錯目的,但無法啟動。

  • arch//boot/*image,是最終可以啟動的壓縮後的核心映象檔案:

    • bzImage for x86,
    • zImage for ARM,
    • Image.gz for RISC-V,
    • vmlinux.bin.gz for ARC等。
  • arch//boot/Image,也可以引導的未壓縮核心映像。

  • arch//boot/dts/*.dtb,編譯的裝置樹檔案(某些架構)。

  • 所有核心模組,分佈在核心原始碼樹中,作為 .ko(核心目標)檔案。

配置編譯環境:指定架構和編譯器,以及單板的配置檔案

不同的開發板對應不同的配置檔案,配置檔案位於核心原始碼 arch/arm/configs/ 目錄。

IMX6ULL_Pro開發板 kernel 的編譯過程如下:

cd /home/book/100ask_imx6ull-sdk/Linux-4.9.88
make mrproper
make 100ask_imx6ull_defconfig
make zImage -j8
make dtbs

編譯完成後,在 arch/arm/boot 目錄下生成 zImage 核心檔案, 在 arch/arm/boot/dts 目錄下生成裝置樹的二進位制檔案 100ask_imx6ull14x14.dtb

編譯安裝核心模組

  • 使用核心模組可以支援更多不同的裝置外設。
  • 模組使無需重啟即可輕鬆開發驅動程式:載入、測試、解除安裝、重建、載入...
  • 有助於將核心映像大小保持在最小(在 PC 的 GNU/Linux 發行版中必不可少)。
  • 對於減少啟動時間也很有用:您無需花時間初始化稍後才需要的裝置和核心功能。

注意:一旦載入,在系統中擁有完全控制權和許可權。沒有特別的保護。這就是為什麼只有 root 使用者才能載入和解除安裝模組。

編譯:

cd ~/100ask_imx6ull-sdk/Linux-4.9.88/
make modles

安裝核心模組到Ubuntu內的某一個目錄備用:

cd ~/100ask_imx6ull-sdk/Linux-4.9.88/
make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install

編譯裝置樹

  • 目標單板所需的硬體裝置資訊。
  • 一般用於嵌入式裝置。

裝置樹檔案要與目標單板配套使用。一般和核心映象存放同一位置。

核心原始碼目錄下執行 make dtbs

安裝核心和模組到開發板

mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt
cp /mnt/zImage /boot
cp /mnt/100ask_imx6ull-14x14.dtb /boot
cp /mnt/lib/modules /lib -rfd

替換對應的目錄中檔案,重啟開發板即可完成更新 zImage、dtb、模組

完整的系統

根檔案系統與 busybox

Linux 系統需要一組基本的程式才能工作,包括一個 init 程式、一個 shell 以及用於檔案操作和系統配置的各種基本實用程式。在普通的 GNU/Linux 系統中,這些程式由不同的專案提供。

Busybox 本身包含了很多 Linux 命令,但是要編譯其他程式或者某些依賴庫,需要手工下載、編譯。 如果想做一個極簡的檔案系統,可以使用 Busybox 手工製作。

檔案系統是一套實現了資料的儲存、分級組織、訪問和獲取等操作的抽象資料型別(Abstract data type)

  • 資料存取

    • 使用硬碟和光碟這樣的儲存裝置,並維護檔案在裝置中的物理位置
    • 透過網路協議(如 NFS、SMB 等)提供的或者暫存於記憶體上
    • 虛擬檔案(如 proc 檔案系統)
  • 使用者訪問管理

    • 不必關心資料實際儲存在硬碟(或者光碟)的地址為多少的資料塊上,只需要記住這個檔案的所屬目錄和檔名
    • 不必關心硬碟上的那個塊地址沒有被使用,硬碟上的儲存空間管理(分配和釋放)功能由檔案系統自動完成

根檔案系統:被掛載在特定層次結構的 root 位置,由“/”標識

  • mount 和 umount 是程式,是檔案系統中的檔案。所以在安裝至少一個檔案系統之前無法使用
  • 不能用普通的掛載命令掛載,由核心直接掛載,根據“root=”核心選項進行設定。當沒有可用的根檔案系統時,核心會崩潰
  • 支援從不同位置掛載,包括儲存裝置(硬碟,SD卡等),NFS和記憶體。

busybox 在根檔案系統:

Buildroot

Buildroot 是一組 Makefile 和補丁,可自動化地為嵌入式系統構建完整的、可啟動的 Linux 環境(包括 bootloader、Linux 核心、包含各種 APP的檔案系統)。

  • 可以自動構建所需的交叉編譯工具鏈,建立根檔案系統,編譯 Linux 核心映像,並生成引導載入程式用於目標嵌入式系統。並支援所有步驟的任何獨立組合。
  • 使用簡單:類似核心的menuconfig
  • 支援大量的實用軟體包,比如 QT等

構建說明

  • 所有的構建都會輸出到頂層目錄下的 output/目錄內。O = output。另外也支援 out-of-tree 構建。
  • 配置檔案作為.config 儲存在頂級 Buildroot 源目錄中。CONFIG_DIR = $(TOPDIR),TOPDIR = $(shell pwd)

IMX6ULL_Pro 編譯過程

cd ~/100ask_imx6ull-sdk/Buildroot_2020.02.x

#選擇配置介面
make menuconfig

# 單獨編譯核心
make linux-rebuild

# 進入核心配置選項
make linux-menuconfig

# 單獨編譯 u-boot
make uboot-rebuild

# 單獨編譯某個軟體包
make <pkg>-rebuild

# 進入 busybox 配置選項
make busy-box-menuconfig

# 生成系統 sdk
make sdk

配置檔案說明

編譯系統

cd /home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x
make clean
make 100ask_imx6ull_pro_ddr512m_systemV_qt5_defconfig
make all -j4

映象檔案說明

buildroot2020.02.x/output/images/

  • 100ask_imx6ull-14x14.dtb【裝置樹檔案】
  • rootfs.ext2
  • rootfs.ext4
  • rootfs.tar
  • rootfs.tar.bz2【打包並壓縮的根檔案系統,用於NFSROOT啟動】
  • 100ask-imx6ull-pro-512d-systemv-v1.img【完整的系統映象,用於燒寫EMMC和SD卡】
  • uboot-dtb.imx【Uboot映象】
  • zImage【核心映象】

系統燒錄

USB 模式燒錄

使用 USB 燒寫工具:

使用命令列

  • 執行指令碼命令

    • sudo ./bin/uuu scripts/basic/emmc/write_all.clst #燒寫整個系統
  • 對於裸機程式,名字各有不同,沒有提供固定的指令碼

    • sudo ./bin/uuu -b emmc(or sd) firmware/u-boot-dtb_fastboot_100ask.imx files/led.imx #把 led.imx 燒到 EMMC

在開發板上直接燒寫

燒寫 u-boot

  • 將uboot映象u-boot-dtb.imx複製到開發板根目錄

    • 燒寫 EMMC

      echo 0 > /sys/block/mmcblk1boot0/force_ro 					//取消此分割槽的只讀保護 
      dd if=u-boot-dtb.imx of=/dev/mmcblk1boot0 bs=512 seek=2 	//實際燒寫命令 
      echo 1 > /sys/block/mmcblk1boot0/force_ro 					//開啟此分割槽的只讀保護
      
    • 燒寫 SD/TF

      dd if=u-boot-dtb.imx of=/dev/mmcblk0 bs=512 seek=2

更新核心或裝置樹

開發板使用的核心名為 zImage,裝置樹名為 100ask_imx6ull-14x14.dtb。 儲存在開發板的/boot 目錄中,只要替換/boot 目錄下的檔案後重啟即可完成更新

燒寫 SD/TF 卡

Windows SD/TF 卡燒錄工具

格式化:

燒寫映象:

Ubuntu下使用命令列燒錄 SD/TF 卡

在 Ubuntu 下可以更精細地操作 SD/TF 卡:把 sdcoard.img 整個燒寫到卡上,單獨燒寫 u-boot 到卡上,甚至掛接卡上的檔案系統後單獨更新裡面的檔案。

  • 識別 SD/TF 卡:使用 dmesg 命令獲取裝置掛載的裝置節點

  • 更新整個系統映象:使用 dd 命令燒寫 sdcard.img 映象檔案到 /dev/sdb 裝置

    • sudo dd if=sdcard.img of=/dev/sdb
  • 只更新卡上的 u-boot:使用 dd 命令燒寫 uboot的imx 映象檔案到 /dev/sdb 裝置

    • sudo dd if=u-boot-dtb.imx of=/dev/sdb bs=1k seek=1 conv=fsync
  • 更新 SD/TF 卡中的核心和裝置樹

    • 對於曾經燒寫過的 SD/TF 卡,上面已經有分割槽。使用 vmware 連線 TF 卡設 備後,Ubuntu 系統系統會自動掛載 tf 卡內的分割槽檔案系統

      • 執行df -h命令找到對應目錄,將其中的核心映象複製到開發板 /boot 目錄後重啟

相關文章