香蕉派 BPI R3 玩机记录

香蕉派 BPI R3 玩机记录

最近项目需要用到香蕉派的 BPI R3 开发板,折腾起来极其难受,故将整个过程记录下来,以备后用。

常用链接

常用数据

硬件

  • 联发科 MT7986 (Filogic 830) 双核 ARM Cortex A53 + MT7531;2G DDR4 内存;板载 128 MB Nand flash;板载 8GB eMMC;26 Pin GPIO;5 个千兆以太网接口;2 个 2.5 G SFP 接口;Wifi 6 4x4 2.4G Wifi (MT7975N) + 4x4 5G Wifi (MT7975P);M.2 KEY-M PCIe接口;M.2 Key B USB 接口;1 USB 3.0 接口;供电 20W/12V TypeC PD。

  • 尺寸:$100.5\times 148\mathrm {mm}$;重量:$200\mathrm g$。

  • TTL 串口:波特率 115200;数据位 8;停止位 1;奇偶校验无;流控制无。

  • 跳线设置(侧面可以上下波动的开关)

    跳线开关 SW1(SW1-A) SW2(SW1-B) SW5(SW1-C) SW6(SW1-D)
    SPIM-NoR X
    SPIM-Nand X
    eMMC 高(一说 X)
    SD 卡 X

    注:SW1-A 和 SW1-B 用于选择 boot strap;SW1-C 用于切换 SPI-Nand 或 SPI-Nor 直连到 CPU 的 SPI 总线;SW1-D 用于切换 SD 卡或 EMMC 设备直连到 CPU 的 EMMC 总线。

  • 网口命名:包括 SFP 光口从左起分别为:eth1、LAN5 (sfp2)、LAN0 (wan)、LAN1、LAN2、LAN3、LAN4。在 OpenWrt 中,eth1 & lan0 被划给 br-wan桥;lan4 & rax0 & lan2 & lan5 & ra0 & lan3 & lan1 被划给了 br-lan桥。其中 ra0 是 2.4G WiFi 口,rax0 是 5G WiFi 口。
    eth0 比较特别,是 CPU(mt7986) 和交换机芯片(mt7531a)之间的直连网口,不能禁用。LAN 05 都直连到交换机芯片上(eth1 是否直连存疑)。HNAT 硬件加速可以应用于 LAN 05 以及 eth1 所有网口。

    gmac1 (eth0) ---- (p6)mt7531(P0) ---- WAN
                                (P1-4) -- LANx4
                                (p5/lan4) ---- right SFP slot (sfp2)
    gmac2 (eth1) ---- left SFP slot (sfp1)
    

软件

  • LAN 口默认 IP:192.168.1.1。

  • 默认用户名/密码:pi/bananapi(没找到例子)或 root/bananapi(官方 Ubuntu 镜像)或 root/<空>(官方 OpenWrt 镜像)。

  • 板子到手建议先跑 mtd erase /dev/mtd10,清掉 mtd10 才能保存配置!

  • 如果系统没法识别 U 盘,那么试试安装 kmod-usb-storage-uas 包。

  • 切换启动途径:
    NOR:fw_setenv bootcmd "run nor_init ; env default bootcmd ; saveenv ; reset" & reboot
    NAND:fw_setenv bootcmd "run ubi_init ; env default bootcmd ; saveenv ; reset" & reboot

    EMMC:fw_setenv bootcmd "run emmc_init ; env default bootcmd ; saveenv ; saveenv ; reset" & reboot
    刷入 NOR:

    modprobe mtd-rw i_want_a_brick=1
    mtd write openwrt-mediatek-filogic-bananapi_bpi-r3-nor-preloader.bin bl2
    mtd write openwrt-mediatek-filogic-bananapi_bpi-r3-nor-bl31-uboot.fip fip
    mtd write openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb recovery
    mtd write openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb fit
    

    刷入NAND:

    modprobe mtd-rw i_want_a_brick=1
    mtd write openwrt-mediatek-filogic-bananapi_bpi-r3-snand-preloader.bin bl2
    mtd write openwrt-mediatek-filogic-bananapi_bpi-r3-snand-bl31-uboot.fip fip
    . /lib/functions.sh
    ubiformat /dev/mtd$(find_mtd_index ubi)
    ubiattach -m $(find_mtd_index ubi)
    ubimkvol /dev/ubi0 -n 0 -N ubootenv -s 1M
    ubimkvol /dev/ubi0 -n 1 -N ubootenv2 -s 1M
    set -- $(wc -c openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb)
    ubimkvol /dev/ubi0 -n 2 -N fit -s $1
    ubiupdatevol -s $1 /dev/ubi0_2 openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb
    set -- $(wc -c openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb)
    ubimkvol -n 3 -N recovery -s $1
    ubiupdatevol -s $1 /dev/ubi0_3 openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb
    

刷系统

烧录到 SD 卡

按照快速上手的说法,到我手里的应该是裸机,但实际上 SPI 里都已经预装了 OpenWrt,所以可以直接从进入 SPI Nand 系统开始,故跳过此部分。

烧录官方镜像到板载 EMMC

官方指南:

由于 SD 卡和板载 EMMC 共用一个 SOC 接口,因此需要先烧录 SD 镜像,然后从 SD 卡启动,再将 Nand 镜像烧录到 Nand 中,然后将 boot strap 改为从 Nand 启动,再将 EMMC 镜像烧录到 EMMC 中。最后将 boot strap 改为从 EMMC 启动。

由于我买到的板子在 SPI Nand 里预装了 OpenWrt,故从这部分开始:

  1. 首先在 U 盘里准备好从这个位置下载的 EMMC 镜像以及引导。
    需要注意的是,如果需要刷 Debian 或 Ubuntu 系统,那么也需要下载 OpenWrt 部分最新的文件,因为只有 OpenWrt 这边下到的是个压缩包,里面有 bl2_emmc.img 引导文件,其他地方都是只有一个 .img。

  2. 首先将跳线开关调成“高低高低”,然后插电开机,从 SPI Nand 启动,接着插入 U 盘,官方的 SPI Nand 里默认是支持自动挂载的,如果不能自动挂载,那么需要手动挂载:

    mount -t <磁盘格式,如 vfat/exfat> /dev/<磁盘设备名,一般是sda1> /mnt/<磁盘设备名,需要提前创建好文件夹,或直接挂到 /mnt>
    cd /mnt
    
  3. 把镜像刷到 EMMC 设备里:

    echo 0 > /sys/block/mmcblk0boot0/force_ro
    dd if=bl2_emmc.img of=/dev/mmcblk0boot0
    dd if=mtk-bpi-r3-EMMC-WAN1-SFP1-20220928-single-image.img of=/dev/mmcblk0
    mmc bootpart enable 1 1 /dev/mmcblk0
    
  4. 关机,物理拔电,拔掉 U 盘,把跳线开关切换到“低高高低”,从 EMMC 启动,重新插电开机,享受 EMMC 的大容量吧~

烧录 OpenWrt 官方固件

  1. 固件下载页,EMMC 需要下载 EMMC-BL31-UBOOT.FIP & EMMC-PRELOADER.BIN & sdcard.img.gz。把文件放到一个文件夹,并在此文件夹设置好 TFTP 服务器(推荐用 MobaXterm)。

  2. 首先连接 TTL 串口线,波特率设置为 115200,然后在启动目录选择 Load BL31+U-Boot FIP via TFTP ... 选项刷入 FIP,选择 Load BL2 preloader via TFTP ... 选项刷入 preloader。最后进系统插 U 盘刷入 sdcard.img 即可。
    不需要 TTL 的方法:Sinovoip BananaPi BPi R3

  3. 这时候还不能享受 EMMC 的大容量,因为固件给 /overlay 目录的空间很小,需要我们手动扩容。
    可以通过df -h 看到,/overlay 的物理磁盘是 /dev/mmcblk0p66,但实际上 /dev/mmcblk0p65/dev/mmcblk0p66/dev/mmcblk0p128都是从 /dev/mmcblk0p5 虚拟出来的。使用 lsblk 可以看到:

    NAME           MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
    mmcblk0        179:0    0  7.3G  0 disk
    ├─mmcblk0p1    179:1    0  512K  0 part
    ├─mmcblk0p2    179:2    0    2M  0 part
    ├─mmcblk0p3    179:3    0    4M  0 part
    ├─mmcblk0p4    179:4    0   32M  0 part
    ├─mmcblk0p5    179:5    0  104M  0 part 
    ├─mmcblk0p6    179:6    0   20M  0 part 
    ├─mmcblk0p65   259:0    0  5.3M  1 part /rom
    ├─mmcblk0p66   259:1    0 93.5M  0 part /overlay
    └─mmcblk0p128  259:2    0    4M  0 part 
    mmcblk0boot0   179:8    0    4M  1 disk
    mmcblk0boot1   179:16   0    4M  1 disk
    

    因此扩容分为两步:

    • 扩容 /dev/mmcblk0p5 容量,这里有两种方法,一种是使用 cfdisk /dev/mmcblk0,先使用 sort/dev/mmcblk0p5 分区移到尾部,再扩容到 $6.9\mathrm G$;另一种办法是用 parted 中的 resizepart 将此分区结束点设置到 835(未实际尝试),然后关机拔电

    • 切换到 SPI NAND 启动,直接使用 resize.f2fs /dev/mmcblk0p66 会得到 Mount unclean image to replay log first 的错误提示,现在需要先将此分区挂载一次再卸载:

      mount /dev/mmcblk0p66 /mnt
      umount /dev/mmcblk0p66
      resize.f2fs /dev/mmcblk0p66
      

      就可以完美扩容。(不要相信网上说的 fsck.f2fs -f,没用的,根本没错误检查也没用,只会强制修复个寂寞)此时再切换回 EMMC 启动,尽情享受大容量吧~

安装 pypcapy

为香蕉派编译 Python wheel 包

因为 OpenWrt 系统的限制,pip 安装包时是不能在系统中根据源代码打包的(主要是因为缺各种 -dev 包,虽然 python-dev 是有的),所以我们需要通过交叉编译来为 OpenWrt 的 pip 编译 wheel 包。

为了方便,我们选择同为 aarch64 架构的 Orange Pi 5 Plus 启动 musllinux 的 docker 来为香蕉派编译 wheel 包。

首先需要安装 docker,并且换源,接着执行下面的指令:

sudo docker pull "quay.io/pypa/musllinux_1_1_aarch64"
git clone <编译 wheel 所需要的源码地址>
cd <源码文件夹>
docker run --rm -e PLAT="musllinux_1_1_aarch64" -e "PYTHON_TAGS=\"cp39-cp39\"" -v `pwd`:/io -it "quay.io/pypa/musllinux_1_1_aarch64:latest" sh

便可以进入容器中,此时先进行换源、 修改Python 版本、安装 -dev 库等操作(这里以编译 pcapy 为例):

sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
export PATH=/opt/_internal/cpython-3.9.18/bin:$PATH
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
apk update
apk add --update alpine-sdk
apk add libpcap-dev
cd /io

此时就可以开始快乐地编译 wheel了~

但其实我们也可以直接借助 pip 安装的缓存来获得包:

/ # pip install pcapy-ng
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting pcapy-ng
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/1d/00/b8e11541298de365900b599a6ebcf711e0c234c55a0246c7b2c4302c037c/pcapy-ng-1.0.9.tar.gz (38 kB)
  Preparing metadata (setup.py) ... done
Building wheels for collected packages: pcapy-ng
  Building wheel for pcapy-ng (setup.py) ... done
  Created wheel for pcapy-ng: filename=pcapy_ng-1.0.9-cp39-cp39-linux_aarch64.whl size=90829 sha256=68aecdbc5e4b29bdbf5d7f5e564fe831f90475e006624eb53e8c49b85c168635
  Stored in directory: /root/.cache/pip/wheels/54/5c/05/284f873a628cd36db1429dfa979fef513fd67a711aef56e638
Successfully built pcapy-ng
Installing collected packages: pcapy-ng
Successfully installed pcapy-ng-1.0.9

我们可以看到,包被缓存到了 /root/.cache/pip/wheels/54/5c/05/284f873a628cd36db1429dfa979fef513fd67a711aef56e638 目录,我们直接从这个目录把编译好的包拷贝到 /io 下即可。

但将 wheel 包放到香橙派上安装好后,会发现还是 import 不了,这时候我们需要将 .so 文件命名为正确的格式。先用 pip show pcapy-ng 查看包的安装位置,接着 cd 过去,会发现名为 pcapy.cpython-39-aarch64-linux-gnu.so 的动态链接库。观察同文件夹下的其他 .so 文件,会发现没有 linux-gnu 后缀,故通过 mv 改名删掉即可。