扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

RT1170 USB DFU 固件更新:免编程器的现场升级方案

1小时前
85
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

嵌入式产品的全生命周期中,现场固件升级是核心功能需求,NXP i.MX RT1170 凭借内置 USB 设备控制器,可通过USB DFU(Device Firmware Upgrade) 实现免外部编程器的固件更新,仅需 PC 与 USB 线缆即可完成,适配产线烧录、现场维护等多种场景。本文基于 MCUXpresso IDE 与 RT1170 SDK,详解 DFU 环境搭建、dfu-util 工具定制、自定义固件编译与升级全流程,解决 CRC 校验、地址偏移等核心问题,实现稳定的固件更新。

资料获取:[RT1170] 如何通过USB DFU更新Firmware

1. USB DFU 核心原理与环境准备

1.1 DFU 升级核心逻辑

RT1170 的 USB DFU 升级基于DFU 引导程序 + dfu-util 主机工具的协同工作,核心流程为:
  1. 烧录 DFU Demo 工程到 RT1170,设备上电后枚举为 USB DFU 设备,等待主机连接;
  2. 主机通过定制化 dfu-util 工具,将待升级固件(bin 格式)添加 CRC32 校验后,通过 USB 传输至 RT1170;
  3. RT1170 的 DFU 程序将固件加载到指定 RAM 地址,校验固件末尾的 CRC32 值,确保无数据错误;
  4. 校验通过后,DFU 程序跳转到固件入口地址,运行新固件;校验失败则提示错误,不执行升级。

1.2 关键特性与注意事项

  • CRC32 强制校验:SDK 自带的 DFU Demo 会严格检查固件最后 4 个字节的 CRC32 值,无校验或校验错误将拒绝运行;
  • RAM 加载运行:DFU 升级的固件先加载到指定 RAM 地址(默认 0x10000),而非直接烧录到 Flash,需保证固件地址与 DFU 程序配置匹配;
  • 免拆机升级:仅需 USB 物理连接,无需 JLink/ST-Link 等调试器,适配现场无专业工具的场景。

1.3 软硬件环境准备

(1)软件环境

  • 开发 IDE:MCUXpresso IDE(任意兼容版本);
  • 固件源码:RT1170 SDK 2.15.000(含dev_dfu_freertos_cm7 DFU Demo 工程);
  • 主机工具:dfu-util(需定制修改源码,添加 CRC32 功能)、libusb(dfu-util 依赖库);
  • 辅助工具:串口调试工具(Tera Term/SSCOM)、USB 驱动(系统自动识别 DFU 设备)。

(2)硬件环境

  • 主控板:RT1170-EVKB 开发板
  • 配件:USB Type-C 线缆 2 根(一根用于串口调试,一根用于 DFU 数据传输)、5V 电源

(3)核心工具下载地址

  • RT1170 SDK:NXP 官网下载SDK_2_15_000_MIMXRT1170-EVK
  • dfu-util 源码:git://git.code.sf.net/p/dfu-util/dfu-util
  • libusb 源码:https://github.com/libusb/libusb.git
  • 官方预编译 dfu-util(win64):dfu-util-0.9-win64.zip(仅作参考,需自行编译定制版)。

2. 定制化 dfu-util 工具编译(添加 CRC32 功能)

官方原生 dfu-util 工具不支持为固件添加 CRC32 校验,而 RT1170 的 DFU Demo 强制校验该值,因此需修改 dfu-util 源码并重新编译,实现固件末尾自动追加 4 字节 CRC32。以下为 Ubuntu 交叉编译 Windows 版 dfu-util 的步骤(Windows 本地编译亦可,核心为源码修改)。

步骤 1:安装编译依赖

# 安装libusb与dfu-util编译依赖
sudo apt-get build-dep libusb-1.0-0 dfu-util
# 安装Windows交叉编译工具链
sudo apt-get install gcc-mingw-w64-x86-64

步骤 2:拉取源码

# 克隆dfu-util与libusb源码
git clone git://git.code.sf.net/p/dfu-util/dfu-util
git clone https://github.com/libusb/libusb.git

步骤 3:核心修改(添加 CRC32 写入逻辑)

编辑 dfu-util 源码中的dfu_file.c,修改dfu_store_file函数的后缀写入逻辑,将 CRC32 值追加到固件末尾(4 字节):
/* write suffix, if any */
if (write_suffix) {
    uint8_t dfusuffix[DFU_SUFFIX_LENGTH];
    dfusuffix[0] = file->bcdDevice & 0xff;
    dfusuffix[1] = file->bcdDevice >> 8;
    dfusuffix[2] = file->idProduct & 0xff;
    dfusuffix[3] = file->idProduct >> 8;
    dfusuffix[4] = file->idVendor & 0xff;
    dfusuffix[5] = file->idVendor >> 8;
    dfusuffix[6] = file->bcdDFU & 0xff;
    dfusuffix[7] = file->bcdDFU >> 8;
    dfusuffix[8] = 'U';
    dfusuffix[9] = 'F';
    dfusuffix[10] = 'D';
    dfusuffix[11] = DFU_SUFFIX_LENGTH;
    // 注释原CRC计算行,新增CRC32写入固件末尾
    // crc = dfu_file_write_crc(f, crc, dfusuffix, DFU_SUFFIX_LENGTH - 4);
    dfusuffix[12] = crc;
    dfusuffix[13] = crc >> 8;
    dfusuffix[14] = crc >> 16;
    dfusuffix[15] = crc >> 24;
    crc = dfu_file_write_crc(f, crc, dfusuffix + 12, 4);
}

步骤 4:编译 libusb 库

# 创建统一编译目录
mkdir -p build
cd libusb
# 生成配置文件
./autogen.sh
# 配置交叉编译(目标Windows x64)
PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig 
./configure --host=x86_64-w64-mingw32 --prefix=$PWD/../build
# 编译并安装
make && make install
cd ..

步骤 5:编译定制版 dfu-util

cd dfu-util
# 生成配置文件
./autogen.sh
# 配置交叉编译,依赖已编译的libusb
PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig 
./configure --host=x86_64-w64-mingw32 --prefix=$PWD/../build
# 编译并安装
make && make install
cd ..

步骤 6:获取编译产物

编译完成后,在build/bin目录下得到 Windows 版工具集,核心文件为:
  • dfu-util.exe:主升级工具;
  • dfu-suffix.exe:固件 CRC32 添加工具;
  • libusb-1.0.dll:依赖库(需与工具放在同一目录)。

步骤 7:为固件添加 CRC32

将编译好的工具拷贝到 Windows 主机,在 CMD 中执行以下命令,为固件(bin 格式)追加 CRC32 校验:
# 格式:dfu-suffix.exe -a 固件文件名.bin
dfu-suffix.exe -a hello_world_dfu.bin
# 成功提示:Suffix successfully added to file
执行后,固件末尾将自动添加 4 字节 CRC32 值,满足 RT1170 DFU Demo 的校验要求。

3. 烧录 DFU Demo 工程,让 RT1170 枚举为 DFU 设备

DFU Demo 工程是 RT1170 实现 DFU 功能的核心,烧录后设备将作为 USB DFU 从设备,等待主机发送升级固件。

步骤 1:导入 DFU Demo 工程

  1. 打开 MCUXpresso IDE,点击「Import SDK Examples」;
  2. 选择 RT1170-EVK 开发板,找到usb分类下的dev_dfu_freertos_cm7工程,导入 IDE。

步骤 2:编译并烧录工程

  1. 连接 RT1170-EVKB 与 JLink 调试器,将开发板设置为调试模式;
  2. 编译 DFU Demo 工程,无错误后点击「Debug」烧录到开发板;
  3. 烧录完成后重启开发板,通过 USB 线缆连接开发板与 PC。

步骤 3:验证 DFU 设备枚举

  1. 打开 Windows「设备管理器」,在「Universal Serial Bus devices」下看到DFU DEVICE,表示枚举成功;
  2. 打开串口调试工具,配置波特率(与 Demo 一致,默认 115200),可看到串口输出:USB device dfu demo,表示 DFU 程序正常运行。

步骤 4:获取 DFU 设备的 VID/PID

VID(厂商 ID)和 PID(产品 ID)是 dfu-util 工具识别设备的关键,可通过两种方式获取:
  1. 设备管理器:右键 DFU 设备→「属性」→「详细信息」→「硬件 ID」,格式为USBVID_xxxx&PID_xxxx
  2. 工程源码:打开 DFU Demo 的usb_device_descriptor.h,查看宏定义:
    #define USB_DEVICE_VENDOR_ID     0x15A2  // 示例VID
    #define USB_DEVICE_PRODUCT_ID    0x0073  // 示例PID
    
记录该 VID/PID,后续升级时需指定。

4. 使用官方固件测试 DFU 升级(快速验证)

RT1170 SDK 中提供了已添加 CRC32 的测试固件dev_hid_mouse_bm.bin),可直接用于测试 DFU 升级,无需手动添加 CRC32,快速验证环境是否正常。

步骤 1:执行升级命令

在 Windows CMD 中,进入定制化 dfu-util 工具目录,执行以下升级命令:
# 格式:dfu-util.exe -d VID:PID -D 固件文件名.bin
dfu-util.exe -d 15A2:0073 -D dev_hid_mouse_bm.bin

步骤 2:验证升级结果

  1. 升级过程中,工具会显示进度条,提示数据传输中;
  2. 串口调试工具将输出:crc check ok,表示 CRC 校验通过;
  3. 校验通过后,RT1170 将运行新固件,设备被枚举为USB 鼠标设备,在电脑屏幕上实现鼠标矩形旋转移动,说明 DFU 升级成功。

5. 编译自定义固件,实现个性化 DFU 升级

实际开发中需升级自研固件,直接编译的固件会因地址偏移不匹配「CRC 校验通过但无法运行」,核心原因是 DFU Demo 要求固件加载到0x10000 RAM 地址,需对自研固件的编译配置进行针对性修改。以下以hello_world_cm7工程为例,详解自定义固件的编译配置步骤。

步骤 1:导入并配置自研工程

  1. 在 MCUXpresso IDE 中导入hello_world_cm7工程(或自研工程);
  2. 右键工程→「Properties」→「C/C++ Build」→「Settings」→「MCU Linker」→「Managed Linker Script」;
  3. 勾选Link application to RAM,将固件编译为 RAM 运行模式(DFU 升级的固件需加载到 RAM 运行)。

步骤 2:修改内存配置,匹配 DFU 地址要求

  1. 在工程属性中,进入「MCU Settings」→「Memory details」;
  2. 找到SRAM_ITC(指令 TCM),将其移动到 Flash 下方作为第一个 RAM 区域;
  3. 修改 SRAM_ITC 的起始地址大小,使其与 DFU Demo 规定的0x10000加载地址匹配(具体参数参考 DFU Demo 的内存配置);
  4. 点击「Apply」保存配置,确保固件编译后入口地址为 DFU 指定的 RAM 地址。

步骤 3:编译工程并生成 bin 格式固件

  1. 编译自研工程,确保无编译错误;
  2. 右键工程→「Binary Utilities」→「Create binary」,生成 bin 格式固件(如hello_world_dfu.bin);
  3. 生成的 bin 文件位于工程的Debug/Binaries目录下。

步骤 4:为自定义固件添加 CRC32 并升级

  1. 使用定制化的dfu-suffix.exe为 bin 固件添加 CRC32:
    dfu-suffix.exe -a hello_world_dfu.bin
    
  2. 执行 DFU 升级命令,指定 VID/PID 和自定义固件:
    dfu-util.exe -d 15A2:0073 -D hello_world_dfu.bin
    
  3. 验证升级结果:串口输出crc check ok,随后显示hello world dfu.,表示自定义固件成功运行。

6. 常见问题排查与避坑指南

6.1 CRC 校验错误(crc check error)

  • 原因 1:固件未添加 CRC32,或使用原生 dfu-util 工具添加;
  • 原因 2:修改 dfu-util 源码时逻辑错误,CRC32 写入位置不对;
  • 解决:使用定制化dfu-suffix.exe重新添加 CRC32,检查源码修改是否与本文一致,对比添加 CRC 前后的固件大小(相差 4 字节为正常)。

6.2 CRC 校验通过但固件无法运行

  • 核心原因:固件编译的RAM 加载地址与 DFU Demo 规定的 0x10000 不匹配,DFU 程序无法找到固件入口;
  • 解决:严格按照本文步骤修改工程的内存配置,勾选「Link application to RAM」,确保 SRAM_ITC 地址与 DFU Demo 一致。

6.3 升级时提示「LIBUSB_ERROR_PIPE」

  • 原因 1:USB 线缆接触不良,或使用非数据传输线(仅充电线);
  • 原因 2:DFU 设备枚举异常,未正确识别;
  • 解决:更换优质 USB 数据线缆,重新插拔开发板,在设备管理器中确认 DFU 设备正常识别(无黄色感叹号)。

6.4 设备管理器中无 DFU 设备

  • 原因 1:DFU Demo 工程未成功烧录,或开发板启动模式错误;
  • 原因 2:USB 驱动未正常安装;
  • 解决:重新烧录 DFU Demo 工程,确认开发板为正常启动模式,重启 PC 或开发板重新枚举设备。

6.5 dfu-util 编译失败

  • 原因 1:Ubuntu 编译依赖未安装完整,或交叉编译工具链缺失;
  • 原因 2:源码拉取不完整,或修改源码时语法错误;
  • 解决:重新安装所有依赖,拉取完整源码,检查dfu_file.c的修改部分是否有语法错误(如少分号、括号不匹配)。

7. 进阶优化与实际应用建议

7.1 实现 Flash 烧录升级

本文中 DFU 固件为RAM 运行模式,掉电后丢失,实际产品中需修改 DFU Demo,增加固件从 RAM 烧录到外部 Flash的逻辑,实现掉电保存的永久升级(核心为添加 Flash 擦写驱动,将 RAM 中的固件写入 FlexSPI NOR Flash)。

7.2 增加固件版本校验

在固件中添加版本号字段,DFU Demo 升级前先校验待升级固件版本,避免低版本覆盖高版本,或重复升级同一版本。

7.3 增加升级进度反馈

在 DFU Demo 中添加 USB 数据传输进度反馈,通过串口或 USB HID 将升级进度(如百分比)发送到主机,提升用户体验。

7.4 适配量产场景

  • 批量升级:基于 dfu-util 开发批量升级脚本,实现多设备同时 DFU 升级,提升产线效率;
  • 安全升级:结合 RT1170 的 HAB 安全启动,为 DFU 固件添加数字签名,防止非授权固件升级,提升设备安全性。
RT1170 的 USB DFU 固件更新方案核心是定制化 dfu-util 工具 + DFU Demo 工程 + 固件地址匹配,通过修改 dfu-util 源码实现 CRC32 自动添加,解决 DFU 强制校验问题;通过调整自研固件的编译配置,匹配 DFU 指定的 RAM 加载地址,解决「校验通过但无法运行」的核心痛点。
该方案无需外部编程器,仅需 USB 线缆即可完成固件升级,适配现场维护、产线批量烧录等场景,且基于官方 SDK 开发,兼容性强、稳定性高。实际产品开发中,可在此基础上增加 Flash 烧录、版本校验、安全签名等功能,实现更贴合量产需求的 DFU 升级方案。

相关推荐