免责声明
⚠️警告:刷机有风险,操作需谨慎
刷写 Bootloader(BL2/FIP)、分区表(GPT)和固件系统涉及对硬件底层存储的直接操作。操作不当可能导致:
- 设备无法启动(变砖)
- 网络功能失效
- 分区表损坏导致数据全部丢失
- 硬件永久性损坏
本教程及配套固件仅供参考学习用途。作者不对因遵循本教程进行操作所导致的任何直接或间接损失承担责任,包括但不限于:
- 设备变砖、无法恢复
- 数据丢失或损坏
- 硬件故障或损坏
- 保修失效
在操作前,请确保你:
- 已充分理解刷机原理和风险
- 已备份所有重要数据
- 具备基本的 Linux 命令行操作能力
- 阅读并理解了完整的教程内容
如无法接受以上条款,请勿进行任何刷机操作。进行刷机即代表你已理解并承担全部风险。
本教程发布于 CSDN,仅为技术分享,并非官方指南。
以mtk-bpi-r3mini-NAND-20231115-single-image.bin为例,说清楚来龙去脉。
一、你要理解的核心:BPI-R3 Mini 的双存储架构
BPI-R3 Mini 上有两套存储介质:
为什么有两个存储?
- eMMC:出厂默认启动介质。8GB 空间,速度快。但 eMMC 焊接在主板上,刷坏了救砖相对麻烦(需要拆壳短接)。
- NAND:备选启动介质。BPI-R3 Mini 的 NAND 一般装的是 UBI 文件系统,适合频繁读写。刷 NAND 刷不死,即使写坏了也可以通过 U-Boot Web 界面恢复。
二、认识各种刷机文件
BPI-R3 Mini 的固件文件种类繁多,先搞清楚每种文件是干什么的:
QWRT/OpenWrt 系列的固件
QWRT-R24.04.06-mediatek-mt7986-bananapi_bpi-r3-mini-emmc-squashfs-sysupgrade.rar QWRT-R24.04.06-mediatek-mt7986-bananapi_bpi-r3-mini-nand-squashfs-sysupgrade.bin| 文件名关键词 | 含义 |
|---|---|
emmc-squashfs-sysupgrade | 用于刷到eMMC的升级包(写入 p5 分区) |
nand-squashfs-sysupgrade | 用于刷到NAND的升级包(通过 U-Boot Web 或 openwrt 升级) |
这两种都是sysupgrade格式,只包含 kernel + rootfs,不含 BL2 和 U-Boot。
MTK BSP 官方固件
mtk-bpi-r3mini-NAND-20231115-single-image.bin| 关键词 | 含义 |
|---|---|
NAND | 用于 NAND 闪存 |
single-image | 完整单文件镜像,包含 BL2 + FIP + Kernel + RootFS 全部内容 |
20231115 | 发布版本日期 |
这是最完整的镜像。刷这一个文件就相当于:刷 BL2 + 刷 U-Boot + 刷固件,一次完成。通常来自香蕉派官方的 BSP(Board Support Package)。
其他辅助文件
| 文件 | 说明 |
|---|---|
preloader.bin | 单刷 BL2(eMMC boot0 分区) |
bl31-uboot.fip | 单刷 FIP/U-Boot(eMMC p4 分区) |
gpt.bin | GPT 分区表(eMMC 头部 34 个扇区) |
nand-factory.bin | 从 U-Boot 写入 NAND 的工厂镜像 |
recovery.itb | eMMC 恢复分区镜像(p4 备用) |
sysupgrade.itb | eMMC 系统分区镜像(p5 主系统) |
三、核心概念:什么是 DD?
dd=Disk Dump(磁盘转储),是 Linux 上一个按字节原始复制数据的命令。
ddif=输入文件of=输出文件bs=块大小seek=跳过块数conv=fsync| 参数 | 含义 |
|---|---|
if= | 读取来源(Input File) |
of= | 写入目标(Output File)—— 可以是设备文件如/dev/mmcblk0 |
bs= | 每次读写的字节数(块大小),通常用 512 |
seek= | 在输出设备上跳过多少个 bs 块再开始写 |
count= | 只读写多少块(限制写入范围) |
conv=fsync | 写入完成后同步刷到磁盘(必须!否则可能没写完就断电) |
DD 和 cp/cat 的区别:
cp以文件为单位复制,会经过文件系统抽象层dd直接操作原始设备,绕过任何文件系统,直接读写字节- 所以
dd可以用来写分区表、写 bootloader、写裸镜像
警告:dd极其危险。dd if=/dev/zero of=/dev/mmcblk0会在 1 秒内抹掉整个 eMMC,没有任何确认提示。
四、刷机教程(核心)
场景:用mtk-bpi-r3mini-NAND-20231115-single-image.bin给 BPI-R3 Mini 刷机
这个文件是MTK BSP 全量 NAND 镜像,写的是 NAND Flash。
方法一:在 U-Boot 中从 U 盘刷(推荐)
这是最安全的路径,因为 U-Boot 下的环境最简单,且 NAND 刷不死。
准备工作
- 准备 U 盘,格式化为 FAT32
- 把
mtk-bpi-r3mini-NAND-20231115-single-image.bin复制到 U 盘根目录 - U 盘插入 BPI-R3 Mini 的 USB 口
- 将启动选择器拨到 eMMC(确保从 eMMC U-Boot 启动)
进入 U-Boot 命令行
有两种方式:
方式 A:串口中断(推荐)
- USB 转 TTL 连接 BPI-R3 Mini 的 UART 串口(3.3V)
- 波特率 115200
- 上电时按住
Ctrl+C或任意键中断启动,进入 U-Boot 命令行
方式 B:Web Failsafe(免串口)
- 启动选择器拨到 eMMC
- 上电前用网线连接路由器,保证可获取 IP
- 启动时让 U-Boot 加载 Web Failsafe(观察路由器分配的 IP)
- 浏览器打开
http://<分配给板子的IP>,进入 U-Boot Web 界面
U-Boot 命令刷写
# 1. 初始化 USB usb start # 2. 检查 U 盘内容 ls usb 0:1 # 3. 将镜像加载到内存 (0x40000000 是 U-Boot 的加载地址) fatload usb 0:1 0x40000000 mtk-bpi-r3mini-NAND-20231115-single-image.bin # 4. 擦除 NAND (0 偏移,擦除 128MB) nand erase 0x0 0x8000000 # 5. 将内存中的镜像写入 NAND nand write 0x40000000 0 0x8000000 # 6. 重启 reset断电,将启动选择器拨到 NAND 位置,再上电,应该从 NAND 启动新系统。
方法二:在已运行的系统中用 DD 写入(高手向)
如果你已经有一个可启动的 OpenWrt/QWRT 系统在跑(无论从 eMMC 还是 TFTP 启动),可以在系统里用dd将 single-image 写入 NAND。
Step 1:把镜像传到路由器
# 方式 A:通过 scp 传输scpmtk-bpi-r3mini-NAND-20231115-single-image.bin root@192.168.1.1:/tmp/# 方式 B:通过 wget 下载wgethttp://你的电脑IP/mtk-bpi-r3mini-NAND-20231115-single-image.bin-O/tmp/single-image.binStep 2:查看 NAND 设备
# 查看 MTD 设备布局cat/proc/mtd# 典型输出:# dev: size erasesize name# mtd0: 10000000 00020000 "spi-nand0"mtd0就是整个 NAND Flash。single-image.bin需要被直接写到原始 NAND 设备。
Step 3:写 NAND(关键步骤)
⚠️ 这一步会完全覆盖 NAND 里的所有内容,包括 BL2/FIP/系统,BL2 刷错会导致变砖,请仔细理解后再操作。
对于 single-image.bin 这个完整的 MTK BSP 镜像来说,它的结构从 NAND 的 0 偏移开始依次排列:
single-image.bin就是这个布局的线性二进制拼接文件。所以可以直接写入:
# 方法 A:通过 mtd 工具写入(推荐,自动处理坏块)flash_erase /dev/mtd000ddif=/tmp/single-image.binof=/dev/mtd0bs=2048conv=fsync# 方法 B:直接 dd 到 mtdblock(如果存在)ddif=/tmp/single-image.binof=/dev/mtdblock0bs=2048conv=fsync⚠️ 注意:
bs=2048是因为 NAND 的页大小通常是 2KB(具体看你的 NAND 型号),用 2048 可以避免跨页问题conv=fsync不能省,确保数据完全写入- 写完后不要直接重启,先执行
sync,等待 10 秒再断电
Step 4:切换启动介质
syncsyncreboot断电后,将启动选择器拨到 NAND 位置,再上电。
方法三:DD 刷 eMMC 组件(针对 NAND 启动已有 U-Boot 的情况)
如果板子上已经有能启动的 U-Boot,只想单独更新某个组件,可以用 dd 精确写入:
刷 BL2(preloader)
# BL2 在 eMMC 的 boot0 分区,这是特殊分区,需要先解除写保护echo0>/sys/block/mmcblk0boot0/force_ro# 先擦除(可选)ddif=/dev/zeroof=/dev/mmcblk0boot0bs=512count=8192conv=fsync# 写入 BL2ddif=preloader.binof=/dev/mmcblk0boot0bs=512conv=fsync刷 FIP(U-Boot)
# FIP 在 eMMC 主存储的第 13312 扇区开始(约 6.5MB 偏移)ddif=bl31-uboot.fipof=/dev/mmcblk0bs=512seek=13312conv=fsyncseek=13312的由来:13312 × 512B = 6,815,744 字节 ≈ 6.5MB,这就是 GPT 规范中 FIP 分区的起始位置。
刷 GPT 分区表
# GPT 表在 eMMC 头部 34 个扇区ddif=gpt.binof=/dev/mmcblk0bs=512seek=0count=34conv=fsync刷系统分区(eMMC 启动的情况)
# 将 sysupgrade 镜像写入 eMMC 的 p5 分区(系统分区)ddif=QWRT-*-emmc-squashfs-sysupgrade.binof=/dev/mmcblk0p5bs=512conv=fsync五、常见问题 FAQ
Q1:刷错了变砖了怎么办?
BPI-R3 Mini 基本刷不死,前提是:
- eMMC 中的 BL2 + FIP 还在→ 插 USB 到 U-Boot 重新刷 NAND 即可
- eMMC 也被刷坏了→ 需要救砖:拆外壳,短接 eMMC CLK 和 GND,从 SD 卡或 USB 启动 U-Boot,重新写入 eMMC
如果只是 NAND 固件刷坏了,切换到eMMC 启动,进入系统后用 DD 重新写 NAND。
Q2:如何确认当前是从哪个介质启动的?
# 查看 U-Boot 环境变量fw_printenv boot_vol2>/dev/null||cat/proc/cmdline# 或者看内核启动参数cat/proc/cmdline# NAND 启动的 cmdline 会包含 ubi.mtd=...# eMMC 启动的 cmdline 会包含 root=/dev/mmcblk0p...Q3:MTK single-image.bin 和其他 sysupgrade.bin 有什么区别?
| 特性 | single-image.bin | sysupgrade.bin |
|---|---|---|
| 是否包含 BL2 | ✅ 是 | ❌ 否 |
| 是否包含 U-Boot | ✅ 是 | ❌ 否 |
| 是否包含 RootFS | ✅ 是 | ✅ 是 |
| 写入目标 | NAND 原始设备 | MTD 分区 / eMMC 分区 |
| 适用场景 | 出厂刷机 / 完整重刷 | 日常升级 |
Q4:DD 和 Sysupgrade 哪个好?
- 日常升级→ 用
sysupgrade(保留配置,更安全) - 全新刷机 / 换系统 / 救砖→ 用
dd写 single-image(彻底干净)
Q5:刷完不启动怎么办?
- 确认启动选择器拨到了正确位置
- 串口看 log,观察停在哪个阶段
- 如果 U-Boot 能启动但系统不行 → NAND 没写对或镜像不匹配
- 如果 U-Boot 都不启动 → BL2/FIP 损坏,走救砖流程
Q6:M.2 WiFi /5G 模块怎么接?
M.2 插槽的 USB 信号走的是xhci-mtk控制器(对应Bus 002)。在设备树里使能后,模块会被识别为 USB 设备。模块的供电取决于 BPI-R3 Mini 硬件版本:
- 大部分版本上电即供电,不需要额外 GPIO 控制
- 可以通过
lsusb确认模块是否被识别
六、总结
关键命令速查:
写 single-image 到 NAND(U-Boot 中)
usb start
fatload usb 0:1 0x40000000 镜像文件名.bin
nand erase 0x0 0x8000000
nand write 0x40000000 0 0x8000000
写 single-image 到 NAND(Linux 中)
flash_erase /dev/mtd0 0 0
dd if=/tmp/镜像文件名.bin of=/dev/mtd0 bs=2048 conv=fsync
刷 BL2
echo 0 > /sys/block/mmcblk0boot0/force_ro
dd if=preloader.bin of=/dev/mmcblk0boot0 bs=512 conv=fsync
刷 FIP
dd if=bl31-uboot.fip of=/dev/mmcblk0 bs=512 seek=13312 conv=fsync