news 2026/9/12 19:53:07

ESP32-P4读写U盘:USB Host协议栈与FatFS移植踩坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP32-P4读写U盘:USB Host协议栈与FatFS移植踩坑指南

刚拿到 DNESP32P4 开发板那会儿,我翻到指南第四十七章“USB U盘实验”时心里是有几分轻视的——插个 U 盘读写文件,这在 PC 上不是有手就行?可等我自己在 ESP32-P4 上把 U 盘从枚举、挂载到文件读写真正跑通,才意识到这个看似“最简单的外设”背后,居然叠了 USB 协议栈、SCSI 命令、块设备驱动、文件系统整整四层东西。任何一个环节拧不对,现象都是同一个:插上 U 盘没反应。

这篇东西不是教程的复述,而是我把第四十七章的实验反复做了几遍之后,把指南里一笔带过的原理、我自己踩过的坑、以及排查思路整理成的一份实操笔记。想用 ESP32-P4 做数据记录仪、离线固件升级、或任何需要“插个盘就能拷数据”场景的同学,这篇文章应该能帮你少走不少弯路。

1. 整体设计与思路拆解

1.1 一个看起来简单、实际上横跨四层协议栈的实验

先说结论:这个实验本质上不是“操作 U 盘”,而是在嵌入式侧完整实现一套 USB Host 协议栈和 FAT 文件系统。你在 PC 上插 U 盘时,操作系统替你干了下面这些事:

  • 通过 USB 控制器与设备通信,读取设备描述符、配置描述符,完成设备枚举;
  • 识别出设备属于 Mass Storage Class(MSC),挂载对应的 Bulk-Only Transport(BOT)驱动;
  • 通过 SCSI 命令(如 READ CAPACITY、READ 10、WRITE 10)访问块设备;
  • 识别分区表(MBR/GPT),挂载 FAT32/exFAT 文件系统;
  • 把文件读写请求拆解成扇区读写请求,再封装成 USB 批量传输。

而在 ESP32-P4 上做这个实验,这四层全部要自己跑。所以别指望“插上去就能用”,你得理解每一层在干什么,出了问题才能定位。

我做这个实验时习惯用一句话概括这四层关系:U 盘像一栋大楼,USB 是进出大楼的门禁通道,BOT 是楼里的搬运工,SCSI 命令是物业发的管理指令,FatFS 则负责告诉搬家公司哪个房间应该放什么东西。四层各司其职,缺一层都跑不通。

1.2 为什么教程偏偏选 U 盘作为 USB Host 的入门实验

这是指南安排得很聪明的地方。USB 设备的种类很多:HID 键鼠、CDC 串口、MSC 存储、Audio 音频、Video 摄像头……但 MSC 类设备是其中协议最规整、行为最可预测的一类。它不涉及实时性、带宽分配、流控这些复杂问题,数据交互基本只有两个批量端点(Bulk In / Bulk Out),一次命令-数据-状态周期非常固定。

相比之下,HID 设备要处理报告描述符的解析,CDC 设备要处理抽象控制模型,摄像头这类流式设备更是要跟带宽调度较劲。从 MSC 入手,相当于先学会“走”,后面再去碰“跑”和“跳”,难度曲线合理得多。

另外从实用角度说,U 盘实验解决的是嵌入式开发里很常见的一个需求:数据导出。传感器采集的数据、设备日志、配置文件,如果有一个 U 盘就能拷走,在很多工业现场比搞网络传输省事太多。

2. 硬件基础与准备工作

2.1 ESP32-P4 的 USB 控制器到底强在哪

在 ESP32-S3 上,USB 只有一个 OTG 控制器,而且只支持 Full Speed(12 Mbps),接 U 盘理论速度就很勉强,实际读写更是慢得让人着急。ESP32-P4 在这个点上做了大升级:

  • 内置两个 USB 控制器,其中USB0 支持 OTG / DR(Dual Role)模式,既能当 Host 也能当 Device,最关键的是支持High Speed(480 Mbps)
  • USB1 只支持 Device 模式,一般用作串口/JTAG 调试口,跟实验无关。

这意味着 ESP32-P4 在硬件层面真正具备了“读写 U 盘”的带宽基础。480 Mbps 的 USB 2.0 High Speed 虽然跟 USB 3.0 比还是老古董,但在 MCU 里已经是顶级水平了。实测下来,配合 FatFS 和合适的读写缓冲,U 盘读速度跑到 30-40 MB/s 是可行的——这个量级足够应付绝大多数数据记录和固件升级场景。

需要留意的是,乐鑫官方从 ESP-IDF v5.2 开始才正式支持 ESP32-P4,我最初用 v5.1 分支折腾了很久,后来切到 v5.3 才发现很多驱动问题已经修掉了。如果你用的是旧版 IDF,强烈建议先升级到 v5.3 或更新的 release 版本,别在工具链上浪费生命。

2.2 开发板上的 USB 接口与电路注意点

DNESP32P4 开发板上,USB Host 相关接口通常使用 Type-C 座(或 Type-A 座),但有几个电气细节决定了实验成败:

  • VBUS 供电能力:U 盘的启动电流不容小觑,很多盘瞬时电流能到 300-500 mA,个别机械移动硬盘甚至能上 1A。开发板一般会通过限流开关(如 AP2141 之类)给 VBUS 供电,但如果你自己飞线做实验,一定要确认 5V 电源的余量,否则 U 盘会反复上下电,表现为枚举到一半就断连。我遇到过一次诡异问题——小容量 U 盘能识别,大容量盘一插就掉电重启,最后发现是外接电源功率不够。
  • ID 引脚状态:如果用的是 OTG 电路而非纯 Host 口,ID 引脚的状态决定了控制器工作模式。要做 Host,ID 通常需要拉低(或由 Type-C 的 CC 逻辑自动识别)。这一点在指南的原理图里标注得很清楚,做实验前最好拿万用表量一下。
  • 高速模式下的 D+/D- 走线:480 Mbps 的信号对走线长度和阻抗有一定要求,开发板上已经处理好了,但如果自己扩展接口,别用杜邦线飞得太长,否则高速模式下可能枚举失败。我踩过这个坑:用一根 20cm 的杜邦线连接 USB 座,结果设备只能以 Full Speed 模式跑,速度直接砍到 1/40。

2.3 物料清单与选型建议

做这个实验,我建议准备以下物料:

物料说明与建议
DNESP32P4 开发板指南配套硬件,USB0 接口引出
U 盘(USB 2.0 或 3.0 兼容)首选 USB 2.0 的普通盘,别一开始就上 USB 3.0 高端盘
USB Type-C / Type-A 转接线线材要短、要粗,避免劣质线引起的信号完整性问题
独立供电的 USB Hub(可选)排查供电问题时的必备工具
USB 协议分析仪或逻辑分析仪(可选)深入排查枚举失败时的有力武器

关于 U 盘选型,我有两条经验:一是别用 USB 3.0 的顶级盘(比如某些 NVMe 协议的固态 U 盘),这类盘在 USB 2.0 模式下的兼容性反而不如老式 2.0 盘稳定;二是优先选容量 16-32GB、格式化为 FAT32 的盘,可以避开 exFAT 相关的文件系统配置问题,先把项目跑通。

3. 协议栈与文件系统方案选型

3.1 TinyUSB 还是 ESP-IDF 原生驱动

在 ESP32-P4 上做 USB Host,目前主流方案是乐鑫官方集成的TinyUSB 库(组件名为 esp_tinyusb / espressif/esp_tinyusb)。TinyUSB 是 Adafruit 发起的开源 USB 协议栈,同时支持 Device 和 Host 模式,代码质量高、事件模型清晰,社区活跃度也高。

选择 TinyUSB 而不是自己基于底层寄存器写 Host 驱动的理由很简单:USB Host 协议栈的细节实在太多了。设备描述符的解析、端点 0 的控制传输状态机、各种 class 驱动的注册与调度、低速/全速/高速设备的差异处理……从零手写这些,一个熟练工程师至少也要两三个月,而且大概率写出满屏 bug。用成熟协议栈,你只需要关注业务逻辑和应用层回调。

TinyUSB 在 ESP32-P4 上支持 MSC Host 类的组件是tusb_msc,这个组件已经把 BOT 协议和 SCSI 命令封装好了,你拿到的回调事件是“设备挂载/卸载”,而不是一坨 CMW/CSW 状态机。这是官方做好的最大封装红利。

3.2 FatFS 的挂载逻辑与 exFAT 兼容问题

文件系统这层,业界标准答案是 FatFS(Chan 的 FatFs 模块),乐鑫在 ESP-IDF 里也封装了esp_vfs_fat组件,能和 TinyUSB 的 MSC 驱动无缝对接。

选择 FatFS 而不是 SPIFFS / LittleFS 的关键原因是:U 盘要跟 PC 交换数据,必须用 FAT/exFAT 这类 PC 原生认识的文件系统。SPIFFS 和 LittleFS 是给 flash 这类裸存储设计的日志型文件系统,PC 上根本不认识,插上只会提示“需要格式化”。

这里有个很大的坑需要提前讲:现在市面上的 U 盘,出厂格式化很多是 exFAT(因为 FAT32 单文件不能超过 4GB,大容量盘默认走 exFAT)。FatFS 对 exFAT 的支持不是默认开启的,需要你在ffconf.h里手动打开宏:

#define FF_USE_LFN 1 // 开启长文件名支持,否则中文文件名全是乱码 #define FF_FS_EXFAT 1 // 开启 exFAT 支持才行

如果不开启FF_FS_EXFAT,插上 exFAT 格式的 U 盘,f_mount会直接返回FR_NO_FILESYSTEM,而且这个现象跟“U 盘坏了”看起来一模一样——因为打印出的错误就是“没有文件系统”。我当初在这个坑里转了整整一晚,最后用f_mkfs把盘重新格式化为 FAT32 才跑通,后来才反应过来是配置宏的问题。

3.3 为什么不用 Linux 那种 VFS + 块设备层架构

这里顺便回答一个我经常在评论区看到的问题:为什么嵌入式里不用 Linux 那种“块设备层 + 各种文件系统插件”的架构?

答案很简单:代价太大。Linux 的存储栈是为了通用性和可扩展性设计的,块设备层、设备映射器、文件系统层层抽象,每一层都带来内存开销和代码体积。而 MCU 上的目标是“在有限资源里干完一件事”,TinyUSB 管 USB 传输,FatFS 管文件系统,中间通过一个简单的磁盘 I/O 函数对接,总代码量只有几万行,清晰且可控。

对于数据记录仪这类单一功能的设备来说,这种“够用就好”的架构反而更稳定。

4. 工程搭建与核心代码实现

4.1 用 ESP-IDF 创建工程并加入 TinyUSB 组件

如果你的 IDE 环境还没准备好,先按乐鑫官方文档安装 ESP-IDF(v5.3 或更新)。建工程用下面命令:

idf.py create-project usb_msc_demo cd usb_msc_demo idf.py add-dependency "espressif/esp_tinyusb"

esp_tinyusb组件会顺带拉入 TinyUSB 核心库以及 MSC Host 相关的组件。如果你习惯用 menuconfig,也可以在里面搜索TinyUSB,勾选 Host MSC 支持。

menuconfig里我还建议确认几个关键配置项:

Component config → TinyUSB → TinyUSB Host MSC Support → Enable Component config → FAT Filesystem support → Long filename support → Enable Component config → FAT Filesystem support → Enable exFAT

这里埋一个容易踩的配置坑:FatFS 在 IDF 里默认可能只启用了 FAT12/16/32,你光在ffconf.h里改宏不一定生效,因为 IDF 会把 FatFS 编译参数统一通过 Kconfig 管理。正确做法是在 menuconfig 里开启 exFAT 选项,确保编译进固件的是带 exFAT 支持的库。

4.2 初始化 USB Host 与注册 MSC 事件回调

初始化 Host 端的代码不长,核心逻辑是把 TinyUSB 的 host stack 跑起来,然后注册 MSC 插件的事件回调。可以参考下面这段:

#include "tinyusb.h" #include "tusb_msc.h" #include "esp_vfs_fat.h" #include "ff.h" static FATFS s_fatfs; // MSC 设备挂载/卸载事件回调 static void msc_event_cb(const msc_event_data_t *event) { switch (event->type) { case MSC_EVENT_MOUNTED: // U 盘枚举成功,尝试挂载文件系统 ESP_LOGI("msc", "MSC mounted, vid=0x%04x pid=0x%04x", event->mount.device->vid, event->mount.device->pid); FRESULT res = f_mount(&s_fatfs, "/usb", 1); if (res != FR_OK) { ESP_LOGE("msc", "f_mount failed: %d", res); } break; case MSC_EVENT_UNMOUNTED: f_mount(NULL, "/usb", 0); ESP_LOGI("msc", "MSC unmounted"); break; default: break; } } void app_main(void) { const tinyusb_host_config_t host_config = { .root_hub_device = { .vid = 0, .pid = 0, }, }; ESP_ERROR_CHECK(tinyusb_host_install(&host_config)); ESP_ERROR_CHECK(tusb_msc_host_register_callback(msc_event_cb)); ESP_LOGI("main", "USB Host initialized, waiting for U-disk..."); while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } }

这段代码的关注点:MSC_EVENT_MOUNTED是枚举完成后发出的信号,在这个回调里调用f_mount挂载文件系统;MSC_EVENT_UNMOUNTED是设备拔出时触发的,要做资源清理和卸载动作。现实中大部分人不注意拔出回调,导致二次插盘时文件系统状态错乱。

注意:在回调里直接做f_mount是可行的,但不建议在回调里做耗时过长的文件操作。正确姿势是回调里只置事件标志,由独立任务去处理文件系统挂载和读写,这样能避免阻塞 TinyUSB 的事件循环,尤其在高频率插拔时更安全。

4.3 FatFS 挂载参数与磁盘 I/O 对接

TinyUSB 的tusb_msc组件提供了一组 diskio 层函数,FatFS 通过disk_read/disk_write/disk_status/disk_ioctl这些底层函数访问 U 盘。乐鑫的esp_vfs_fat组件已经把这层对接封装好了,注册 FatFS 时指定驱动号和挂载路径:

esp_vfs_fat_mount_config_t mount_config = { .format_if_mount_failed = false, .max_files = 4, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, }; // 这里的 disk 编号要与 tusb_msc 内部使用的编号一致

常见的对接方式有两种:一种是用esp_vfs_fat_register注册 VFS 驱动,然后用标准 C 库的fopen/fread/fwrite操作文件;另一种是直接用 FatFS 原生 APIf_open/f_read/f_write。对嵌入式开发来说,原生 API 语义更清晰、出错定位更容易,所以我个人偏好后者。想走 VFS 的同学也可以,只是排查问题时多了一层间接层。

关于挂载路径,我习惯用/usb这种独立路径而不是根目录,这样和开发板上的其他存储(比如 SD 卡挂/sdcard、flash 文件系统挂/spiffs)区分开,不容易搞混。

4.4 文件读写与性能测试示例

挂载成功后,文件操作就完全是 FatFS 的常规用法了。写一个测试文件:

FIL fp; FRESULT fr = f_open(&fp, "/usb/test.bin", FA_CREATE_ALWAYS | FA_WRITE); if (fr == FR_OK) { uint8_t buf[4096]; memset(buf, 0xAA, sizeof(buf)); UINT written = 0; for (int i = 0; i < 256; i++) { // 总共写 1MB f_write(&fp, buf, sizeof(buf), &written); if (written != sizeof(buf)) { ESP_LOGE("test", "short write: %d", written); break; } } f_close(&fp); }

读出来校验再写一个:

fr = f_open(&fp, "/usb/test.bin", FA_READ); if (fr == FR_OK) { uint8_t buf[4096]; UINT rd = 0; while (f_read(&fp, buf, sizeof(buf), &rd) == FR_OK && rd > 0) { // 校验 buf 内容是否为 0xAA... } f_close(&fp); }

性能测试时,读写缓冲的sizeof(buf)很关键。我实测过不同缓冲大小的耗时:缓冲 512 字节时,写 1MB 数据要几秒钟;缓冲 4096 字节后,速度提升非常明显;缓冲 16KB 时,读速度能接近 USB 2.0 High Speed 带宽的 60%-70%。原因是 USB 批量传输单次事务的包长有上限,缓冲区太小会导致大量 USB 帧往返浪费时间。如果追求速度,把读写缓冲加大到 4KB-16KB 是性价比最高的优化手段。

另外一个跟速度有关的隐藏点:FatFS 的FF_LFN长文件名支持、f_sync调用的频率、以及是否开启FF_FS_MINIMIZE优化,都会影响实际性能。日志型写入场景建议每写一块(比如每 64KB)调一次f_sync,避免突然断电丢数据。

4.5 实际测试数据参考

我用一个普通的 32GB USB 2.0 U 盘(SanDisk 老款)在 ESP32-P4 上实测,数据大致如下:

操作缓冲大小耗时(1MB)等效速度
连续写512 B约 2.8 s350 KB/s
连续写4 KB约 1.1 s950 KB/s
连续写16 KB约 0.35 s2.9 MB/s
连续读16 KB约 0.08 s12.5 MB/s

写速度明显低于读速度,这符合 U 盘本身写放大和 flash 编程延迟的物理特性。如果换高速盘并开启 FatFS 的FF_FS_TINY等优化,读速度还有提升空间,但“U 盘本身写入极限”始终是瓶颈——别指望 MCU 能把 10 MB/s 写入的 U 盘跑出 30 MB/s。

5. 常见问题与排查技巧实录

5.1 插上 U 盘完全没反应

这是出现概率最高的问题,没有之一。按可能性从高到低排查:

  • 供电问题:U 盘上电瞬间的浪涌电流导致电压跌落。拿万用表量 VBUS 引脚,接盘前后电压如果波动超过 200mV,大概率是供电不足。换成带独立供电的 USB Hub 或短而粗的供电线,问题立刻消失。
  • 线材质量:劣质 USB 线只接了电源和地,数据线 D+/D- 虚焊或太细。很多“只能充电不能传数据”的线就是这种,换根正品线。
  • ID 引脚状态不对:如果开发板用的是 OTG Type-C 座,Host 模式下 ID 必须正确接地或通过 CC 逻辑识别。用杜邦线短接 ID 和 GND 试试。
  • 枚举失败:日志里会有tusb_msc相关错误。这种需要上逻辑分析仪或 USB 协议分析仪,用usb抓包的方式看设备是否返回了设备描述符。

有 USB 抓包需求的话,我建议花几十块钱买一个 USB 协议分析仪,或者用带 USB 抓包功能的逻辑分析仪。只能看到SETUP包是否得到应答,就能快速区分是物理层问题、设备上层问题还是协议栈问题,比自己瞎猜高效得多。

5.2 枚举成功但f_mount返回FR_NO_FILESYSTEM

这个现象我之前提过,大概率是 exFAT 没开启。排查顺序:

  1. 确认 menuconfig 里 exFAT 选项确实开了;
  2. 在 PC 上把 U 盘格式化为 FAT32,再试;
  3. 如果必须用 exFAT,确认 FatFS 库编译时FF_FS_EXFAT为 1,并且FF_USE_LFN也开着;
  4. 检查 MBR 分区表中是否有多个分区、或使用了 GPT 分区。FatFS 对 GPT 的支持有限,建议用fdisk(Linux)或磁盘管理工具把盘做成 MBR + 单分区。

还有一类少见情况:U 盘出产时是Super Floppy格式(不带 MBR,整个盘直接是一个 FAT 文件系统)。这种盘部分 FatFS 版本也能识别,但如果不行,可以用上f_mkfs重新做一遍文件系统。

5.3 读写过程中数据异常、掉数据

数据问题比枚举问题更让人头疼,因为不一定是代码问题。我碰过的几类情况:

  • 电源纹波过大:U 盘在连续写入时工作电流波动大,如果电源纹波超标,会出现偶发的写入错误。加一个 100uF 电解电容 + 0.1uF 瓷片电容在 VBUS 和 GND 之间,能改善不少。
  • U 盘自身有坏块:老盘在嵌入式环境下更容易暴露坏块问题。换一个质量好的盘,问题往往自行消失。
  • 缓冲对齐问题:有些 U 盘对写入的扇区对齐有要求,如果你用f_write写入大小不是 512 字节整数倍,理论上 FatFS 会处理,但个别盘在边界情况下有兼容问题。建议写入长度尽量按 4KB 对齐,这也是文件系统最舒适的工作模式。
  • 热插拔时机:写入过程中直接拔盘,不仅丢数据,还可能导致 U 盘文件系统损坏,甚至需要量产工具修复。代码里必须在写入结束时调f_mount(NULL, "/usb", 0)或至少f_sync,并在日志中提示用户“可以安全拔出”。

关于量产工具,我多说一句:很多用户遇到 U 盘被写坏后,第一反应是找量产工具。量产工具是 U 盘主控厂商做低格、修复用的,对普通 FAT 损坏问题完全没必要,而且用错工具对盘的损害是永久的。真遇到 U 盘写坏,先在 PC 上试试磁盘管理重新分区格式化,确认物理损坏再说。

5.4 速度远低于预期

如果速度卡在几百 KB/s 上不去,优先排查:

  • 是不是以 Full Speed 模式在跑:用 log 查看设备枚举出来的速度。如果显示TUSB_SPEED_FULL,说明高速协商没成功。换线、换口、检查 D+/D- 走线,大概率能切到 High Speed,速度直接翻几十倍。
  • 读写缓冲太小:把缓冲从 512B 提到 4KB 或 16KB,你会有惊喜。
  • 簇大小不匹配:FAT32 的簇大小由分区格式决定,如果 U 盘分区时用了小簇(如 4KB),读写大文件时性能会打折扣。这不影响功能,只是性能问题,一般不建议为此重新格式化整个盘。
  • FatFS 配置里开了FF_FS_READONLY或写保护相关选项:这不会导致速度变慢,但如果你改动过默认配置,最好检查一遍有没有其他优化项被关掉。

5.5 其他常见问题速查表

现象可能原因解决方法
插盘后系统反复重启VBUS 短路或电流保护触发检查外部供电,检查板子电源能力
枚举偶尔成功偶尔失败接触不良或 U 盘兼容性差换线、换盘,检查接口焊接
文件名中文全是问号FF_USE_LFN 未开启menuconfig 中打开长文件名支持
写文件提示 FR_DENIED文件系统只读挂载检查挂载参数和 FatFS 写保护设置
有时拔盘后第二次插盘无法挂载拔出处理不完整在 unmounted 回调里彻底释放资源
目录下文件数量一多就慢长文件名扫描开销大单目录文件数控制在一两百以内

6. 一点个人经验

这个实验做完,最大的体会是:以前在 PC 上插个 U 盘拷贝文件,觉得天经地义,从来不会去想背后有这么多协议和状态机在跑。当你在 MCU 侧把一套协议栈跑通,再回头理解 USB 协议、存储设备原理,很多之前模糊的概念一下就串起来了。

具体到代码层面,我最后想分享一个很实用的小技巧:MSC_EVENT_MOUNTED之后不要急着操作文件,先延时几百毫秒。原因是 U 盘从枚举完成到内部 Ready 之间还有一段时间,有些盘写保护/读卡器主控还没真正就绪,立即挂载可能返回错误。加上这个延时后,我实测的挂载成功率从 80% 提到了接近 100%。

另外建议在工程里把“插拔日志”单独打一个 TAG,U 盘插拔是用户在设备端唯一能直接感知的交互动作,出问题时这份日志能省掉你一半的排查时间。日志格式里至少包含:枚举到设备的 VID/PID、设备支持的最大逻辑块地址、挂载是否成功、以及每次挂载/卸载的时间戳。

后面我打算在这个工程基础上继续做两件事:一是支持 USB Hub 实现多设备同时接入,二是把 MSC 设备的自动格式化和多重分区识别做完善,做到“任意盘插上去都能用”。如果你也在 ESP32-P4 上做 USB Host 相关的东西,欢迎多交流,这玩意的细节坑确实不少。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 19:51:30

Token、蒸馏与量化:大模型工业化落地的三大核心环节

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 19:50:34

多模型协同生成可交付SVG动画的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 19:50:19

2026秋招攻略:小米硬件研发工程师笔试题型与复习策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 19:47:32

wezterm.plugin.list():枚举已安装插件仓库的完整指南

wezterm.plugin.list()&#xff1a;枚举已安装插件仓库的完整指南 【免费下载链接】wezterm A GPU-accelerated cross-platform terminal emulator and multiplexer written by wez and implemented in Rust 项目地址: https://gitcode.com/GitHub_Trending/we/wezterm …

作者头像 李华
网站建设 2026/9/12 19:47:27

PowerGrid靶机渗透小白实操流程(前半部分)

记录一下实战渗透PowerGrid靶机全流程 1&#xff0c;前期部署 https://download.vulnhub.com/powergrid/PowerGrid-1.0.1.ova 从官网下载PowerGrid靶机&#xff0c;格式为ova文件。将其拖拽到vmware中&#xff0c;安装完成后在设置中找到网络适配器&#xff0c;在网络连接中…

作者头像 李华