ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

esp-iot-solution 之 esp_tinyuf2:USB 虚拟盘 UF2 固件烧录与 NVS INI 配置的完整实践指南

esp-iot-solution 之 esp_tinyuf2:USB 虚拟盘 UF2 固件烧录与 NVS INI 配置的完整实践指南 esp-iot-solution 之 esp_tinyuf2USB 虚拟盘 UF2 固件烧录与 NVS INI 配置的完整实践指南【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution本文基于 esp-iot-solution 仓库中的 esp_tinyuf2 组件文档 展开系统讲解esp_tinyuf2组件的工作原理、API 与全部 Kconfig 配置参数并结合usb_uf2_ota、usb_uf2_nvs、bootloader_uf2三个官方示例说明如何仅通过“把 USB 设备插到电脑上、拖拽一个 UF2 文件”的方式完成 ESP32-S2/S3/P4 设备的固件升级与 NVS 参数配置。读完本文后你将能够在自己的项目中集成该组件理解虚拟磁盘背后的 UF2 文件格式并知道如何生成.uf2升级文件。一、esp_tinyuf2 是什么esp_tinyuf2是 Adafruit TinyUF2 方案在乐鑫带 USB-OTG 芯片上的增强实现当前版本 1.1.1见 idf_component.yml。它把设备通过 USB 枚举为一个MSC 大容量存储设备虚拟 U 盘主机侧无需安装任何驱动即可看到一块磁盘从而支持三大能力源自组件 README 与 esp_tinyuf2.h通过虚拟 USB 盘进行 OTA 升级主机把.uf2文件拖入磁盘设备解析后写入指定的 OTA 应用分区把 NVS 键值对导出为 ini 文件磁盘中的CONFIG.ini反映设备 NVS 指定命名空间中的数据修改 ini 文件写回 NVS主机修改并保存CONFIG.ini设备自动解析并把新的键值对写回 NVS——这使得“免 Wi-Fi 配网”成为可能。组件声明支持的目标芯片为esp32s2、esp32s3、esp32p4依赖 ESP-IDF4.4、cmake_utilities、leeebo/esp-inih与leeebo/tinyusb_src0.16.0~6版本这些依赖关系可在 idf_component.yml 中直接确认。从版本历史CHANGELOG.md看v1.1.0 增加了 Bootloader UF2 模式与 ESP32-P4 支持v1.1.1 修复了重复安装 USB PHY 导致的崩溃重启问题——这对应源码中安装/卸载时对usb_phy的反复创建与释放逻辑。二、虚拟磁盘背后的 UF2 格式要理解拖拽升级为什么可行需要先看 UF2 文件本体。在 private_include/uf2.h 中定义了标准的 512 字节 UF2 块结构typedef struct { // 32 byte header uint32_t magicStart0; // 0x0A324F55 (UF2\n) uint32_t magicStart1; // 0x9E5D5157 uint32_t flags; uint32_t targetAddr; // 该块要写入的 flash 目标地址 uint32_t payloadSize; uint32_t blockNo; uint32_t numBlocks; uint32_t familyID; uint8_t data[476]; // 实际负载 uint32_t magicEnd; // 尾部魔数限制部分块读造成的损坏 } UF2_Block;关键设计均出自 uf2.h 中的注释与宏块自描述地址每个块头部携带targetAddr主机只是把块按顺序拷进磁盘设备端依据块头把数据写到正确的 flash 偏移主机无需了解设备分区布局CFG_UF2_FLASH_SIZE默认 4MB与 Kconfig 中UF2_FLASH_SIZE_MB默认 4对应注释明确说明“4MB 尺寸约需 2kB RAM见 MAX_BLOCKS”即设备端用一个位图writtenMask跟踪 256 字节粒度的写入进度固件大小上限受 RAM 制约写入状态机WriteState记录numBlocks/numWritten/writtenMask当所有块到齐后触发烧录完成流程complete_cb。在实现层面组件的 CMakeLists.txt 显示虚拟盘由三块拼成TinyUSB 的msc_device.cMSC 类协议栈、msc/msc.c磁盘后端与 uf2/ghostfat.c无 FAT 文件系统的极简 FAT 实现即“ghost FAT”而 UF2 块的解析与 NVS ini 的生成落在 uf2/board_flash.c 中。三、核心 API 与组件内部机制3.1 两个配置结构与默认值esp_tinyuf2.h 提供了一组默认配置宏#define DEFAULT_TINYUF2_OTA_CONFIG() \ { \ .subtype ESP_PARTITION_SUBTYPE_ANY, \ .label NULL, \ .if_restart true \ } #define DEFAULT_TINYUF2_NVS_CONFIG() \ { \ .part_name nvs, \ .namespace_name tuf2, \ }两个结构体的完整字段见 esp_tinyuf2.h结构体字段含义tinyuf2_ota_config_tsubtype目标分区子类型ESP_PARTITION_SUBTYPE_ANY时使用“下一个待更新分区”label指定分区标签仅在明确查找某分区时设置if_restartUF2 刷写完成后是否自动重启进入新应用分区complete_cb升级完成后的用户回调tinyuf2_nvs_config_tpart_nameNVS 分区名默认nvsnamespace_name命名空间名默认tuf2modified_cbCONFIG.ini被修改并写回 NVS 后的回调3.2 安装、卸载与状态机组件对外只有四个主要 APIesp_tinyuf2.hesp_tinyuf2_install(ota_config, nvs_config)两者至少传一个非空参数决定启用哪类功能esp_tinyuf2_uninstall()恢复 USB 到默认状态esp_tinyuf2_current_state()返回TINYUF2_STATE_NOT_INSTALLED / INSTALLED / MOUNTED三态esp_restart_from_tinyuf2()先调用esp_reset_reason_set_hint(UF2_RESET_REASON_VALUE)再esp_restart()UF2_RESET_REASON_VALUE即 Kconfig 项UF2_OTA_RESET_REASON_VALUE默认0xF2应用重启后可据此识别“这次重启来自 UF2 升级”。阅读 esp_tinyuf2.c 的esp_tinyuf2_install可以看到参数校验逻辑未开启CONFIG_UF2_OTA_FACTORY_ONLY时subtype必须落在ESP_PARTITION_SUBTYPE_APP_OTA_MIN..APP_OTA_MAX区间内或为ANY开启该选项后则只允许ESP_PARTITION_SUBTYPE_APP_FACTORY。校验通过后依次调用board_flash_init()OTA 路径、board_flash_nvs_init()NVS ini 路径、uf2_init()和tinyusb_init()最后置状态为INSTALLED并唤醒 USB 任务。几个值得注意的源码级细节PHY 切换ESP32-S2/S3 默认 USB 引脚被 USB Serial/JTAG 占用。安装时 esp_tinyuf2.c 的_usb_otg_phy_init先拉低 D 让主机产生“断开”事件避免快速切换导致主机不重新枚举再把 PHY 切到 OTG 控制器卸载时再切回 Serial/JTAG 控制器。这也是 CHANGELOG v0.2.2 中“切换后主机可能不重新枚举”问题的修复点。任务与电源安装时创建一个 4096 字节栈、绑定到核心 0 的usbd任务循环调用tud_task()若启用了 PMCONFIG_PM_ENABLE会申请 CPU 最高频锁保证 USB 时序稳定见 tinyusb_init。卸载的局限头文件注释明确说明“因 TinyUSB 不支持 teardown不释放内存”。实现上组件通过xTaskNotify让 USB 任务自行退出、对 S2/S3 用 GPIO matrix 给 VBUS 一个假断开信号再调用一个弱符号tusb_teardown()占位见 esp_tinyuf2.c。因此同一 Flash 内重复 install/uninstall 会累积静态内存设计时应有预期。挂载回调tud_mount_cb/tud_umount_cb/tud_suspend_cb/tud_resume_cb驱动三态状态机的迁移若开启了 USB Console还会在挂载时初始化 CDC-ACM 控制台把日志直接打到 USBCONFIG_ENABLE_UF2_USB_CONSOLE默认关闭。四、Kconfig 配置参数全解进入menuconfig的 “TinyUF2 Config” 菜单Kconfig完整参数如下配置项默认值 / 范围作用ENABLE_UF2_FLASHINGS2/S3/P4 下默认y总开关自动select TINYUSB_SOURCE_CODE_ONLY即以源码方式集成 TinyUSBENABLE_UF2_USB_CONSOLEn复用 CDC-ACM 把 ESP_LOG 输出到 USB 控制台UF2_DISK_SIZE_MB84~32虚拟磁盘容量UF2_FLASH_SIZE_MB42~8可升级 APP 的最大尺寸受 RAM 约束FLASH_CACHE_SIZE324~64单位 KBflash 写缓存大小TUSB_VID/TUSB_PID0x303A/0x8000USB 设备描述符的 VID/PIDUF2_VOLUME_LABEL按目标为ESP32S2-UF2/ESP32S3-UF2/ESP32P4-UF2主机看到的磁盘卷名TUSB_MANUFACTURER/TUSB_PRODUCT/UF2_SERIAL_NUM/UF2_INDEX_URLEspressif/ESP TinyUF2/12345678/ products 页面设备描述符字符串UF2_INI_FILE_SIZE512256~2048CONFIG.ini的大小UF2_INI_NVS_VALUE_HIDDENn允许在 ini 中隐藏 NVS 值敏感项不落盘到 iniUF2_INI_NVS_HIDDEN_MAX_NUM32可隐藏 key 的数量上限UF2_OTA_FACTORY_ONLYn限制 OTA 只能刷 factory 分区UF2_OTA_RESET_REASON_VALUE0xF2esp_restart_from_tinyuf2写入的重启原因提示值TINYUSB_RHPORT_HS/TINYUSB_RHPORT_FSP4 默认 HS其余默认 FSTinyUSB 使用的根端口 PHY高速/全速开启隐藏值功能时头文件在CONFIG_UF2_INI_NVS_VALUE_HIDDEN下额外暴露两个运行时 APIesp_tinyuf2_set_all_key_hidden(bool)与esp_tinyuf2_add_key_hidden(const char *key)用于把敏感键如 token从导出的 ini 中遮蔽见 esp_tinyuf2.h 对应段落的声明。五、实战一应用内 UF2 OTAusb_uf2_ota示例位于 examples/usb/device/usb_uf2_ota其 README.md 与 main/usb_uf2_ota_main.c 给出了完整流程。分区表示例提供 4MB/8MB 两档、factory 单分区与 factory双 OTA 两种表如 partitions_two_ota_4m.csv# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, , 0x4000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, factory, app, factory, , 1M, ota_0, app, ota_0, , 1M, ota_1, app, ota_1, , 1M,[sdkconfig.defaults](https://link.gitcode.com/i/4913370140e7df77bdcbb539587f089f)中同时开启了CONFIG_ENABLE_UF2_USB_CONSOLEy因此该示例升级完成后日志可直接走 USB 控制台。主程序要点usb_uf2_ota_main.c/* install UF2 OTA */ tinyuf2_ota_config_t config DEFAULT_TINYUF2_OTA_CONFIG(); config.complete_cb uf2_update_complete_cb; /* disable auto restart, manual restart later */ config.if_restart false; esp_tinyuf2_install(config, NULL); /* Waiting for UF2 ota completed */ ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ESP_LOGI(TAG, Firmware update complete); for (int i 5; i 0; i--) { /* 倒计时 5 秒 */ ... } esp_tinyuf2_uninstall(); /* 卸载USB 恢复默认状态 */ esp_restart();要点是关闭if_restart自动重启由complete_cb通过xTaskGetHandle(main) xTaskNotifyGive通知主任务主任务完成倒计时、卸载组件后再esp_restart()从而干净地落到新 OTA 分区。若目标板是 ESP32-S3 的 USB-OTG 变体CONFIG_ESP32_S3_USB_OTG代码还会先把 GPIO18 置低以释放默认 PHY 占用。操作流程README 原文步骤idf.py -p PORT flash monitor烧录第一版“支持 TinyUF2 的固件”用 USB 连接设备文件管理器中出现ESP32S3-UF2命名的新磁盘对后续版本执行idf.py uf2-ota生成或转换.uf2文件把.uf2文件拖入磁盘即完成升级示例串口/USB 日志会以 “Firmware update complete → Restarting in N seconds... → Restarting now” 收尾README 中附有完整输出样例。idf.py uf2-ota的实现组件 CMakeLists.txt 注册了一个名为uf2-ota的 CMake target它调用 utils/uf2conv.py 把build/project.bin按-c -b 0x00 -f target参数转换成project.uf2输出到工程根目录同目录的 uf2families.json 保存各芯片的 family ID-f参数据此匹配。六、实战二通过 CONFIG.ini 写回 NVSusb_uf2_nvs第二个示例 examples/usb/device/usb_uf2_nvs 演示了 TinyUF2 的“免配网 Wi-Fi 配网”场景见其 README.md 与 main 源码如存在则按实际文件名。该示例把 Wi-Fi 凭证存放在nvs分区的wifi_config命名空间key 为ssid/passwordtinyuf2_nvs_config_t nvs_config DEFAULT_TINYUF2_NVS_CONFIG(); nvs_config.part_name uf2_nvs_partition; // nvs nvs_config.namespace_name uf2_nvs_namespace; // wifi_config nvs_config.modified_cb uf2_nvs_modified_cb; ESP_ERROR_CHECK(esp_tinyuf2_install(NULL, nvs_config)); // 只传 nvs_configmodified_cb里置位事件组主循环被唤醒后重新nvs_get_str读出新凭证并重启 Wi-Fi。用户侧操作README 原文烧录固件后用 USB 连接出现 UF2 磁盘打开磁盘中的CONFIG.ini编辑ssid与password后保存设备解析保存的文件把键值对写回 NVS随即用新凭证连接 Wi-Fi。README 附带了完整日志样例uf2 nvs modified之后设备连上 APESP并获取到192.168.1.9。配合第四节的UF2_INI_NVS_VALUE_HIDDEN可以把password这类 key 遮蔽避免敏感值出现在导出的 ini 中。七、实战三Bootloader UF2bootloader_uf2examples/usb/device/bootloader_uf2 提供了第三种形态不依赖应用配合的 UF2 烧录。按其 README.md将CONFIG_BOOTLOADER_UF2_GPIO_NUM引脚拉到CONFIG_BOOTLOADER_UF2_GPIO_LEVEL电平并保持CONFIG_BOOTLOADER_UF2_GPIO_PULL_TIME_SECONDS秒设备即进入 TinyUF2 模式硬件按键即可触发适合量产救砖进入后BOOTLOADER_UF2_LED_INDICATOR_GPIO_NUM指示 LED 闪烁主机看到ESP32S3 - UF2磁盘该示例固定config.subtype ESP_PARTITION_SUBTYPE_APP_FACTORY见 main/usb_uf2_ota_main.c即把 UF2 刷到 factory 分区升级完成后自动重启并从 factory 启动。这一形态与Kconfig中的UF2_OTA_FACTORY_ONLY选项相呼应工厂产线场景只需 factory 分区无需 OTA 分区表。八、集成注意事项与适用边界结合 CMakeLists.txt、idf_component.yml 与源码实现集成时需要遵守以下前提芯片限制仅支持带 USB-OTG 的 ESP32-S2、ESP32-S3含 USB-OTG 变体、ESP32-P4ENABLE_UF2_FLASHING也仅在这三个 target 下默认开启TinyUSB 必须以源码方式编译若项目开启了 “Build tinyusb as a static library”TINYUSB_SOURCE_CODE_ONLY未选中组件会直接FATAL_ERROR报错提示关闭该选项RAM 与固件尺寸UF2_FLASH_SIZE_MB上限受writtenMask位图占用约束4MB 固件约需 2kB RAM设置时应同时评估UF2_DISK_SIZE_MB与FLASH_CACHE_SIZE卸载不释放内存见 3.2 节esp_tinyuf2_uninstall只恢复 USB 硬件状态不适合高频反复安装/卸载的场景描述符自定义量产时建议修改TUSB_VID/TUSB_PID与UF2_VOLUME_LABEL避免与示例默认值0x303A/0x8000、ESP32S3-UF2冲突。九、小结esp_tinyuf2用一块“虚拟 U 盘”把固件升级和设备配置两件事都变成了一次拖拽/一次保存文件UF2 块头自描述的目标地址让主机完全不感知分区布局ghost FAT MSC 让零驱动成本成立而 NVS ini 通道则提供了一个安全可控的免配网入口。仓库内的三个示例分别覆盖了应用内 OTAusb_uf2_ota、NVS 配置usb_uf2_nvs与 Bootloader 强制入口bootloader_uf2三条典型路线配合第四节的完整 Kconfig 参数表与idf.py uf2-ota构建目标即可在 S2/S3/P4 产品上快速落地一套免驱动的 USB 烧录与配置方案。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表