crosstool-NG
下載最新版的 crosstool-NG
https://crosstool-ng.github.io
sudo apt install automake bison chrpath flex g++ git gperf gawk libexpat1-dev libncurses5-dev libsdl1.2-dev libtool libtool-bin python2.7-dev texinfo help2man
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.24.0.tar.bz2
tar xf crosstool-ng-1.24.0.tar.bz2 ./configure --enable-local make sudo make install |
確認安裝成功
./ct-ng |
列出工具鏈範本
./ct-ng list-samples |
這裡以 arm 為範例
顯示預設配置內容
./ct-ng show-arm-cortex_a8-linux-gnueabi |
指定使用
./ct-ng arm-cortex_a8-linux-gnueabi |
設定內容
./ct-ng menuconfig |
建議配置
Paths and misc 中停用 Render the toolchain read-only
Target options | Use specific FPU 中輸入 neon
Target options | Floating point 中選用 hardware (FPU)
C-library | extra config 中增加 --enable-obsolete-rpc
配置參考:
https://tgarc.github.io/2015/03/08/building-a-linaro-cross-compiler-toolchain-with-cross-ng/
build
./ct-ng build |
編譯成功後可以在以下目錄中找到
~/x-tools/arm-cortex_a8-linux-gnueabihf/
設定路徑
PATH=~/x-tools/arm-cortex_a8-linux-gnueabihf/bin:$PATH |
測試編譯
vi helloworld.c
|
編譯
arm-cortex_a8-linux-gnueabihf-gcc helloworld.c -o helloworld |
檔案內容
file helloworld |
arm-cortex_a8-linux-gnueabihf-readelf -a helloworld | grep "Shared library" arm-cortex_a8-linux-gnueabihf-readelf -a helloworld | grep "program interpreter" |
QEMU
安裝 qemu-system-arm
sudo apt update sudo apt install qemu-system-arm |
根目錄
建立 rootfs
mkdir -p ~/arm/rootfs cd ~/arm/rootfs mkdir bin dev etc home lib proc sbin sys tmp usr var mkdir usr/bin usr/lib usr/sbin mkdir var/log |
Linux Kernel
下載 linux kernel
解壓縮時注意資料夾內檔名區分大小寫
linux
tar -xvf linux-5.9.1.tar.xz cd linux-5.9.1 make mrproper |
套用既有配置至 .config 再自訂
make ARCH=arm multi_v7_defconfig |
自訂配置 .config
make ARCH=arm menuconfig |
開發時建議使用
若要使用 NFS 根目錄檔案系統,需設定
File systems | Network File Systems 中選用 Root file system on NFS
檢視 kernel version
make kernelversion |
如果路徑沒設要設定路徑
PATH=~/x-tools/arm-cortex_a8-linux-gnueabihf/bin:$PATH |
編譯內核
make -j 8 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- zImage |
若發生錯誤
Error: selected processor does not support `isb ' in ARM mode |
||
設定 crosstool-NG 配置
配置內容 Target options | Use specific FPU 中輸入 neon
build
參考: https://stackoverflow.com/questions/62304821/selected-processor-does-not-support-dmb-ish-in-arm-mode |
編譯硬體結構樹
make ARCH=arm dtbs |
編譯內核模組
make -j 8 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- modules |
安裝內核模組
make -j 8 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- INSTALL_MOD_PATH=~/arm/rootfs modules_install |
cp arch/arm/boot/zImage ~/arm/ cp arch/arm/boot/dts/vexpress-v2p-ca9.dtb ~/arm/ cd ~/arm |
以 qemu 執行
QEMU_AUDIO_DRV=none qemu-system-arm -m 256M -nographic -M vexpress-a9 -kernel zImage -dtb ve xpress-v2p-ca9.dtb -append "console=ttyAMA0" |
此時沒掛載根目錄當然跑不起來
離開 qemu
Ctrl-A X
BusyBox
安裝 busybox
wget https://busybox.net/downloads/busybox-1.32.0.tar.bz2 tar -xf busybox-1.32.0.tar.bz2 cd busybox-1.32.0/ make distclean make defconfig |
設定 busybox
make menuconfig |
在 menuconfig 設定 static binary
Busybox Settings ---> --- Build Options [*] Build BusyBox as a static binary (no shared libs) |
也可以不設定 no shared libs,只是就要去 crosstool-NG 產生的工具鏈複製 shared lib 至 rootfs/lib
編譯
make -j 8 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- |
安裝至 rootfs
make CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- CONFIG_PREFIX=~/arm/rootfs/ install |
建立裝置節點
cd ~/arm/rootfs sudo mknod -m 666 dev/null c 1 3 sudo mknod -m 600 dev/console c 5 1 |
sudo vi etc/inittab
|
mkdir etc/init.d vi etc/init.d/rcS
chmod +x etc/init.d/rcS |
配置 gdbserver
(之後可透過 gdbserver 進行遠端除錯,若不需要可略過)
複製 gdbserver
cd ~/arm/rootfs/ cp -a ~/x-tools/arm-cortex_a8-linux-gnueabihf/arm-cortex_a8-linux-gnueabihf/debug-roo t/usr/bin/gdbserver usr/bin/ |
找出 gdbserver 的相依性
arm-cortex_a8-linux-gnueabihf-readelf -a usr/bin/gdbserver | grep "program interprete r" |
[Requesting program interpreter: /lib/ld-linux-armhf.so.3] |
arm-cortex_a8-linux-gnueabihf-readelf -a usr/bin/gdbserver | grep "Shared library" |
0x00000001 (NEEDED) Shared library: [libdl.so.2] 0x00000001 (NEEDED) Shared library: [libm.so.6] 0x00000001 (NEEDED) Shared library: [libc.so.6] 0x00000001 (NEEDED) Shared library: [ld-linux-armhf.so.3] |
檢視檔案
arm-cortex_a8-linux-gnueabihf-gcc -print-sysroot export SYSROOT=`arm-cortex_a8-linux-gnueabihf-gcc -print-sysroot` |
依以上顯示的 program interpreter 及 Shared library 檢視檔案
ls -l $SYSROOT/lib/ld-linux-armhf.so.3 |
lrwxrwxrwx 1 jphf jphf 10 十二 2 18:55 /home/jphf/x-tools/arm-cortex_a8-linux-gnueabihf/arm-cortex_a8-linux-gnueabihf/sysroot/lib/ld-linux-armhf.so.3 -> ld-2.29.so |
ls -l $SYSROOT/lib/libdl.so.2 |
lrwxrwxrwx 1 jphf jphf 13 十二 2 18:54 /home/jphf/x-tools/arm-cortex_a8-linux-gnueabihf/arm-cortex_a8-linux-gnueabihf/sysroot/lib/libdl.so.2 -> libdl-2.29.so |
其他檔案的方式相同
複製檔案到根目錄檔案系統對應的資料夾
cp -a $SYSROOT/lib/ld-linux-armhf.so.3 lib/ cp -a $SYSROOT/lib/ld-2.29.so lib/ cp -a $SYSROOT/lib/libdl.so.2 lib/ cp -a $SYSROOT/lib/libdl-2.29.so lib/ cp -a $SYSROOT/lib/libm.so.6 lib/ cp -a $SYSROOT/lib/libm-2.29.so lib/ cp -a $SYSROOT/lib/libc.so.6 lib/ cp -a $SYSROOT/lib/libc-2.29.so lib/ |
根目錄檔案系統掛載
初始記憶體檔案系統
獨立的模擬磁碟
cd ~/arm/rootfs find . | cpio -H newc -ov --owner root:root > ../initramfs.cpio cd ../ gzip initramfs.cpio mkimage -A arm -O linux -T ramdisk -d initramfs.cpio.gz uRamdisk |
以 qemu 執行
QEMU_AUDIO_DRV=none qemu-system-arm -m 512M -nographic -M vexpress-a9 -kernel zImage -dtb vexpress-v2p-ca9.dtb -append "console=ttyAMA0 rdinit=/sbin/init" -initrd initramfs.cpio.gz |
透過初始記憶體檔案系統掛載,啟動後寫入檔案,再重啟後檔案會不見。
NFS 掛載根目錄檔案系統
透過 NFS 掛載,目前的建立的根目錄,可直接與目標機器上的資料同步,方便開發與除錯
kernel 要先配置 CONFIG_ROOT_NFS
安裝
sudo apt install nfs-kernel-server |
sudo vi /etc/exports
|
重啟
sudo service nfs-kernel-server restart |
如果開發環境是用 virtual box 建立,網路設定裡需要指定為使用 "橋接介面卡"
檢視目前網路設定
ifconfig |
其中 192.168.0.102 就是這台機器的 IP
HOST_IP 如上所示
TARGET_IP 可以指定任何與 HOST_IP 同網域但未使用的 IP
gdbserver 遠端除錯
(這裡的範例採用 NFS 掛載根目錄檔案系統)
cd ~/arm/rootfs/home vi helloworld.c
arm-cortex_a8-linux-gnueabihf-gcc helloworld.c -o helloworld |
在目標機器上可以執行
cd /home ./helloworld |
透過網路
在目標機器上執行 gdbserver
gdbserver :10000 ./helloworld |
在開發機器上指定同樣程式
arm-cortex_a8-linux-gnueabihf-gdb helloworld (gdb) target remote 192.168.0.105:10000 |
透過序列埠
在目標機器上執行 gdbserver
gdbserver /dev/ttyO0 ./helloworld stty -F /dev/ttyO0 115200 |
在開發機器上指定同樣程式
arm-cortex_a8-linux-gnueabihf-gdb helloworld (gdb) set remotebaud 115200 (gdb) target remote /dev/ttyUSB0 |