參考資料
本篇內容主要參考 韋東山的《嵌入式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 和模組
編譯驅動程式之前要先編譯核心:
- 驅動程式要用到核心檔案
- 編譯驅動時用的核心、開發板上執行到核心,要保持一致
- 同理,更換板子上的核心後,板子上的其他驅動也要更換
流程說明
-
獲取配套的交叉編譯工具鏈
- SOC原廠提供:NXP ST Rockchip Amlogic Allwinnertech等。
- 社群下載:Linrao Debian ARM Bootlin
-
下載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原始碼
-
-
Host下配置開發環境
- 安裝必要依賴包
- 解壓配置合適的工具鏈
-
指定編譯板子配置檔案
make BOARDNAME_defconfig
-
編譯
- 編譯核心映象
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 目錄後重啟
- 執行
-