嵌入式linux设备升级和sm32升级对比
很好,上位机从 STM32F103 的“双区 bootloader+app1/app2”思维迁移到 RK3588S 的嵌入式 Linux,其实理念一脉相承:分区(或“分区/分槽”)+ 安全校验 + 断电可回滚。下面按“原理 → 方式 → 典型落地方案(含步骤)→ 和 STM32 的对照”来讲。
一、启动与分区整体观(先把“地图”搞清楚)
启动链(简化)
- BootROM(SoC 固化,相当于“硬件级 bootloader”)
- SPL/IDBLoader(初始化 DDR/时钟)
- U-Boot(真正的可编程引导器)
- Linux 内核 + DTB + initramfs
- RootFS(根文件系统) + /data
常见分区/槽位布局(Linux 产品常用)
idbloader
(原始分区,SPL)uboot
(原始分区,U-Boot/ITB)trust
(可选,OP-TEE/ATF)bootA
,rootfsA
(槽 A)bootB
,rootfsB
(槽 B)recovery
(救援小系统,只读)data
(应用数据,读写)
思路:和你原来的 app1/app2 一样,A/B 双槽保证升级写在“另一半”,切换失败还能回滚;
recovery
用来“拉你一把”。
二、升级目标与关键点
- 可靠:断电/网络中断不可把设备“刷死”。
- 可回滚:启动 N 次失败自动退回上一版本。
- 可验证:镜像签名校验(防篡改),根分区可配 dm-verity 只读防破坏。
- 分离数据:系统和
/data
分开,升级不抹掉用户/校准数据。 - 可分层:系统固件(boot/kernel/rootfs)与应用层(包管理/容器)各自独立升级。
三、常见升级方式(从“底层到应用层”,由重到轻)
1) 工厂烧录/救砖(离线整包)
- 场景:产线/返修/完全损坏。
- 介质:USB OTG(MaskROM/Loader 模式)、TF 卡、SATA/USB 量产器。
- 内容:整盘镜像或各分区镜像(idbloader/uboot/trust/boot/rootfs…)。
- 优点:最干净;缺点:需要现场或物理接入。
2) 系统级 OTA(A/B 无感升级,强推荐)
-
思路:有
A/B
槽;在线下载“包”,写入未使用槽 → 切换引导 → 健康检查成功再确认“生效”,否则回滚。 -
包形式:整分区镜像、差分包(bsdiff/xdelta/zstd)、或 OSTree(内容寻址)。
-
落地工具:
- RAUC、SWUpdate、Mender、OSTree/bootupd(任选其一)。
-
优点:可靠、断电可恢复;缺点:实现略复杂(但值得)。
3) 包管理升级(Debian/Ubuntu:apt;Yocto:opkg/dnf)
- 思路:仅升级某些软件包。
- 优点:颗粒度细;缺点:不如整包可控,容易“漂移”。
- 最佳实践:只读 rootfs + OverlayFS,通过包仓库“发布应用层”,系统层仍走 A/B。
4) 容器镜像升级(Docker/Podman)
- 思路:系统层冻结,应用以容器交付,拉新镜像即升级。
- 优点:隔离强、回滚快;缺点:要管理镜像空间与网络。
5) 单独升级内核/DTB/引导器(谨慎)
- 对象:
boot
/kernel
/dtb
/uboot
/trust
。 - 风险:一旦写坏,设备可能“黑砖”;建议纳入 A/B 或由 recovery 执行并验证。
6) U-Boot 阶段升级(紧急/早期)
- 方式:fastboot/TFTP/rockusb 从 U-Boot 下载镜像写入。
- 场景:现场救援或早期 bring-up。生产中不常用。
四、推荐的一套“稳妥可落地方案”(适合 RK3588S Linux 产品)
目标:企业级可靠 OTA + 易维护 + 快速回滚
1. 分区规划
idbloader
(raw)uboot
(raw)trust
(raw,可选)bootA
(ext4 或 FIT/EFI)rootfsA
(ext4,建议只读 + dm-verity)bootB
/rootfsB
(同上)recovery
(小系统,内置升级与修复工具,ext4 只读)data
(ext4,应用数据/日志/配置,读写)
2. 引导器逻辑(U-Boot / EFI 同理)
-
环境变量包含:
slot=a|b
,upgrade_available
,bootcount
,bootlimit
。 -
规则:
- 正常开机:从
slot
指定的bootX/kernelX
启动。 - 升级后首次重启:
upgrade_available=1
,bootcount
自增。 - 系统用户态健康检查成功(比如启动 2 分钟后服务全部 OK):清掉
upgrade_available
并写“OK”标志。 - 若连续
bootcount >= bootlimit
仍未标记 OK,则自动回滚到另一槽。
- 正常开机:从
3. OTA 组件选择
- 用 RAUC(或 SWUpdate/Mender 任一)管理镜像包、签名和写盘。
- 传输渠道:HTTPS(可配 MQTT 触发/轮询)。
- 包含内容:最少包含
boot+rootfs
的镜像;可做差分包减少流量。 - 签名:在构建机生成密钥;设备端保留公钥验证
.raucb/.swu
。 - 根分区启用 dm-verity(只读完整性),应用写入放
/data
或 OverlayFS。
4. 升级流程(设备侧)
- Agent 接到“有新版本” → 下载到
/data/update/
。 - 校验签名/哈希 → 调 RAUC 写入未激活槽(如 B):写
bootB
、rootfsB
。 - 设置
slot=B
、upgrade_available=1
→ 重启。 - 新系统启动后运行
health-check.service
(看关键进程/网络/硬件自检)。 - 通过后写“OK”并清标志;失败 N 次自动回滚到
slot=A
。
5. 救援与离线
recovery
里放:网络工具、量产/刷机脚本、日志导出;支持 U-Boot 菜单按键/看门狗主动进。- 支持 U 盘/TF 卡“离线升级包”:在 recovery 挂载并调用同一 RAUC/SWUpdate 流程。
6. 安全与可追溯
- Secure Boot / 签名链(可用 Rockchip 安全启动 + U-Boot FIT 签名)
- 镜像签名 + 版本号/时间戳/Changelog;
- 升级全流程日志写入
/data/logs
,便于问题复盘。
五、和你熟悉的 STM32F103 升级对照
STM32 术语 | RK3588S/Linux 对应 | 说明 |
---|---|---|
ROM/ISP | BootROM | 固化在芯片,决定从哪里启动 |
Bootloader | U-Boot | 可编程引导器,决定启动哪个槽、回滚等 |
app1/app2 | rootfsA/rootfsB (+ bootA/bootB) | 双槽切换,断电可回滚 |
固件包 | OTA 包(.raucb/.swu/镜像) | 带签名、可差分 |
升级确认 | 健康检查 + 标记 OK | 失败自动回滚 |
量产烧写 | 工厂刷机/救砖 | USB/TF 卡整包烧录 |
六、几种典型实现“怎么选”
- 产品型设备(强可靠):A/B OTA(RAUC/SWUpdate/Mender) + 只读 rootfs(dm-verity)+ recovery。
- 开发板/内部环境:包管理(apt/opkg)+ 容器。
- 对网络/成本极端敏感:做差分更新或 OSTree(节省流量且原子切换)。
- 应用变化频繁:系统层 A/B 固定,应用用容器发版。
七、简化版“落地清单”(你可以照着做)
- 规划 GPT 分区:
idbloader/uboot/trust/bootA/B/rootfsA/B/recovery/data
。 - 构建两套
boot/rootfs
(A/B),rootfs 设为只读(可上 dm-verity),应用写/data
。 - U-Boot 打开 BOOTCOUNT/BOOTLIMIT,实现 A/B 环。
- 选型并集成 RAUC(或 SWUpdate/Mender/OSTree)。生成签名的升级包。
- 写升级 Agent(systemd 服务):下载→校验→刷写未激活槽→设置环境变量→重启。
- 写 health-check.service:启动后自测通过→确认生效;失败自动回滚。
- 做 recovery 分区:支持 U 盘/TF 卡离线升级与日志导出。
- 建版本/日志闭环:每台设备可追踪版本、升级历史、失败原因。
如果你愿意,我可以基于 RK3588S Linux SDK(Buildroot/Debian),给你一份最小可用的 A/B OTA 示例工程(分区表、U-Boot 环境、RAUC 配置、health-check、升级脚本与服务清单),你直接对着集成即可。
太好了 — 我这就给你一套**可直接拿去试(最小可用)**的 A/B OTA 示例方案,包含:
- 推荐的分区表(GPT)与说明
- U-Boot 环境变量与引导脚本(含 bootcount/bootlimit 逻辑)
- RAUC bundle、manifest 示例与打包/签名命令(RAUC 常用)
- 设备端流程脚本:升级 Agent + health-check + systemd 单元(可直接复制粘贴)
- 工具/命令汇总(刷机、回滚、调试快捷命令)
- RK3588S / Rockchip 注意点与参考文献链接(方便你对接 BSP)
我把关键实现放成可复制运行的片段,你按着替换设备实际分区、路径和文件名就能跑。文中涉及 RAUC 与 U-Boot 的集成逻辑参考自官方文档与社区最佳实践。(RAUC, bootlin.com, GitHub)
1) 最小分区表(GPT,示例)
下面是一个常见、适合 A/B OTA 的 GPT 分区布局(名字用来索引):
idbloader
— 固件(raw,SPL)uboot
— U-Boot(raw)trust
— optional(TF-A/OP-TEE)boot_a
— boot kernel + dtb(ext4 或 raw FIT)rootfs_a
— rootfs A(ext4 或 squashfs,建议只读)boot_b
— boot Brootfs_b
— rootfs Brecovery
— 小型 rescue system(只读)data
— /data(读写,保存用户数据/日志)
示例 GPT 分区表(fdisk/sfdisk 风格) — 请按设备块设备名调整(例如 /dev/mmcblk0
或 /dev/nvme0n1
):
# 注意:实际分区大小需按你镜像大小/板子 RAM/闪存调整
# 下面仅示意分区顺序
parted /dev/mmcblk0 --script mklabel gpt
parted /dev/mmcblk0 --script mkpart idbloader 1MiB 5MiB
parted /dev/mmcblk0 --script mkpart uboot 5MiB 9MiB
parted /dev/mmcblk0 --script mkpart trust 9MiB 13MiB
parted /dev/mmcblk0 --script mkpart boot_a 13MiB 133MiB
parted /dev/mmcblk0 --script mkpart rootfs_a 133MiB 1536MiB
parted /dev/mmcblk0 --script mkpart boot_b 1536MiB 1656MiB
parted /dev/mmcblk0 --script mkpart rootfs_b 1656MiB 3060MiB
parted /dev/mmcblk0 --script mkpart recovery 3060MiB 3160MiB
parted /dev/mmcblk0 --script mkpart data 3160MiB 100%
把 boot_a/boot_b
做成小分区(放 kernel/dtb/fit/boot.img),rootfs_x
放 squashfs 或 ext4(推荐只读 squashfs + dm-verity 或 ext4+dm-verity)。
2) U-Boot 环境变量与引导逻辑(最关键)
要实现 A/B 自动回滚,U-Boot 需要支持 bootcount/bootlimit
或用 RAUC 推荐的 BOOT_ORDER
, BOOT_<name>_LEFT
变量机制。RAUC 文档给了标准做法:U-Boot 环境中维护 BOOT_ORDER
(例如 “A B”),并用 BOOT_A_LEFT
表示 A 槽还能被尝试多少次。Linux 在安装更新后会通过 fw_setenv
写这些变量以触发“计数/回滚”机制。(RAUC, bootlin.com)
下面给一个**简化的 U-Boot 引导脚本(boot.scr)**范例(伪脚本,按你的板子启动命令调整):
# 假设 U-Boot 环境中已有变量 BOOT_ORDER (e.g. "A B") 和 BOOT_A_LEFT, BOOT_B_LEFT
# 引导时的伪逻辑(在 U-Boot 的 script 中实现)
setenv tried ""
for i in ${BOOT_ORDER}; do# 读取 LEFT 计数env get BOOT_${i}_LEFT || setenv BOOT_${i}_LEFT 0if test ${BOOT_${i}_LEFT} -gt 0; thenecho "Trying slot: ${i}"# 将当前 slot 标记到 tried 列表setenv tried "${tried} ${i}"# 从相应分区加载 kernel/initramfs/dtb# 以下加载命令需根据板子 mmc/partition 的编号调整if mmc dev 0; thenif test "${i}" = "A"; then# 假设 boot_a 在 mmcblk0p4load mmc 0:4 ${kernel_addr_r} /boot/Imageload mmc 0:4 ${fdt_addr_r} /boot/dtbelseload mmc 0:6 ${kernel_addr_r} /boot/Imageload mmc 0:6 ${fdt_addr_r} /boot/dtbfibooti ${kernel_addr_r} - ${fdt_addr_r}fifi
done# 如果都失败,跳 recovery
echo "All slots failed, booting recovery"
# 加载 recovery 并启动
如何从 Linux 操作 U-Boot 环境:常用 fw_printenv
/ fw_setenv
(来自 u-boot-tools
)。RAUC 在安装完新槽后会在 Linux 中写入 BOOT_ORDER
, BOOT_<slot>_LEFT
,并将 upgrade_available
之类变量写入以启动计数流程。(RAUC, bootlin.com)
重要 U-Boot 支持点:
- 确保编译/配置时启用了
CONFIG_BOOTCOUNT
或环境变量持久化(env stored in flash or FAT)。有些 Rockchip BSP 已经支持;若没支持需在 U-Boot 源里启用并选择 env 存储方式。(lists.yoctoproject.org)
3) RAUC:bundle + manifest + 打包/签名(最小示例)
RAUC 是很常用的 A/B 更新管理工具(bundle 格式是一个 SquashFS 后跟签名)。RAUC 的 bundle 里包含 manifest.raucm
来描述要刷写的映像与挂载点。官方有清晰的 bundle 制作与 U-Boot 集成说明。(RAUC)
一个最小 manifest.raucm
示例(伪):
[system]
compatible = "mydevice"[image.boot]
filename = "boot.img"
type = "raw"
device = "/dev/mmcblk0p4" # boot_a 分区(示例)
compress = "none"[image.rootfs]
filename = "rootfs.squashfs"
type = "raw"
device = "/dev/mmcblk0p5" # rootfs_a 分区(示例)
compress = "none"
在构建 host 端打包并签名(假设你已经有私钥 cert.pem
/ key.pem
):
# 在 build-host 上准备 input-dir,包含 boot.img, rootfs.squashfs, manifest.raucm
rauc bundle --cert cert.pem --key key.pem ./input-dir myupdate.raucb
设备端安装:
# 将 myupdate.raucb 放到设备 /data/update/
rauc install /data/update/myupdate.raucb
# rauc 会验证签名并安装到指定设备分区(manifest 指定)
RAUC 会在安装过程中按 manifest 写分区,并可以在成功写入后由 Linux 写 U-Boot 环境以触发 boot 次计数(RAUC 文档有 U-Boot 集成说明)。(RAUC)
4) Device-side:升级 Agent + health-check + systemd(可拷贝)
下面给出最小可用的实现,你放到设备上,替换 URL/路径后即可实测。
a) health-check.sh
(位于 /usr/local/bin/health-check.sh
,systemd 启动后运行):
#!/bin/bash
# 简单健康检查:关键服务是否在运行、网络是否连通
# 返回 0 表示健康,非 0 表示不健康# check a service
systemctl is-active --quiet my_critical.service || exit 1# check network
ping -c 1 8.8.8.8 >/dev/null 2>&1 || exit 2# 你可以加入更多硬件健康判断逻辑
exit 0
记得 chmod +x /usr/local/bin/health-check.sh
.
b) upgrade-agent.py
(下载并触发 RAUC,放 /usr/local/bin/upgrade-agent.py
):
#!/usr/bin/env python3
import requests,subprocess,sys,osUPDATE_URL = "https://updates.example.com/latest/myupdate.raucb"
TMPDIR = "/data/update"os.makedirs(TMPDIR, exist_ok=True)
bundle_path = os.path.join(TMPDIR, "myupdate.raucb")# 下载(简化,真实使用需 retry、断点续传、签名校验)
print("Downloading update...")
r = requests.get(UPDATE_URL, stream=True, timeout=60)
if r.status_code != 200:print("download failed", r.status_code)sys.exit(1)
with open(bundle_path, "wb") as f:for chunk in r.iter_content(1024*64):if chunk:f.write(chunk)# 可选:校验哈希 (sha256)
# 调用 rauc
print("Installing with RAUC...")
p = subprocess.run(["rauc","install",bundle_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(p.stdout.decode(), p.stderr.decode())
if p.returncode != 0:print("RAUC install failed")sys.exit(2)# 安装完成后 RAUC 会触发写 U-Boot env (如果配置了), 并设置 upgrade flags
print("Install succeeded; rebooting to new slot")
subprocess.run(["sync"])
subprocess.run(["reboot","-f"])
(注:真实代码要更健壮,支持断点续传、校验、签名验证、错误上报等)
c) rauc-health.service
(systemd,负责新系统启动后做 health-check 并确认)
[Unit]
Description=RAUC health check and finalize update
After=network.target[Service]
Type=oneshot
ExecStart=/usr/local/bin/health-check.sh
# If health-check returns 0, run custom confirm script to mark update OK
ExecStartPost=/bin/sh -c 'if [ $? -eq 0 ]; then echo "OK" > /data/update/ok; /usr/bin/fw_setenv upgrade_available 0; /usr/bin/fw_setenv boot_tries 0; fi'
RemainAfterExit=yes[Install]
WantedBy=multi-user.target
(这里示意:实际应用用 rauc
的 rauc status
或 rauc confirm
/rauc install
的 hooks 来进行更标准的确认流程)
5) 常用调试 / 操作命令(开发时很有用)
- 查看 U-Boot env(在 Linux 中,需安装
u-boot-tools
并配置/etc/fw_env.config
):
fw_printenv
fw_setenv BOOT_ORDER "B A"
fw_setenv BOOT_A_LEFT 3
- 手动用 RAUC 安装并观察:
rauc -v install /path/to/myupdate.raucb
journalctl -u rauc.service -f
- 查看 RAUC 状态:
rauc status
- 强制回滚(如果 U-Boot 环境支持):
fw_setenv BOOT_ORDER "A B"
reboot
6) RK3588S / Rockchip 特殊注意点(要点)
- Rockchip 平台通常使用 Rockchip 的 maskrom + loader (rkdeveloptool/rockusb) 做量产刷写或救砖;生产线或返修可以通过该方式 flash 整盘镜像。U-Boot 的 env 管理通常由 BSP(meta-rockchip)设置为存放在特定分区或“FAT boot partition”。集成时要确认你的 U-Boot 是否启用了 env 持久化与 bootcount 支持。(GitHub, lists.yoctoproject.org)
- RK 系列的 U-Boot 源在社区/厂商 repo 有多种变种,调试时注意使用与你 BSP 匹配的 U-Boot 版本。(GitLab)
7) 小结与落地建议(步骤化)
- 在开发板上先搭建基本系统(带 U-Boot 可交互)。
- 规划并在开发板上创建 A/B 分区(可用 parted + mkfs)。
- 在 build 主机上生成两个 rootfs(A/B)以及 boot 镜像。
- 集成 RAUC(或 Mender/SWUpdate),在开发板上安装 RAUC 并测试
rauc install
(用本地文件,不要先用网络)。(RAUC) - 配置 U-Boot 环境与 boot 脚本,确保
BOOT_ORDER
、BOOT_<slot>_LEFT
、以及持久化 env 工作正常。用fw_printenv/fw_setenv
验证。(RAUC, bootlin.com) - 实现 health-check 服务:新系统第一次启动时健康检查通过才写入“确认标记”。失败则 U-Boot 的 bootcount/left 会触发下一次尝试或回滚。
- 逐步把升级 Agent 放到设备上,先用局域网/HTTP 下载做 end-to-end 测试。
- 最后引入镜像签名(RAUC bundle 签名/验证)与可选 dm-verity。(RAUC)
参考(你实现时最有用的文档)
- RAUC 官方文档(bundle 格式、U-Boot 集成、创建 bundle 等)。(RAUC)
- RAUC 与 U-Boot 集成说明(如何使用
BOOT_ORDER
/BOOT_<slot>_LEFT
)。(RAUC) - 使用 U-Boot 实现 A/B 与 bootcount 的讨论(Bootlin 的讲稿、U-Boot 配置)。(bootlin.com, after hours coding)
- Rockchip / RK3588 U-Boot 源及注意点(社区 repo)。(GitHub, GitLab)
如果你愿意,我可以立刻继续并为你做其中一项完整交付(任选其一)——无需额外信息就能交付的选项有:
A) 完整的 RAUC 示例包(manifest + 打包脚本 + demo rootfs/boot 占位文件),你可以直接在主机上运行 rauc bundle
生成 .raucb
并在设备上 rauc install
测试。
B) U-Boot 引导脚本 + fw_env 配置示例(针对 RK3588S,给出 fw_env.config
、示例 boot.scr
,并可直接用于 mkimage
生成 boot.scr)。
C) 完整的 device-side 小服务套件:upgrade-agent.py
、health-check.sh
、systemd 单元文件、日志方案(可直接复制到目标系统并启用)。
你说一个字:A、B 或 C,我现在就把对应的完整文件和详细步骤给你(可以直接复制粘贴运行)。
这个问题问得非常好 👍,很多从 MCU(STM32 等裸机/RTOS) 转过来的人都会有类似的疑惑:
在 嵌入式 Linux 系统(比如 RK3588S 这种 SoC)里,升级对象不仅仅是 “APP”,而是多层次的东西。我们来对比一下你熟悉的 STM32 Bootloader+APP 模式,然后逐步拆解 Linux 的情况。
1. 在 STM32 上的升级
你以前的 STM32 模式:
- Bootloader:很小的引导程序,负责决定跳转到 App1 还是 App2,或者进行升级。
- App1/App2:真正运行的业务逻辑代码(比如采集传感器、串口通信)。
- 升级的核心就是 替换 App1/App2 区域的固件。
👉 在 MCU 世界,系统单一,没有复杂的分区和文件系统,APP == 你的业务代码。
2. 在 Linux 上的分层理解(以 RK3588S 为例)
Linux 系统通常由几个部分组成:
-
Bootloader (U-Boot)
- 类似 STM32 的 Bootloader
- 负责初始化 DDR、时钟、外设,并加载 Kernel 到内存。
- 一般存在于 eMMC/NAND/SD 卡的前几个分区。
-
Kernel (Linux 内核)
- 操作系统核心,提供驱动、进程管理、内存管理等能力。
- 就相当于 MCU 上的 底层 HAL/驱动+RTOS 内核,但要强大很多。
-
RootFS (根文件系统)
- 包含 /bin、/etc、/lib、/usr 等目录。
- 这里存放了系统服务、库文件、配置文件,还有你的应用程序(APP)。
- 举例:在 /usr/bin/ 或 /opt/app/ 下,可能放着你的业务程序(比如相机服务、控制服务)。
-
APP(用户态程序)
- 在 Linux 世界,“APP” 就是 运行在用户空间的应用程序。
- 它只是整个系统里的一部分(相当于 RootFS 里的一个文件)。
- 举例:你在终端输入
./my_camera_app
,这个就是你的业务 APP。
👉 所以:在 Linux 设备里,APP 并不是整个系统,而只是系统中的一层。
3. 升级对象有哪些?
在 Linux 设备中,升级并不一定只是 “APP 升级”,而是可能包括以下内容:
-
应用程序升级 (最常见)
- 就是替换 RootFS 里的某个二进制文件,例如更新
/opt/myapp/app.bin
。 - 类似于你 STM32 的 App 升级,但这里只升级用户态 APP。
- 就是替换 RootFS 里的某个二进制文件,例如更新
-
RootFS 升级
- 整个文件系统打包更新(比如
rootfs.img
)。 - 适合大版本更新:库文件、配置、APP 全部替换。
- 整个文件系统打包更新(比如
-
Kernel 升级
- 比如更新
kernel.img
,通常配合驱动变更(新硬件、Bug 修复)。
- 比如更新
-
Bootloader 升级
- 比较少改,但如果启动逻辑有问题,也可能升级。
-
全量固件升级 (system.img)
- 包含 Bootloader + Kernel + RootFS,一次性整体替换。
- 类似于刷机。
4. 升级方式
RK3588S(和大部分嵌入式 Linux)常见的升级方式有:
-
OTA 升级(Over-The-Air)
- 从服务器下载升级包,然后写入 eMMC/NAND 的对应分区。
- 可能是 APP、RootFS、甚至全量固件。
- 典型工具:mender、swupdate。
-
U 盘升级 / SD 卡升级
- 把升级包放在外部存储里,系统检测后写入。
-
USB 烧录工具
- 开发阶段常用,比如 Rockchip 提供的
rkdeveloptool
。 - 可以整机刷机(Bootloader+Kernel+RootFS)。
- 开发阶段常用,比如 Rockchip 提供的
-
A/B 分区冗余升级
- 类似手机,系统有 rootfsA 和 rootfsB 两个分区。
- 升级时写到未使用的分区,重启后切换。
- 如果失败,可以回滚。
5. 对比总结
层次 | STM32 | Linux (RK3588S) |
---|---|---|
Bootloader | 负责加载 APP | 负责加载 Kernel |
内核 | (没有,直接写寄存器) | Linux Kernel,驱动+调度 |
文件系统 | (没有 Flash 文件系统,可能裸数据) | RootFS (包含库、配置、APP) |
APP | 你的应用逻辑 | 用户空间程序(只是 RootFS 的一部分) |
升级对象 | App1/App2 固件 | APP / RootFS / Kernel / Bootloader / 全量固件 |
✅ 所以回答你的问题:
-
在 Linux 上,APP 只是系统的一部分,并不是升级的唯一对象。
-
升级时,可以只升级 APP(二进制文件),也可以升级 RootFS、Kernel,甚至全量固件。
-
具体取决于你们产品的需求:
- 如果只是修复业务逻辑 Bug → 升级 APP 就够了。
- 如果库、驱动也要更新 → 升级 RootFS 或 Kernel。
- 如果启动逻辑有问题 → 升级 Bootloader。
要不要我帮你画一个对比图(STM32 Bootloader+APP vs Linux U-Boot+Kernel+RootFS+APP),这样更直观?
太好了 👍 那我来给你捋清楚 RK3588S 这种嵌入式 Linux 系统里 “APP” 的概念,以及它和升级的关系。你之前做过 STM32 的 bootloader + app1/app2 升级,可以把这个经验类比一下,但要理解几个关键不同点。
1. Linux 系统的基本组成
在 RK3588S 这种 SoC 里,系统一般分为以下几个部分:
-
Bootloader (U-Boot)
- 负责最早启动(类似 STM32 的 bootloader)。
- 初始化 DDR、时钟、外设,然后加载 Kernel。
-
Kernel (Linux 内核)
- 驱动硬件(CPU、I2C、USB、Camera、Display、PCIe…)。
- 提供系统调用接口。
-
Rootfs (根文件系统)
- 存放 Linux 的用户态程序、库文件、配置、脚本。
- 类似于一个迷你版的 Ubuntu/Android 系统。
-
用户应用 (App)
- 运行在 rootfs 里的程序(比如你的设备主程序、守护进程、服务、GUI)。
- 这部分就是最终面向用户的“功能逻辑”。
- 可能是你写的
my_camera_app
,也可能是 Python 脚本、Qt GUI 程序、C++ 守护进程。
2. 那么 “升级” 升级的到底是啥?
升级不只是单纯的 “APP”,而是看你要更新 哪一层:
层级 | 对应 STM32 类比 | 是否可能单独升级 | 升级方式 |
---|---|---|---|
Bootloader (U-Boot) | STM32 自己写的 bootloader | 可以,但风险大 | 通常整包升级或 SD 卡刷机 |
Kernel | STM32 的低层驱动 | 可以单独升级 | 烧写 boot.img 或 Image |
Rootfs | STM32 没有对应,算是“大号 app1/app2 区” | 可以单独升级 | 更新 rootfs 分区 |
用户 App | STM32 app1/app2 | 最常见 | 直接替换可执行文件/脚本 |
3. 常见升级方式
在 Linux 设备里,升级一般有几种方式:
(1)整包升级
- 把 bootloader + kernel + rootfs + userdata 都打成一个固件包 (
update.img
)。 - 一次性烧录,保证系统完整性。
- 类似 STM32 一次烧掉 bootloader+app。
- 常用于出厂、重大版本更新。
(2)分区升级
- 每个部分都有独立分区:
uboot.img
、boot.img
(内核)、rootfs.img
。 - 可以只更新某一个,比如 rootfs。
- 比如 OTA 升级时,只下发 rootfs 镜像,节省流量。
(3)应用层升级(最常见)
-
在 rootfs 里,应用只是一个文件,比如
/usr/bin/my_app
。 -
直接下载新版本替换即可。
-
方式:
- scp / ftp / wget 下载覆盖
- OTA 服务推送
- 包管理工具(opkg / apt)
这跟你以前 STM32 app1/app2 类似,只不过:
- Linux 下 APP 是一个文件,不需要 MCU 那种 重定向向量表 的 bootloader。
- 系统本身(U-Boot/Kernel/rootfs)不会因为你换了 app 崩掉。
4. 原理对比(和 STM32 的差异)
对比项 | STM32 | RK3588S Linux |
---|---|---|
Bootloader | 你自己写的,负责跳转到 app | U-Boot,加载 Kernel |
App | 固定放在 Flash 某区(裸跑) | 文件系统里的 ELF 可执行文件 |
升级方式 | 重新烧写 Flash 的指定区域 | 文件替换 / 分区烧写 / OTA |
风险 | Bootloader 被覆盖可能导致板子“变砖” | 一般 Rootfs 有双分区/Recovery 机制,容错性更强 |
5. 举个例子
假设你做一款 RK3588S AI 相机:
- Bootloader:U-Boot(不变)
- Kernel:Linux + Camera 驱动(偶尔升级)
- Rootfs:Ubuntu base system + 依赖库(偶尔升级)
- App:你写的
camera_service
(经常升级)
升级场景:
- 发现算法有 bug → 只替换
/usr/bin/camera_service
文件。 - 内核驱动需要更新 → 升级
boot.img
。 - 重大系统更新 → OTA 下发完整
update.img
,相当于重刷系统。
兄弟,这样解释清楚没?要不要我再给你画一个 STM32 升级 vs RK3588 升级的对比流程图,让你一下子就看懂?
太好了,我给你画一个对比流程图,用文字图的方式,让你一眼就能看懂 STM32 升级流程 vs RK3588 Linux 升级流程。
1️⃣ STM32 升级流程(Bootloader + App1/App2)
+------------------+
| Bootloader |
| (Flash 启动区) |
+------------------+|v
+------------------+
| App1 | <-- 运行区
+------------------+
| App2 | <-- 备用升级区
+------------------+升级步骤:
1. Bootloader 检测升级请求(UART/USB/SD)
2. 将新 App 写入 App2
3. Bootloader 切换跳转到 App2
4. 成功后覆盖 App1 或保留双版本
特点:
- Bootloader 很小,直接操作 Flash
- App1/App2 固定区域
- 升级只是替换 App 区
2️⃣ RK3588 Linux 升级流程(U-Boot + Kernel + RootFS + APP)
+------------------+
| U-Boot | <-- Bootloader
+------------------+|v
+------------------+
| Kernel | <-- Linux 内核
+------------------+|v
+------------------+
| RootFS | <-- 根文件系统 (只读/只更新)
| /usr/bin/my_app | <-- 用户态应用 (APP)
+------------------+|v
+------------------+
| 数据区 /data | <-- 用户数据,读写
+------------------+
升级对象:
- APP:替换
/usr/bin/my_app
(最轻量) - RootFS:替换整个文件系统(包含 APP、库、配置)
- Kernel:更新 Linux 内核
- Bootloader:U-Boot(少用,高风险)
- 整机镜像:Bootloader + Kernel + RootFS + 数据区
升级方式:
- 单文件替换:只替换 APP 文件
- 分区升级:更新 RootFS / Kernel
- A/B 分区 OTA:写入备用分区,启动失败可回滚
- 全量刷机:类似量产或救砖
3️⃣ 对比总结
特性 | STM32 | RK3588 Linux |
---|---|---|
Bootloader | 小型,直接跳 App | U-Boot,加载 Kernel |
升级对象 | App1/App2 | APP / RootFS / Kernel / Bootloader |
升级方式 | Flash 覆盖 | 文件替换、分区烧写、OTA、全量刷机 |
容错性 | 较低,Bootloader 被破坏可能砖板 | 高,可用 A/B 分区和 recovery 回滚 |
APP 概念 | 直接裸机二进制 | Linux 用户态可执行程序,位于 RootFS |
💡 小结:
- 在 STM32,升级就是替换 App 区。
- 在 Linux,APP 只是 RootFS 的一部分,升级可能只替换它,也可能升级整个系统。
- Linux 系统的升级更复杂,但也更安全、更灵活。
如果你愿意,我可以帮你画一个 RK3588 OTA 升级完整流程图(从下载 -> 安装 -> 回滚 -> 确认成功),让你完全理解 A/B OTA 的逻辑,比 STM32 的升级逻辑清晰得多。
你想让我画吗?
好嘞,我给你画一个 RK3588 嵌入式 Linux OTA 升级完整流程图,用文字流程图的形式展示整个升级过程,包括下载、安装、回滚和确认成功。
RK3588 OTA 升级流程(A/B 分区 + APP/RootFS)
[1] 升级触发||-- OTA 服务器推送 / 用户触发下载v
[2] 下载升级包- 下载 .raucb 或 rootfs/app 镜像到临时目录 (/data/update)- 可断点续传 / 校验签名 / 校验哈希|v
[3] 校验升级包- 验证签名是否可信- 验证完整性(sha256 / crc)|v
[4] 安装到备用分区 (B)- 根据 manifest 写入 boot_b / rootfs_b 或替换 APP 文件- 安装过程中,保持当前系统 (A) 运行|v
[5] 更新 U-Boot 环境- 设置 BOOT_ORDER="B A"- 设置 BOOT_B_LEFT=3 (尝试次数)|v
[6] 重启系统 -> 启动到新分区 (B)|v
[7] 健康检查- systemd health-check 服务或守护进程- 检查关键服务、硬件、网络是否正常|v
[8] 检查结果|-- 成功 -> 标记新系统有效| - BOOT_B_LEFT 清零| - rootfs/app 已正式生效||-- 失败 -> 回滚机制触发- BOOT_ORDER 切换回 "A B"- 再次启动到旧系统 (A)- 保证设备不砖|v
[9] 完成升级- 新系统 / APP 正常运行- 旧分区仍可回滚(可选清理)
核心特点
-
A/B 分区
- 保证升级失败时可以回滚到旧系统
- 提高设备可靠性
-
升级包安全
- RAUC bundle 带签名
- 校验完整性 → 防止下载错误/恶意篡改
-
健康检查机制
- 升级后第一次启动由系统检测成功与否
- 不通过则自动回滚
-
多层升级支持
- 可以只升级 APP
- 可以升级整个 RootFS 或 Kernel
- 可以升级 Bootloader(小心!高风险)
💡 总结:
- STM32 的升级逻辑是单层的:Bootloader + App
- RK3588 的 Linux 系统升级是 多层次、可回滚、安全可靠 的
- APP 只是 RootFS 里的一部分,Linux 可以选择只更新 APP,也可以更新整个系统
如果你需要,我可以帮你画一个 图解版的 RK3588 系统升级结构图,把 Bootloader / Kernel / RootFS / APP / OTA 流程 放到同一张图里,让你更直观理解每层作用和升级路径。
你想让我画吗?
太好了,我给你画一个RK3588 嵌入式 Linux 系统升级结构图,把 Bootloader / Kernel / RootFS / APP / OTA 流程 都放在同一张图里,用文字图展示:
RK3588 嵌入式 Linux 系统升级结构图
+---------------------------------------------------+
| Flash / eMMC / NAND |
+------------------+----------------+---------------+
| Bootloader | Kernel | RootFS |
| (U-Boot) | (vmlinuz / | /bin / /usr |
| | Image / dtb)| /lib / APP |
+------------------+----------------+---------------+| | |v v v
+------------------+ +----------------+ +----------------+
| Bootloader logic | | Kernel loads | | 用户应用 APP |
| 初始化硬件、DDR | | 驱动设备 | | my_camera_app |
| 决定启动分区 A/B | | 启动 RootFS | | 服务/脚本/守护 |
+------------------+ +----------------+ +----------------+OTA 升级流程 / A-B 分区逻辑--------------------------------|v[下载升级包] (APP/RootFS/Kernel)|v[验证签名 + 校验完整性]|v[安装到备用分区 B]|v[更新 U-Boot 环境 BOOT_ORDER / BOOT_B_LEFT]|v[重启系统 -> 启动 B]|v[健康检查服务运行]|+---------+---------+| |成功 失败| |[标记 B 为有效] [回滚到 A 分区]|v系统正常运行
图解说明
-
Bootloader (U-Boot)
- 控制启动顺序 A/B
- 初始化硬件
- 决定哪个 Kernel + RootFS 启动
-
Kernel
- 提供操作系统核心功能
- 加载驱动、调度进程
-
RootFS
- 包含系统服务、库文件、用户应用
- 可以只升级 APP 或整个 RootFS
-
APP(用户态应用)
- 位于 RootFS
- 可独立升级,不影响系统稳定性
-
OTA / A-B 分区
- 升级包下载到设备
- 安装到备用分区
- 健康检查通过才切换分区
- 失败则自动回滚
💡 总结:
- APP 升级只是 Linux 系统升级的最轻量形式
- Linux 系统升级更安全、灵活,可升级多层次
- A/B 分区 + 健康检查 + 回滚机制,防止设备变砖
如果你愿意,我可以帮你再画一个和 STM32 对比版的图,把 STM32 Bootloader+App 和 Linux Bootloader+Kernel+RootFS+APP 升级流程放在一起,直观对比两者差异。
你想让我画吗?
好,我帮你画一个 STM32 升级 vs RK3588 Linux 升级对比图,让你一眼就看懂两者差异。用文字图展示:
STM32 vs RK3588 升级流程对比
STM32 MCU RK3588 嵌入式 Linux
+----------------+ +-------------------------------+
| Bootloader | | U-Boot |
| (Flash 启动区) | | 初始化硬件 / DDR / 启动分区 |
+----------------+ +-------------------------------+| |v v
+----------------+ +-------------------------------+
| App1 | <--- 运行区 | Kernel |
| App2 | | Linux 内核,加载驱动/调度 |
+----------------+ +-------------------------------+| |v v升级替换 App1/App2 +-------------------------------+(Flash 覆盖,Bootloader 跳转) | RootFS || /bin / /usr /lib /APP/脚本 |+-------------------------------+|v用户态应用 APP(my_camera_app / 服务 / 守护进程)|v升级方式:- 单文件替换(APP)- RootFS 分区升级- Kernel 升级- 全量刷机(Bootloader+Kernel+RootFS)|vOTA / A-B 分区逻辑- 下载升级包- 安装到备用分区 B- 更新 U-Boot 启动顺序- 重启 -> 健康检查- 成功标记有效 / 失败回滚到旧分区
对比总结
特性 | STM32 | RK3588 Linux |
---|---|---|
Bootloader | 小型,直接跳 App | U-Boot,加载 Kernel,支持 A/B |
App 概念 | 固件,直接 Flash 区域 | 用户态程序,位于 RootFS,可独立升级 |
升级方式 | Flash 覆盖 | 文件替换 / 分区升级 / OTA / 全量刷机 |
容错性 | 较低,Bootloader 被破坏可能砖板 | 高,A/B 分区 + 回滚机制,防止变砖 |
升级风险 | 高,单步失败可能无法启动 | 低,系统可回滚且支持健康检查 |
💡 关键点理解:
- STM32 升级逻辑单层,Bootloader + App1/App2
- Linux 升级逻辑多层,Bootloader + Kernel + RootFS + APP + OTA
- APP 在 Linux 中只是 RootFS 里的一部分,可以单独升级
- Linux 的 A/B 分区 + 健康检查机制,是 MCU 升级所不具备的安全保障
我可以帮你再画一个直观流程图版,用彩色块和箭头把 STM32 和 RK3588 升级流程对比可视化,让你更形象地理解每层和升级路径。
你想让我画吗?