NanoPi-NEO 全志H3移植Ubuntu 22.04 LTS、u-boot、Linux内核/内核树、mt7601u USB-Wi-Fi支持、配置CLion用于Linux驱动开发
前言
想在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
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