前言
想在NanoPi-NEO
上開發螢幕驅動,但是看了下檔案目錄發現沒有核心樹,導致最基礎的file_operations
結構體都無法使用,於是尋找核心樹安裝方法。但官方提供的核心為4.14太舊了apt
找不到對應的linux-source
版本(其實後面發現不需要用apt
,可以在kernel.org上下載,但反正都裝了那就當學習一下怎麼移植了),於是選擇自己重新構建了整個系統。
1. 準備工作
- x86_64 Linux 機器或者虛擬機器。
如果是Apple Silicon Mac最好用UTM安裝一個x86_64 Ubuntu server,因為本文使用的安裝rootfs的工具僅x86_64系統可用。
當然也有buildroot
和debootstrap
方法。debootstrap
感覺一般;buildroot
或許會比本文方法更好用,但我沒用,想使用這種方法可以考慮去參考這篇文章。
- 一張sd卡。
- 建立一個資料夾存放移植所需各種檔案,如
~/nanopi-neo
。
2. 準備SD卡
- 可以選擇直接從 NanoPi-NEO 官網燒錄一個映象到SD卡,他會自動幫你分好區(不過也需要修改),也可以手動操作。
- 使用
fdisk
進行分割槽操作(假設這裡SD卡是/dev/sdb
,且已經燒錄官方映象)[1]
sudo fdisk /dev/sdb
# 輸入m檢視各種命令
m
# 輸入p列印分割槽情況
p
-
如圖,
sdb1
是boot
分割槽,sdb2
是rootfs
分割槽 -
官方映象可能會多一個
sdb3
存放userdata
,需要刪除後兩個分割槽並格式化,下面展示將末尾分割槽刪除。
-
使用如下所示命令建立分割槽。
-
其中
sector
部分延續sdb1
的131071,第二個直接留空 -
執行下面的命令將
rootfs
分割槽格式化
sudo mkfs.ext4 -L rootfs /dev/sdb2
你也可以選擇從頭建立SD啟動卡,關於這部分可以檢視該教程,這裡不做展開
3. 移植u-boot
-
在 Github 上下載最新
u-boot.tar.gz
,這裡以2024.04為例[2] -
在 Arm GNU 官網按圖尋找下載正確的交叉編譯鏈。
-
解壓
cd nanopi-neo/
tar -vxzf u-boot-2024.04.tar.gz
tar -vxf arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
- 安裝交叉編譯鏈
# 修改交叉編譯鏈檔名方便操作
mv arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-linux-gnueabihf arm-none-linux-gnueabihf
# 移動資料夾
sudo mkdir -p /usr/local/toolchains
sudo mv arm-none-linux-gnueabihf /usr/local/toolchains/
# 新增環境變數
vim .bashrc
# 新增以下三行
export PATH=/usr/local/toolchains/arm-none-linux-gnueabihf/bin/:$PATH
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabihf-
- 編譯 u-boot
cd u-boot-2024.04/
# 生成配置檔案
make nanopi_neo_defconfig
# 生成燒錄檔案 u-boot-sunxi-with-spl.bin
make -j8
# 燒錄到SD卡
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8 oflag=direct
出現錯誤一般是有模組沒有安裝,可以自行搜尋怎麼安裝
4. 移植kernel
- 在 Kernel Archives 上下載最新的
stable
版本 Linux 核心,這裡以6.8.7為例[2:1] - 編譯配置檔案
# 解壓
cd ~/nanopi-neo/
tar -vxf linux-6.8.7.tar.xz
# 安裝一些工具(可能不全,如果編譯遇到缺工具就安裝一下)
sudo apt-get install libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf dwarves bc
cd linux-6.8.7/
# 生成配置檔案.config
make sunxi_defconfig
- 增加usb-wifi支援(本文以
mt7601u
為例)[3]
make menuconfig
按下/搜尋mt7601u
,按enter進行搜尋它所需的依賴項
截個屏或者拍個照,找到所有[=n]
的對應內容按下y將它加入核心編譯中
如果按y出現彈框,並且關閉彈框後發現是
M
不是*
的話,記得用/尋找對應內容並一一加入核心編譯。
如圖是未配置進核心而是配置為module
,需要尋找其他依賴項一一加入核心編譯
一直按esc直到出現該介面,按enter選擇儲存配置
- 編譯
zImage
和sun8i-h3-nanopi-neo.dtb
# 編譯時間大概1-2小時
make -j8
- 安裝到SD卡中
sudo mount /dev/sdb1 /mnt
sudo cp arch/arm/boot/zImage /mnt/zImage
sudo cp arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dtb /mnt/sun8i-h3-nanopi-neo.dtb
sync
sudo umount /mnt
- 將SD卡插入開發板中,進入u-boot命令列拉取核心啟動[4]
setenv bootcmd 'fatload mmc 0 0x46000000 zImage; fatload mmc 0 0x48000000 sun8i-h3-nanopi-neo.dtb; bootz 0x46000000 - 0x48000000'
setenv bootargs "console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait"
saveenv
boot
5. 移植rootfs
- 在 Ubuntu cdimage 下載映象[5],本文使用Ubuntu 22.04 LTS,則進入
jammy/daily/current/
目錄下載jammy-base-armhf.tar.gz
- 建立資料夾並解壓
cd ~/nanopi-neo/
mkdir temp
sudo tar -xpf jammy-base-armhf.tar.gz.tar.gz -C temp
- 安裝
qemu-user-static
(就是這東西只支援x86_64,害我好幾天配置不好)
sudo apt-get install qemu-user-static
- 準備工作
# 網路檔案
sudo cp -b /etc/resolv.conf temp/etc/resolv.conf
# qemu檔案
sudo cp /usr/bin/qemu-arm-static temp/usr/bin/
# 建立mount.sh檔案
touch mount.sh
sudo vim mount.sh
mount.sh
檔案內容如下
#!/bin/bash
mnt() {
echo "MOUNTING"
sudo mount -t proc /proc ${2}proc
sudo mount -t sysfs /sys ${2}sys
sudo mount -o bind /dev ${2}dev
sudo mount -o bind /dev/pts ${2}dev/pts
}
umnt() {
echo "UNMOUNTING"
sudo umount ${2}proc
sudo umount ${2}sys
sudo umount ${2}dev/pts
sudo umount ${2}dev
}
if [ "$1" == "-m" ] && [ -n "$2" ] ;
then
mnt $1 $2
elif [ "$1" == "-u" ] && [ -n "$2" ];
then
umnt $1 $2
fi
很多教程這裡會讓你換國內源,但是我每次換源後apt很多東西裝不上,因此請自行選擇是否換apt源
關於換源方法見:清華 Ubuntu Ports 軟體倉庫
- 使用chroot進入根目錄
# 修改檔案許可權
chmod 777 mount.sh
# 執行.sh檔案
./mount.sh -m temp/
# 切換root
sudo chroot temp
- 執行必要命令
# apt更新
apt update
apt upgrade
apt-get update
# 安裝必要工具
apt install -y systemd
apt install vim sudo openssh-server net-tools network-manager
apt install ifupdown htop iputils-ping kmod rsync
# 新增使用者
useradd -s '/bin/bash' -m -G adm,sudo username
# 新增使用者密碼
passwd username
# 新增root密碼
passwd root
# 退出
exit
./mount.sh -u temp/
- 把核心原始碼複製到
rootfs
中
sudo cp -r linux-6.8.7/ temp/usr/src/
- 安裝
rootfs
到SD卡
sudo mount /dev/sdb2 /mnt
sudo rm -rf /mnt/*
sudo cp -rp temp/* /mnt/
sudo umount /mnt/
- 插入SD卡,開機,首先連線網路
nmcli n
# 如果是disabled執行下面這行命令
nmcli n on
# 檢視網路裝置
nmcli dev
wifi
一般是正常的,eth0
如果是unmanaged
則執行該命令[6]
sudo nmcli dev set eth0 managed yes
我這樣成功了,但不保證一定可以。如果仍然不行可以看註腳的網址,那篇回答同時介紹了另一種方法
連線wifi
# 開啟Wi-Fi
nmcli r wifi on
# 掃描附近Wi-Fi熱點
nmcli dev wifi
# 連線Wi-Fi,替換SSID為Wi-Fi名,PASSWORD為Wi-Fi密碼
nmcli dev wifi connect "SSID" password "PASSWORD" ifname wlx70f11c658d80
配置靜態ip
# 獲取當前ip(假設獲取到ip為192.168.31.102)
ifconfig
# 將當前ip設為靜態ip
sudo nmcli con mod wlx70f11c658d80 ipv4.method manual ipv4.addr 192.168.31.102/24 ipv4.gateway 192.168.31.1 ipv4.dns 192.168.31.1
sudo reboot
- 解決中文亂碼[7]
locale -a
正常情況下這裡應該只有C
、C.utf8
、POSIX
,輸入下面的命令
sudo dpkg-reconfigure locales
按3下enter直到出現如圖所示內容
輸入下面這些數字並回車
# en_US, zh_CN, zh_SG
160 492 497
選擇自己想作為的系統主語言,回車,等待配置完成後重啟即可。
- 修改
hostname
#修改檔案第一行為自己想要的名字即可
sudo vim /etc/hostname
6. 移植核心樹
理論上只需要這樣就可以了[8]
cd /usr/src/linux-6.8.7/
# 因為之前移植kernel編譯過了,應該不用再make一遍了吧?
# 反正不行就再make一次(被打)
sudo make modules
sudo make modules_install
題外話(配置Clion用於Linux驅動開發)
這篇文章起因是Clion無法找到file_operations
結構體,但這樣移植之後還是找不到。配置Clion遠端開發的教程很多,比如這篇,這裡不做贅述,僅提出我這個問題的解決辦法:
- 在
CMakeLists.txt
中加入這樣一段
include_directories("/usr/src/linux-6.8.7/include/")
File -> Reload CMake Project
Tool -> Resync with Remote Hosts
ubuntu製作SD啟動卡 ↩︎
全志H3 | 移植主線最新uboot 2023.04和kernel 6.1.11到Nanopi NEO開發板 ↩︎ ↩︎
usbwifi網路卡mt7601u驅動配置 ↩︎
Uboot命令 ↩︎
Ubuntu rootfs customization ↩︎
Ethernet device not managed ↩︎
解決ubuntu系統中文亂碼問題 ↩︎
【Linux核心樹】五步構建 ↩︎