首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
WSL下STM32开发板烧录指南:USB透传与OpenOCD实操
📅 2026/10/20 1:05:26
✍️ 爱科研究院
👁 阅读 3,247
我板子呢这个问题在过去的几周里几乎成了我每天坐在工位前的第一句话。不是因为爱丢东西而是因为自从我彻底切到WSL环境下写STM32的嵌入式C代码之后编译、构建、版本管理都顺得离谱唯独到了烧录这一步开发板明明插在电脑上WSL里却像什么都没发生一样。这大概是所有端着WSL做嵌入式的人都会撞上的墙IDE里的烧录按钮在Linux侧使不上劲Windows侧的烧录工具又不认识你用CMake折腾出来的那些二进制。所以这篇就来聊聊在WSL环境里到底怎么才能把手里的STM32开发板顺利地烧录起来把这句“我板子呢”变成“板子在WSL里好好待着呢”。按照这个系列的进度到这一步其实已经能写出能在片子上跑起来的C代码了但代码写完总得烧进去看现象。网上关于WSL烧录的帖子不少但大多零散有的说WSL1直接开串口有的说用网络调试器看完更糊涂。我花了两天时间把自己踩过的坑和最终跑通的方案完整梳理了一遍这里面包括USB设备怎么透传、OpenOCD怎么装、烧录命令怎么敲、烧录失败怎么排查还有几个不看一眼文档绝对发现不了的隐藏问题。这篇尽量讲透让后面的人不用再经历一次板子失踪案。1. 起因开发板明明在USB口上WSL里却像没插一样1.1 我板子呢的经典重现先描述一个大多数人都会遇到的场景你在Windows下用烧录工具成功烧了一次确认板子能跑然后想回WSL里改代码。写完代码、编译、生成了.bin拿起线准备烧这时WSL终端里的lsusb输出光秃秃的只有那个虚拟的xHCI host controller根本没有ST-Link的影子。你会下意识地摸一下USB线发现板子的电源灯亮着于是你怀疑是不是线坏了换一根线还是不行。然后你打开Windows设备管理器板子好好的在端口和通用串行总线设备下都看得见。这时候就会冒出那句经典的我板子呢。这不是板子丢了而是WSL2和Windows之间存在一层隔离墙。WSL2本质上是跑在Hyper-V虚拟机里的一个轻量Linux它拥有独立的Linux内核和独立的USB设备子系统Windows上插着的USB设备并不会自动透传过去。WSL1倒是没有这堵墙它直接翻译Windows系统调用所以你可以通过/dev/ttyS0之类的方式访问串口但WSL1又不能跑很多嵌入式工具链要用的Linux内核特性。这让人很难受。1.2 是WSL1还是WSL2决定了你接下来的路径很多人一上来就找WSL烧录STM32的教程结果发现旧教程里写着用WSL1直接访问COM口于是照着操作在WSL2里怎么都找不到设备开始怀疑人生。我们先把这个概念掰清楚如果你用的是WSL1那么宿主机上的COM口会以串口设备的形式映射到Linux里比如/dev/ttyS0配合一个Windows端的USB转UART桥接确实可以在WSL1里操作串口。但WSL2不行WSL2是真正的虚拟化环境它不能直接看到宿主机USB设备。从当前主流的开发习惯来看大部分人的WSL都升级到了WSL2通过wsl --set-version命令可以查到因为WSL2的I/O性能和兼容性更好。所以这篇文章的主角是WSL2下的烧录方案。顺带说一句如果你还在用WSL1其实不太建议为烧录单独迁回WSL1因为后面你会遇到更多边边角角的问题不如一次性把USB透传搞定以后调试器、串口、烧录器都能一并复用。1.3 为什么非要跟WSL较劲Windows下烧录不香吗每次有人听说我在WSL里折腾烧录第一反应都是你这不是自找麻烦Windows下打开烧录软件点一下不就完事了。确实如果一天就烧一次Windows下点几下没毛病。但我的实际痛点是代码已经全切到WSL侧的CMake工程里了编译、链接、代码格式化、静态检查全在Linux侧每次改完代码切到Windows去烧录中间要经历拷贝文件、找工具、选文件、点烧录这一串重复劳动稍微多烧几次就烦了。更别说我想在脚本里实现编译通过后自动烧录的流程Windows GUI完全没法配合。把烧录迁到WSL里得到的是一整套命令行工作流改代码、编译、烧录、看串口全在同一个终端里完成。脚本化之后以后同事拿到工程只要执行一条命令板子就亮起来了。这种体验上的提升值得花一次功夫把USB透传和研究清楚。这也是我写这篇的初衷。2. WSL2下的USB穿透方案usbipd-win的正确使用姿势2.1 USB/IP是什么为什么选它WSL2不能直通USB那怎么把板子交到WSL手里最成熟、社区验证最多的方案是使用usbipd-win加上Linux内核里的usbip客户端。usbip的全称是USB over IP它把一个USB设备从一台机器分享给另外一台机器Windows这边作为USB设备共享服务器WSL2作为客户端接收设备。听起来很复杂其实安装和操作只要几步。注意这里说的不是虚拟机的USB直通功能而是更灵活的设备共享协议。为什么不用Hyper-V的增强会话或Windows自带的USB重定向因为那些是给完整虚拟机用的WSL2没有图形界面管理工具直接在命令行里敲命令更顺手。usbipd-win从很早就开始维护目前版本比较稳定配合WSL2的内核可以直接工作。我自己用下来感觉最舒服的一点是它支持--auto-attach参数可以设定某个设备在插入时自动挂到WSL2里不需要每次手动attach省去了很多麻烦。2.2 Windows侧安装、绑定、attach的完整命令先来看Windows侧要做什么。在Windows 11或较新的Windows 10上你可以通过winget直接安装usbipd-win命令如下winget install usbipd装完之后PowerShell或者CMD需要以管理员身份运行因为后面要操作USB设备。先列出当前计算机上的USB设备usbipd list输出会显示一个BUSID列表每行就是一个USB设备一列是设备描述。比如你的STM32板载ST-Link会显示类似STMicroelectronics STLink dongle这样的名字。找到之后把它绑定bind。绑定的意思是让这个设备可以被WSL共享出来命令格式是usbipd bind --busid BUSID如果希望以后每次插入这个设备时自动挂到某个WSL发行版可以加一个auto-attach参数usbipd bind --busid BUSID --auto-attach绑定之后设备在Windows里就会被摘下来好像被拔掉一样因为它已经准备好交给WSL了。然后执行attach命令usbipd attach --wsl --busid BUSID如果只有一个WSL发行版直接写--wsl即可。如果有多个发行版用--wsl 发行版名字指定。attach成功之后设备就会出现在WSL2里。此时在WSL终端里执行lsusb应该能看到对应的设备了。需要特别提醒的是每次重启Windows或者重启WSLattach状态都会丢失需要重新执行attach。auto-attach也不是完全万能它只处理插入时自动attach如果重启之后设备已经插着还是需要手动attach一次。我习惯把attach命令写成一个alias这样重新进入WSL后一条命令就能恢复。2.3 WSL侧usbip客户端工具的配置WSL2的Linux内核默认带usbip支持但还需要安装用户空间工具不同发行版命令略有不同。Ubuntu/Debian下执行sudo apt update sudo apt install linux-tools-generic usbip hwdata注意linux-tools-generic这个包安装之后usbip命令可能在/usr/lib/linux-tools/内核版本/usbip路径下不在PATH里。你可以直接找到它或者做一个软链接sudo ln -s /usr/lib/linux-tools/$(uname -r)/usbip /usr/local/bin/usbip其实在我们执行attach时通常直接用usbipd的命令就行因为usbipd-win也就是调用了usbip协议。但如果想手动debug可以用usbip list -r Windows主机的IP来查看远程设备列表。一般用不上知道有这回事就行。装好之后在WSL里运行lsusb看到类似STMicroelectronics ST-LINK的就是设备到达了。如果设备对应的是USB转串口在lsusb里也会显示。接下来就可以在WSL里直接访问这个设备。2.4 多发行版、多设备场景下的管理细节如果你装了多个WSL发行版比如一个Ubuntu用于日常开发一个Debian用来做实验attach命令必须指定目标发行版否则usbipd-win不知道往哪儿送。每次attach都要写发行版名字很容易写错。我自己的做法是给每个发行版写一个不同的脚本脚本里exportWSL_DISTRO_NAME再执行attach。这样就算发行版多也不会乱。还有一个细节lsusb看到的设备可能有多个。比如一块ST官方开发板板载ST-Link和USB虚拟串口其实是两个USB功能枚举出来是两个独立设备。如果你把带调试功能的那个设备attach进去了但串口功能那个设备还留在Windows里WSL里就看不到/dev/ttyACM0。所以attach之前先确认一下究竟哪个busid对应你需要的功能。用usbipd list输出里的描述信息就能判断。3. 烧录工具链的安装与配置OpenOCD还是st-flash3.1 两条路线该怎么选设备能看见了只是第一步。接下来要选一个WSL里能跑的烧录工具。目前STM32烧录工具几条主流路线OpenOCD跨平台开源调试和烧录工具支持ST-Link、J-Link等多种调试器社区活跃支持大量目标芯片适合复杂调试和自动化烧录。st-flashstlink-toolsST-Link专用的命令行烧录工具轻量命令简单适合快速烧录但只支持ST-Link。官方图形烧录工具ST官方工具Linux版CLI也能跑但在WSL2里权限问题处理起来比较别扭而且重。我做嵌入式开发的时候比较喜欢OpenOCD因为它不仅能烧录还能配合gdb做调试这一篇烧录下一篇调试也用得上。st-flash更简单直观适合不折腾的人。下面我把两条路都列出来你按自己的风格选。3.2 OpenOCD的安装与基础验证在Ubuntu下安装OpenOCD很方便sudo apt install openocd但这里有个坑Ubuntu官方仓库里的OpenOCD版本可能偏旧而新出的STM32系列芯片可能需要更新的OpenOCD才有支持。如果你用的是比较常规的STM32F1/F4仓库版足够。如果用的是新款芯片建议从源码编译。源码编译也不复杂sudo apt install libtool autoconf automake pkg-config libusb-1.0-0-dev git clone https://github.com/openocd-org/openocd.git cd openocd ./bootstrap ./configure --prefix/usr/local make -j$(nproc) sudo make install编译安装之后检查版本openocd --version与此同时还需要安装arm的交叉编译器。如果你的项目里已经用了CMake可能已经装了。没装的话sudo apt install gcc-arm-none-eabi装完跑一下arm-none-eabi-gcc --version3.3 st-flash的安装与使用st-flash是ST-Link工具集里的命令行烧录工具在Ubuntu下也可以直接装sudo apt install stlink-tools安装完成后可以用st-info --probe来查看当前连接的ST-Link设备。如果设备识别正常会显示芯片型号和容量。烧录的命令很简单st-flash write firmware.bin 0x08000000st-flash只能写bin文件不能直接写elf所以需要先把编译产物转化为bin格式。OpenOCD则可以直接写elf比较省事。从这一点来说我用OpenOCD更多。3.4 为什么我不建议在WSL里用官方GUI烧录工具官方烧录工具的Linux版本虽然提供了CLI但用起来有两个问题。第一它依赖特定的图形库WSL2如果没有启用WSLg跑起来可能报找不到显示器的错虽然CLI模式不需要GUI但安装包体积和依赖确实不小。第二它对USB设备的访问默认走的是自己的驱动栈在WSL2的透传环境下偶尔会出现检测不到设备的情况还得去改配置。相比之下OpenOCD直接走libusb跟usbipd透传过来的设备配合得很自然。当然如果你在Windows下已经习惯用官方工具也没必要非换不可。但从自动化角度讲CLI工具越轻量越好。我现在的工程就是CMake里加一个自定义目标编译完直接调OpenOCD一步到位。3.5 在WSL里验证设备权限的快速检查不管用哪个工具第一步都要确认WSL能看到设备。插上板子在WSL里执行lsusb如果你看到类似1689:5730 STMicroelectronics这样的设备ID说明透传成功。但即便看到了工具可能还是提示libusb_open failed或者permission denied。这是因为Linux对USB设备有权限控制普通用户不能直接访问。解决办法是配置udev规则把当前用户加入dialout组并让ST-Link设备允许用户读写。在WSL2里udev规则也是生效的但需要额外注意WSL的init系统处理方式后面我会专门讲这个坑。4. 烧录实操从编译到OpenOCD烧录的完整链路4.1 一次最小的烧录命令假设你的工程已经用CMake编译出了一个elf文件叫app.elf。在WSL里用OpenOCD烧录命令如下openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c program app.elf verify reset exit其中-f指定接口配置和目标芯片配置。interface/stlink.cfg是ST-Link接口配置文件target/stm32f1x.cfg是STM32F1系列的目标芯片配置。如果你用的是F4改成stm32f4x.cfg即可。命令行的含义是启动OpenOCD加载ST-Link接口和芯片配置然后执行program命令烧录app.elf烧完校验verify复位reset退出exit。这一条命令是日常使用频率最高的没有之一。如果烧录的是bin文件也可以openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c program app.bin 0x08000000 verify reset exit注意bin文件需要在program命令里指定起始地址elf文件不需要因为elf本身就包含加载地址的信息。4.2 编译时要确认的链接地址和格式在嵌入式开发里一个很隐蔽的问题是编译出来的elf文件用的地址和OpenOCD默认烧录的地址是否一致。如果CMake里链接脚本设置的FLASH起始地址不是0x08000000比如跑Bootloader时是0x08010000你直接用OpenOCD烧elf也能正确写入因为elf里有地址信息。但如果你手动把elf转成bin然后烧录时写错地址程序肯定跑不起来。我建议能写elf就直接写elf少一步转换就少一个出错点。如果你的构建流程里已经用objcopy生成了bin那务必确认命令行里给的地址和链接脚本一致。可以用arm-none-eabi-objdump -h app.elf查看各段的VMA地址。4.3 烧录过程中常见的权限问题与udev规则我第一次在WSL里跑上面的命令看到的报错是Error: open failed Failed to open device: LIBUSB_ERROR_ACCESS意思是没有访问USB设备的权限。当时我明明是root执行的为什么还不行后来一查WSL2默认使用普通的USB设备权限模型即使root也需要udev规则或正确的dev节点权限。而且WSL2里系统启动时可能不会加载udev这会导致设备节点可能没有按预期设置权限。解决办法有两个。一个是直接在命令前加sudosudo openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c program app.elf verify reset exit如果OpenOCD是在root下运行大概率能绕过权限问题。但每次都sudo很麻烦而且如果你的交叉编译器、OpenOCD都需要root那CMake设置烧录脚本时也会别扭。我更推荐把当前用户加入dialout组和plugdev组sudo usermod -aG dialout $USER sudo usermod -aG plugdev $USER然后添加一条udev规则让ST-Link设备的权限自动放宽。创建文件/etc/udev/rules.d/99-stlink.rules内容如下SUBSYSTEMusb, ATTR{idVendor}0483, ATTR{idProduct}3748, MODE0666, GROUPplugdev这里0483是ST的USB厂商ID3748是ST-Link的常见产品ID。如果你的板载ST-Link是其他ID可以用lsusb查一下。写完规则后执行sudo udevadm control --reload-rules然后在WSL里重新插拔设备或者用usbipd的detach/attach重新挂载一次再运行openocd就不再需要sudo了。4.4 芯片配置匹配以及Reset Mode引发的烧录失败还有一个高概率翻车点OpenOCD的target配置和芯片型号不匹配。比如你的板子是STM32F103烧录配置里写成stm32f4x.cfgOpenOCD虽然能连上调试器但和芯片握手时就会报识别不到IDCODE的错误。我还遇到过连接不上、一直卡在Error: target not halted的情况排查到最后发现是目标芯片进入了某种模式。这时候的通用解救方法是板子上找到BOOT0引脚拉到高电平让芯片进入系统存储器模式然后重新上电再烧录一次。因为系统存储器模式下的芯片不会跑用户代码也不会设置调试引脚复用调试器比较容易控制。很多板子上BOOT0就是一个小跳线或拨码开关拨到1位置就是高电平。烧录成功后再拨回来复位一下程序就跑起来了。4.5 一个容易让人误判的坑ST-Link固件版本过旧如果你用的是那种条形的ST-Link/V2或者板载ST-Link可能会遇到OpenOCD报错说固件版本太低。以前Windows下用官方烧录工具时它会自动提示升级固件。在WSL下没有那个GUI工具但可以在Windows侧下载ST-Link固件升级工具先在Windows环境里升级一次。升级完再透传到WSLOpenOCD就能正常识别。这个坑特别容易让人误以为是WSL的USB透传失败从而把排查方向搞乱。我自己就浪费了半小时反复detach、attach结果发现是固件版本问题。所以建议一开始就把ST-Link的固件升级到最新减少干扰项。5. 把烧录流程固化到日常开发里脚本、自动化和调试5.1 写一个烧录脚本顺手解决板子又不见了的问题既然烧录命令这么长最好把它封装成脚本。这里提供一个简单的bash脚本放到项目根目录的flash.sh里#!/bin/bash set -e BOARD_CFG${TARGET_CFG:-stm32f1x.cfg} ELF_FILE${1:-build/app.elf} if ! lsusb | grep -q 0483; then echo [ERROR] 没有检测到ST-Link设备请确认USB透传是否成功。 echo 尝试执行: usbipd attach --wsl --busid busid exit 1 fi openocd -f interface/stlink.cfg -f target/${BOARD_CFG} \ -c program ${ELF_FILE} verify reset exit脚本里的if判断很实用每次烧录前先检测lsusb中是否存在ST-Link设备如果不存在就给出提示提醒你执行attach命令。别小看这个判断它能把我板子呢这个灵魂拷问从每天一次变成偶尔几次。配合CMake可以加一个自定义目标add_custom_target(flash COMMAND ${CMAKE_COMMAND} -E env TARGET_CFGstm32f4x.cfg bash ${CMAKE_SOURCE_DIR}/flash.sh $TARGET_FILE:app DEPENDS app )这样执行make flash即可完成编译烧录。5.2 串口监视也必须切到WSL里烧录完程序紧接着要做的事就是看串口输出。如果你的板子通过USB转串口接到电脑透传之后在WSL里会显示为/dev/ttyACM0或/dev/ttyUSB0。直接用cat或者minicomcat /dev/ttyACM0如果提示权限不足同样需要把用户加到dialout组或者用sudo。串口参数要注意默认的波特率通常是115200但cat命令不会设置波特率内核默认使用9600所以用cat直接读可能乱码。建议用stty设置stty -F /dev/ttyACM0 115200 raw -echo cat /dev/ttyACM0也可以安装minicom或者picocom体验更好。这里有一个在WSL下很常见的附加问题如果ST-Link的VCP和调试器是一个复合设备透传时会同时出现两个USB设备你需要选择正确的那个。比如某款探索板板载的ST-Link会枚举出一个ST-Link接口和一个VCP串口接口分别对应不同的busid。attach的时候要选择包含串口的那个否则你在WSL里找不到ttyACM0。5.3 调试器也不落下OpenOCD GDB远程调试烧录只是第一步嵌入式的重头戏其实是调试。OpenOCD本身自带一个GDB服务器烧录完成之后不要退出而是让它继续监听端口。启动命令可以写成openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c program app.elf verify reset halt 注意这里用的是halt而不是exit烧录后会停下来等待GDB连接。然后用另一个终端启动arm-none-eabi-gdbarm-none-eabi-gdb app.elf (gdb) target remote localhost:3333 (gdb) monitor reset halt (gdb) load (gdb) continue这样一来在WSL里也可以获得真正的调试体验单步、断点、查看寄存器都行。如果你前端用编辑器里的remote配置体验还会更好。我现在的习惯是在编辑器里配一个WSL工具链烧录和调试都在WSL里完成Windows端的图形烧录工具基本退役了。5.4 关于USB透传后板子失去响应的那些玄学最后聊几个我实际遇到过、容易让人抓狂的边角问题。一是Windows侧设备管理器里ST-Link设备消失。这其实是bind之后正常现象设备已经被标记为共享Windows上不再显示。如果你发现Windows侧也找不到设备执行usbipd detach --busid BUSID把它释放回来它就会重新出现在Windows上。如果你绑定了设备但忘记attachWindows里也会看不到这不代表设备坏了。二是WSL2里断电重启后要重新attach。如果你用auto-attach可以少一步但Linux内核模块如果没加载usbip attach会报错。此时执行sudo modprobe vhci-hcd将vhci-hcd模块加载上去再attach。WSL2默认模块是有的但偶尔没自动加载。三是烧录大固件时OpenOCD突然卡死。我遇到过几次最后发现是USB线质量太差电流不稳导致ST-Link掉线。这问题无解只能换一根带屏蔽的短线。对了尽量别用电脑前置USB口供电弱的时候烧录到一半失败的概率很大。这些事看起来琐碎但每一个都能让人对着终端发半小时呆。把这条链路理顺之后你会发现用WSL做嵌入式开发是真的舒服编译在Linux侧工具链完全自由烧录调试也能在同一个终端里完成不再需要来回切换Windows软件。我现在坐在工位上开发板安安静静地插在USB口上WSL里的终端已经准备好了。那句我板子呢最近出现的频率越来越低因为脚本和attach别称已经替我记住了所有环节。希望这一篇也能让你在WSL里顺利找到自己的板子。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/19 23:49:55
DeskcommCRM实战:轻量级客户管理与销售跟进全流程落地指南
2026/10/19 23:49:55
以沟通为核心的轻量级CRM系统设计与实践
2026/10/19 23:39:44
Kafka全链路性能调优:吞吐量与延迟的实战权衡
2026/10/20 2:15:36
Redis高级篇---分布式缓存(万字全面解析)
2026/10/20 2:15:36
2、Kubernetes 介绍+安装+卸载
2026/10/20 2:15:36
2026 AI学习路线图:收藏这份系统学习框架,从基础到工程全面提升大模型能力
2026/10/20 2:15:36
如何提高阅读后的知识留存率
2026/10/20 2:15:36
学生成绩管理系统需求分析:表结构、技术栈与避坑指南
2026/10/20 2:10:36
云禾外卖day02-员工管理模块功能完善
2026/10/20 1:05:26
WSL下STM32开发板烧录指南:USB透传与OpenOCD实操
2026/10/20 1:05:26
ROS2工业级开发:实时性、资源适配与可交付验证体系
2026/10/20 1:05:26
STM32+华为云IoT+Qt构建智能家居远程控制系统全解析
2026/10/19 14:00:16
OpenResearch实战:Claude Code、Codex、OpenCode、Cursor 工作流搭建与故障排查
2026/10/19 2:04:59
知识管理核弹:用Obsidian构建第二大脑的工程化方案(TaoToken 统一 Key 接入版)
2026/10/19 15:41:50
金融AI落地指南:从调研报告到技术选型与工程实践
2026/10/17 10:15:50
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/16 18:46:48
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/16 18:46:46
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)