DFU (Device Firmware Upgrade) 和 MCUboot 是 Nordic 设备固件升级的核心技术。
MCUboot 是一个开源的、安全的引导加载程序,专为 32-bit 微控制器设计。
核心功能:
设备上电 → NSIB (第一级引导) → MCUboot (第二级引导) → 应用程序
┌─────────────────────────────────┐
│ 0x0: mcuboot (引导程序) │
├─────────────────────────────────┤
│ Primary Slot (当前运行的固件) │
│ - mcuboot_pad │
│ - app (应用程序) │
├─────────────────────────────────┤
│ Secondary Slot (新固件暂存) │
└─────────────────────────────────┘
| 分区 | 用途 |
|---|---|
| mcuboot | 引导加载程序代码 |
| mcuboot_primary | 主槽 - 运行中的应用 |
| mcuboot_secondary | 副槽 - 新固件下载区 |
| mcuboot_pad | 镜像头/签名区 |
1. 新固件写入 Secondary Slot
2. MCUboot 验证镜像签名
3. 重启时交换 Primary/Secondary
4. 运行新固件
| 方式 | 协议 | 适用场景 |
|---|---|---|
| UART | SMP over Serial | 有线调试 |
| USB | SMP over USB CDC | 有线调试 |
| BLE | SMP over Bluetooth LE | OTA 升级 |
| LTE/WiFi | HTTP/HTTPS | IoT 云升级 |
// 初始化 DFU 目标
int dfu_target_init(int img_type, int img_num, size_t file_size);
// 获取已下载偏移
int dfu_target_offset_get(size_t *offset);
// 写入固件块
int dfu_target_write(const void *buf, size_t len);
// 完成下载
int dfu_target_done(bool successful);
// 调度更新
int dfu_target_schedule_update(int img_num);
// 1. 初始化
dfu_target_init(img_type, 0, file_size);
// 2. 分块写入
while (data_remaining) {
dfu_target_write(chunk, chunk_size);
}
// 3. 完成下载
dfu_target_done(true);
// 4. 标记更新
dfu_target_schedule_update(0);
// 5. 重启设备
sys_reboot(SYS_REBOOT_COLD);
# 启用 MCUboot
CONFIG_BOOTLOADER_MCUBOOT=y
# 启用 DFU Target
CONFIG_DFU_TARGET=y
# 启用 MCUMgr (SMP 协议)
CONFIG_MCUMGR=y
CONFIG_MCUMGR_TRANSPORT_BT=y
# 启用设置存储(断电恢复)
CONFIG_SETTINGS=y
CONFIG_DFU_TARGET_STREAM_SAVE_PROGRESS=y
# 生成签名密钥
imgtool keygen -k sign.key -t rsa-2048
# 签名固件
imgtool sign --key sign.key --header-size 0x200 \
--align 8 --version 1.0.0 --slot-size 0x7a000 \
app.bin app_signed.bin
# 通过 UART 升级
nrfutil dfu serial -pkg app.zip -p /dev/ttyACM0
# 通过 BLE 升级
nrfutil dfu ble -pkg app.zip -d <device_addr>
# 列出连接的设备
mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200"
# 查询镜像信息
mcumgr -c acm0 image list
# 上传固件
mcumgr -c acm0 image upload app.bin
# 标记镜像为待启动
mcumgr -c acm0 image test <hash>
# 重启设备
mcumgr -c acm0 reset
nRF54L/nRF5340 等多核芯片支持同时更新多个镜像:
// 更新应用核
dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, 0, app_size);
// ... 写入应用镜像 ...
// 更新网络核
dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, 1, net_size);
// ... 写入网络镜像 ...
// 一次性调度所有更新
dfu_target_schedule_update(-1); // -1 = 所有镜像
# 启用硬件单调计数器
CONFIG_BOOT_HW_ROLLBACK_PROT=y
# 启用镜像加密
CONFIG_BOOT_ENCRYPT_RSA=y
# 或
CONFIG_BOOT_ENCRYPT_EC256=y
CONFIG_BOOT_SERIAL_LOG_LEVEL_DBG=y
CONFIG_MCUBOOT_LOG_LEVEL_DBG=y
west build -t partition_manager_report
| 错误 | 原因 | 解决 |
|---|---|---|
BOOT_MAX_IMG_SECTORS too small | 扇区数不足 | 增加 CONFIG_BOOT_MAX_IMG_SECTORS |
Cannot upgrade: not a compatible | 外部 Flash 驱动未启用 | 检查 QSPI 驱动配置 |
Signature verification failed | 签名密钥不匹配 | 检查签名密钥配置 |
位置:zephyr/samples/subsys/mgmt/mcumgr/smp_svr
功能:
# nRF52840 DK
west build -b nrf52840dk/nrf52840 samples/subsys/mgmt/mcumgr/smp_svr
# nRF54L15 DK
west build -b nrf54l15dk/nrf54l15/cpuapp samples/subsys/mgmt/mcumgr/smp_svr
*小白 🤖 - 2026-03-18*