一、編譯 Linux 固件
這一章將介紹編譯 ROC-RK3328-CC Linux 固件的整個流程。
1.1 准備工作
Linux 固件在如下的環境中編譯:
- Ubuntu 16.04 amd64
安裝以下包:
sudo apt-get install bc bison build-essential curl \ device-tree-compiler dosfstools flex gcc-aarch64-linux-gnu \ gcc-arm-linux-gnueabihf gdisk git gnupg gperf libc6-dev \ libncurses5-dev libpython-dev libssl-dev libssl1.0.0 \ lzop mtools parted repo swig tar zip
1.2 下載 Linux SDK
創建工程目錄:
# create project dir mkdir ~/proj/roc-rk3328-cc cd ~/proj/roc-rk3328-cc
下載 Linux SDK:
# U-Boot git clone -b roc-rk3328-cc https://github.com/FireflyTeam/u-boot # Kernel git clone -b roc-rk3328-cc https://github.com/FireflyTeam/kernel --depth=1 # Build git clone -b debian https://github.com/FireflyTeam/build # Rkbin git clone -b master https://github.com/FireflyTeam/rkbin
提示:通過以上鏈接可以在線瀏覽源碼。
開發板編譯配置在:
build/board_configs.sh
1.3 編譯 U-Boot
編譯 U-Boot:
./build/mk-uboot.sh roc-rk3328-cc
輸出:
out/u-boot/ ├── idbloader.img ├── rk3328_loader_ddr786_v1.06.243.bin ├── trust.img └── uboot.img
rk3328_loader_ddr786_v1.06.243.bin
: DDR 初始化文件。idbloader.img
: DDR 初始化與 miniloader 結合的文件。trust.img
: ARM trusted 固件。uboot.img
: U-Boot映像文件。
相關文件:
configs/roc-rk3328-cc_defconfig
: 默認 U-Boot 配置
1.4 編譯 Kernel
編譯 kernel:
./build/mk-kernel.sh roc-rk3328-cc
輸出:
out/ ├── boot.img └── kernel ├── Image └── rk3328-roc-cc.dtb
boot.img
: 包含Image
andrk3328-roc-cc.dtb
的映像文件, 為 fat32 文件系統格式。Image
: 內核映像。rk3328-roc-cc.dtb
: 設備樹 blob。
相關文件:
arch/arm64/configs/fireflyrk3328_linux_defconfig
: 默認內核配置。arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
: 開發板設備樹描述。arch/arm64/boot/dts/rockchip/rk3328.dtsi
: CPU 設備樹描述。
自定義內核配置和更新默認配置:
# 這非常重要! export ARCH=arm64 cd kernel # 首先使用默認配置 make fireflyrk3328_linux_defconfig # 自定義你的 kernel 配置 make menuconfig # 保存為默認配置 make savedefconfig cp defconfig arch/arm64/configs/fireflyrk3328_linux_defconfig
注意: 構建腳本不會將內核模塊復制到根文件系統。
1.5 編譯根文件系統
可以下載預編譯的根文件系統,或參考《編譯 Linux 根文件系統》自己編譯一個。
環境:
- Ubuntu 16.04 amd64
安裝依賴包:
sudo apt-get install qemu qemu-user-static binfmt-support debootstrap
下載 Ubuntu core:
wget -c http://cdimage.ubuntu.com/ubuntu-base/releases/16.04.1/release/ubuntu-base-16.04.1-base-arm64.tar.gz
創建一個大小為 1000M 的根文件系統映像文件,並使用 Ubuntu 的基礎包去初始化:
fallocate -l 1000M rootfs.img sudo mkfs.ext4 -F -L ROOTFS rootfs.img mkdir mnt sudo mount rootfs.img mnt sudo tar -xzvf ubuntu-base-16.04.1-base-arm64.tar.gz -C mnt/ sudo cp -a /usr/bin/qemu-aarch64-static mnt/usr/bin/
qemu-aarch64-static
是其中的關鍵,能在 x86_64 主機系統下 chroot 到 arm64 文件系統:
Chroot 到新的文件系統中去並初始化:
sudo chroot mnt/ # 這里可以修改設置 USER=firefly HOST=firefly # 創建用戶 useradd -G sudo -m -s /bin/bash $USER passwd $USER # 輸入密碼 # 設置主機名和以太網 echo $HOST > /etc/hostname echo "127.0.0.1 localhost.localdomain localhost" > /etc/hosts echo "127.0.0.1 $HOST" >> /etc/hosts echo "auto eth0" > /etc/network/interfaces.d/eth0 echo "iface eth0 inet dhcp" >> /etc/network/interfaces.d/eth0 echo "nameserver 127.0.1.1" > /etc/resolv.conf # 使能串口 ln -s /lib/systemd/system/serial-getty\@.service /etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service # 安裝包 apt-get update apt-get upgrade apt-get install ifupdown net-tools network-manager apt-get install udev sudo ssh apt-get install vim-tiny
卸載文件系統:
sudo umount rootfs/
1.6 打包原始固件
把你的 Linux 根文件系統映像文件放在 out/rootfs.img
out
目錄將包含以下文件:
$ tree out out ├── boot.img ├── kernel │ ├── Image │ └── rk3328-roc-cc.dtb ├── rootfs.img └── u-boot ├── idbloader.img ├── rk3328_loader_ddr786_v1.06.243.bin ├── trust.img └── uboot.img 2 directories, 8 files
打包原始固件:
./build/mk-image.sh -c rk3328 -t system -r out/rootfs.img
這條命令根據《存儲映射》所描述的布局,將分區映像文件寫到指定位置,最終打包成 out/system.img
,
二、遇到的問題
2.1 uboot編譯問題
- rkbin路徑沒有加上bin
- 文件丟失
- rk3328_ddr_786MHZ_v1.06.bin
- rk3328_miniloader_v2.43.bin
- rk3328_bl31_v1.34.bin
- rk3328_loader_ddr786_v1.06.243.bin
firefly丟失的文件可以在下面資源找到
https://github.com/gkkpch/rock64-bin
改完路徑,拷貝以上文件,u-boot編譯成功
2.2 編譯kernel遇到的問題
本來內核是在ubuntu16上編譯的,但是我在18上編譯了。很多都是gcc版本引起的,解決起來也比較簡單

drivers/net/wireless/rockchip_wlan/rtl8821cu/hal/phydm/phydm_adc_sampling.c:46:5: warning: this ‘else’ clause does not guard... [-Wmisleading-indentation] error, forbidden warning: phydm_adc_sampling.c:46 沒加大括號
另一個錯誤是~號

drivers/net/wireless/rockchip_wlan/rtl8821cu/hal/btc/halbtc8821c1ant.c:2333:30: warning: ‘~’ on a boolean expression [-Wbool-operation] error, forbidden warning: halbtc8821c1ant.c:2333
修改辦法:
把~號改成!,雖然可能會有問題。但是解決了編譯的問題
drivers/net/wireless/rockchip_wlan/rtl8812au/hal/rtl8812a/rtl8812a_mp.c:640:7: warning: statement will never be executed [-Wswitch-unreachable]
解決辦法:
把語句放在switch外面
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c:2488:3: warning: this ‘for’ clause does not guard... [-Wmisleading-indentation] error, forbidden warning: dm.c:2488
解決辦法:后面加括號
2.3 編譯根文件的問題
編譯根文件的時候可能無法apt-get update,網絡錯誤。使用指令:
cp /etc/resolv.conf mnt/etc/resolv.conf 解決
使用中沒有lsusb命令:
apt-get install usbutils
沒有lspci:
apt-get install pciutils
沒有insmod:
apt-get install kmod
啟動A start job is running for Raise network interfaces:
命令:sudo vim /etc/systemd/system/network-online.target.wants/networking.service 將里面的TimeoutStartSec=5min 修改為TimeoutStartSec=2sec
燒錄鏡像后沒有擴容剩余空間
首先需要安裝apt-get install parted,然后#vi /etc/rc.local
在exit 0前添加/usr/local/bin/first-boot-recovery.sh啟動腳本,給予可執行權限,用來擴容根目錄,記得在根目錄下新建一個firstboot文件
#!/bin/bash clean_first_boot () { rm -f /firstboot 2>/dev/null sync } if [ -e /firstboot ]; then echo "======Expanding the rootfs..." parted /dev/mmcblk0 -- unit s resizepart 5 -34s e2fsck -f /dev/mmcblk0p5 resize2fs /dev/mmcblk0p5 clean_first_boot fi 腳本內容如上,紅色部分看實際情況更改