前两天刚把手上的PY32F002B项目从Keil整套流程迁移到了VS Code EIDE中间折腾了差不多一个晚上踩了不少坑。这颗芯片本身就是走极致性价比路线的官方SDK和工具链支持远不如ST那么顺滑网上资料也少如果不摸清套路光是把环境跑通就能劝退不少人。这篇文章就把我实际验证过的流程完整写出来从EIDE工程创建、编译到DAPLink烧录再到SVD文件定位和调试器连接一步不落。如果你正准备用PY32F002B做低成本方案又不想继续被Keil的工程管理折磨这篇踩坑实录应该能帮你省下不少时间。1. 为什么我选择VS Code EIDE做PY32F002B开发1.1 先聊这颗芯片便宜是有代价的PY32F002B是普冉推出的一颗Cortex-M0内核MCU官方标称Flash 20KB、SRAM 3KB最高主频24MHz封装从SOP8到TSSOP20都有。价格低到离谱很多场景下比一颗运放还便宜做传感器采集、小家电控制、简单IO控制简直是一把好手。但便宜必然伴随工具链生态不完善。最典型的现象就是你去Keil官网或者芯片官网找资料会发现固件库、Pack、示例工程都存在但版本混乱目录结构各版本都不一样。我甚至遇到过官方SDK里例程用的中文注释编码不对Keil直接乱码的问题。更麻烦的是PY32F002B不支持ST-Link那种一键烧录的官方工具链最稳妥的方式是DAPLink走SWD接口。这种小芯片的开发思路跟STM32不太一样。它内部没有外部高速晶振主要靠HSI内部RC提供24MHz主频。所以写代码的时候SystemInit和时钟树配置要特别小心。很多人拿到手直接用STM32F0的启动文件结果SystemCoreClock算错了串口波特率差得一塌糊涂。这个后面细说。1.2 EIDE凭什么能替代KeilEIDE全称Embeded IDE是VS Code下一个嵌入式开发插件核心思路是把Keil那套“工程管理编译下载调试”体验搬进VS Code。它支持GCC ARM、ARM Compiler 5/6、IAR等多套工具链也能配置OpenOCD、PyOCD等调试服务器项目文件全部是明文JSONGit管理非常友好。我用Keil用了很多年但这两年越来越难受。Keil的工程文件是个二进制uvprojx多人协作时几乎没法做代码审查而且老版本对ARM Compiler 6的C99/C11支持总是慢半拍语法检查也弱。EIDE把工程配置和代码分开.eide.json里能看到所有源文件、宏定义、头文件路径改了哪里一目了然。EIDE也不是没有坑。它把Keil那套“分组”逻辑搬过来之后新手经常搞不明白源文件组和文件夹的关系。实际上源文件组只是逻辑上的集合跟磁盘目录完全可以不一致。我习惯按Core、Drivers、Startup建三个组对应不同的功能模块编译顺序靠组内文件顺序控制启动文件必须放在第一个否则链接顺序不对会出一些诡异的undefined reference问题。还有个细节EIDE对国产芯片的默认支持一般PY32F002B这种芯片型号不一定在它的芯片数据库里。我一开始新建工程的时候搜PY32F002B怎么都搜不到后来才发现EIDE的芯片选择列表里是依赖芯片厂商Pack或者CMSIS Device Family Pack的没有对应Pack就只能选通用Cortex-M0内核后面需要手动补启动文件和链接脚本。知道这个逻辑后反而觉得更顺手了因为我可以完全控制工程的每一个环节。2. 建工程之前VS Code环境与DAPLink接线一次到位2.1 VS Code及相关插件安装VS Code的安装没什么好说的官网下载User Installer版本按默认路径装就行。需要注意两点一是路径里最好不要有中文否则后面某些插件和工具链会出现奇怪的问题二是建议在设置里关闭“自动更新”里的扩展自动更新避免EIDE或Cortex-Debug突然升级导致配置失效。推荐安装的插件有四个EIDE插件IDembeddedide.embedded-ide负责工程管理和编译Cortex-Debug插件IDmarus25.cortex-debug负责调试会话和SVD文件解析C/C插件IDms-vscode.cpptools提供基础代码提示和调试符号支持Clangd可选如果你喜欢更快的代码跳转和补全可以用它替代C/C插件的IntelliSense这里有个容易踩的坑C/C插件和Clangd同时启用时会出现两条代码提示引擎互相打架的情况最常见的是.cpp和.h文件里到处是红色波浪线但编译又不出错。解决办法也很简单在项目根目录的.vscode/settings.json里加一行C_Cpp.intelliSenseEngine: disabled把语法提示交给Clangd。同时需要让EIDE生成compile_commands.json给Clangd用在EIDE的工程选项里有个“导出编译数据库”按钮点一下就行。2.2 arm-none-eabi-gcc与OpenOCD的准备工具链是EIDE最核心的依赖。我使用的是arm-none-eabi-gcc 10.3版本注意不要用太老的9.x因为新版本对Cortex-M0的浮点库和C11语法支持更好。安装完成后把bin目录加到系统PATH里验证方式是在终端执行arm-none-eabi-gcc --version输出正常即可。调试服务器方面OpenOCD和PyOCD我都测过。OpenOCD的好处是资料多、参数灵活坏处是它没有对PY32F002B的官方target配置只能用cortex_m或者stm32f0x这类兼容配置去连。PyOCD则可以通过加载官方Pack识别芯片更容易做到开箱即用不过第一次启动时要指定pack路径。如果你用的是DAPLink建议先装一个Zadig确认驱动没问题。DAPLink在Windows上通常被识别成HID设备不需要额外驱动。如果设备管理器里显示的是未知设备大概率是DAPLink固件问题换一个DAPLink或者重新烧录固件再说。2.3 DAPLink接线与目标板要点PY32F002B的SWD接口就是标准的SWDIO和SWCLK外加GND和3V3。我用的DAPLink是市面上常见的蓝色小板接线方式是DAPLink的3V3接目标板VDDDAPLink的GND接目标板GNDDAPLink的SWDIO接目标板SWDIODAPLink的SWCLK接目标板SWCLKDAPLink的RESET接目标板NRST这个强烈建议接上有人会问RESET不接行不行不接通常也能烧录但调试时如果固件把复位引脚或者SWD引脚复用成了普通GPIO连不上调试器的概率会大大增加。我把RESET接上之后OpenOCD挂死、DAPLink无法连接等问题少了很多。还有一个容易忽略的硬件坑PY32F002B的VDD脚旁边一定要放104电容离单片机越近越好。有次我焊的板子VDD电容放得远导致芯片上电瞬间电压跌落DAPLink反复连不上最后用示波器才发现是电源纹波的问题。3. EIDE工程配置从空工程到编译通过3.1 新建工程与芯片选择的坑打开EIDE后点击“创建新项目”选择“空项目”。接下来它会让你选芯片厂商和型号这里就是大部分人第一次卡住的地方。PY32F002B不在默认列表里因为它不是ST、NXP这种EIDE内置了Device Database的大厂。解决方法有两个方向。一是先不管芯片型号选一个通用Cortex-M0内核的空工程后面自己补启动文件、链接脚本和外设库。二是去下载普冉的Keil PackPuya.PY32F0xx_DFP用EIDE的“SDK管理器”导入这个Pack导入后芯片列表里就能看到PY32F002B了。我推荐第二种方式因为Pack里不光有芯片型号还带了SVD文件、Flash算法、器件头文件省得后续到处找。安装Pack时放到一个纯英文路径下比如D:\PuyaPack否则打开SVD文件时路径解析会有问题。新建工程完成后EIDE会生成一个基础目录结构一般包含.eide、.vscode和build目录。此时先别急着写代码把工程名和输出目录检查一下默认的输出目录是build/Output后面调试配置会用到这个路径。3.2 内部启动文件和固件库的摆放PY32F002B启动文件在官方SDK里一般是startup_py32f002b.s注意版本要跟编译器匹配。EIDE里用GCC工具链的话一定要放GCC版本的启动文件直接拿Keil的ARMCC启动文件过来编译会报一堆指令不支持的错。启动文件之外还需要从SDK里拷贝的系统文件有system_py32f0xx.c和对应的头文件器件头文件py32f002b.h、py32f0xx.h如果你用标准外设库把py32f0xx_gpio.c、py32f0xx_usart.c这些拷过来core_cm0plus.h和core_cmFunc.h、core_cm0plus.h的CMSIS核心文件在EIDE里添加文件时要注意启动文件要放在源文件组的最前面。EIDE界面里的源文件组可以上下拖动顺序我刚用的时候没注意把启动文件放到了最后结果编译链接时报警告程序跳转地址乱成一团查了大半天。3.3 链接脚本、宏定义、头文件路径三件套空工程不会自动生成符合PY32F002B资源的链接脚本因为EIDE默认按它内置的那套Flash/RAM分配来写。右键工程选择“链接器配置”手动修改两个关键参数ROM起始地址0x08000000大小0x5000对应20KB FlashRAM起始地址0x20000000大小0xC00对应3KB SRAM这两个参数是很多问题的根源。有人把Flash大小写成0x8000也就是32KB链接器不会立刻报错因为当前代码量可能不到20KB。但当代码膨胀到超20KB后烧录进去的程序会莫名其妙的跑飞因为实际Flash写不进去。RAM同理3KB非常紧张栈和堆分配要抠着来我一般栈给0x200堆给0x100。宏定义方面需要在EIDE的“预定义宏”里加上USE_STDPERIPH_DRIVER如果使用标准外设库HSE_VALUE24000000U用于时钟计算SYSCLK_FREQ_24MHz部分SDK需要这个宏来选择系统主频头文件路径最容易漏的是CMSIS核心目录。EIDE默认添加的是工程自己的Inc目录但你不是把CMSIS核心文件放在工程目录里的话编译器会报core_cm0plus.h: No such file or directory。把CMSIS Device目录和Include目录都加到头文件路径列表里。3.4 点灯代码快速验证编译链路配置完这些之后我习惯先写一个最简点灯程序验证编译链路是否通了。PY32F002B的GPIO控制很简单以PA0为例#include py32f0xx.h void delay(void) { volatile uint32_t i; for (i 0; i 100000; i); } int main(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin GPIO_PIN_0; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); while (1) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0); delay(); } }如果用的是标准外设库而不是HAL库把__HAL_RCC_GPIOA_CLK_ENABLE()换成RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)即可接口风格和STM32F0很接近。编译时我把优化等级设为-Og这是GCC调试优化级别既保留调试信息又不会让代码膨胀太多。调试用的变量如果发现被优化掉了再临时改成-O0不过3KB RAM的芯片跑O0代码体积会大不少正式版记得切回-Og或-Os。4. 用EIDE完成烧录OpenOCD/PyOCD的选择与实测4.1 EIDE烧录器配置流程在EIDE的工程管理树里找到“烧录器”或者“调试器”配置项。EIDE支持的烧录器类型很丰富DAPLink对应的是CMSIS-DAP协议选择DAPLink即可。烧录器配置里最重要的几个选项服务器类型选OpenOCD或者PyOCD目标芯片如果前面导入了Pack这里可以直接选PY32F002B没有Pack的话选一个Cortex-M0内核的兼容目标烧录算法EIDE会根据芯片自动选择Flash算法但如果没有识别出来需要手动选择或者指定EIDE的烧录按钮在工程树的工具栏上点击后会先编译再下载。如果下载失败它会弹出日志面板把OpenOCD或PyOCD的详细输出打印出来一定要养成看日志的习惯很多问题日志里已经写得很清楚了。4.2 OpenOCD连接PY32F002B的实测参数OpenOCD本身没有PY32F002B的target配置实际使用时我用的是STM32F0的兼容配置。在EIDE的调试服务器参数里填写-f interface/cmsis-dap.cfg -f target/stm32f0x.cfg然后显式指定SWD模式-c transport select swd这套组合我实测能正常连接PY32F002B的内核读取IDCODE也正常烧录也能完成。但要注意STM32F0的Flash编程算法是给STM32F0用的烧录PY32F002B时如果Flash的页大小、扇区布局跟STM32F0不完全一致有可能出现“校验失败”或者“烧录地址错误”。遇到这种情况OpenOCD的日志会提示error writing to flash at address...这时候不要硬试改用官方烧录工具或者PyOCD加载Pack的方式。另一个更稳妥的做法是切换到PyOCD。PyOCD支持通过--pack参数加载厂商Pack加载后就能正确识别PY32F002B的Flash和SVD信息。实测命令行如下pyocd flash -t py32f002b -p build/output/demo.hex --pack D:\PuyaPack\Puya.PY32F0xx_DFP.1.0.3.pack第一次用PyOCD还是建议先把DAPLink接好然后执行pyocd list看看能不能枚举到目标设备。枚举不到的原因多半是驱动或者接线问题先解决硬件再谈烧录。4.3 烧录失败的几种典型场景我烧录过程中遇到过的坑可以列一下DAPLink未被识别设备管理器里看到的是未知USB设备重新插拔或者换USB线有些USB线的数据线是断的只供电不传数据连接失败提示找不到swd deviceSWDIO和SWCLK两根线接反了或者目标板上电太晚DAPLink先供电导致芯片没起来烧录到一半卡死Flash算法不对此时OpenOCD日志一般会卡在Running FLASHBANK那行换PyOCD或者换Pack版本烧录成功但程序不运行检查BOOT0引脚PY32F002B部分封装没有独立BOOT0但如果有必须拉低到GND另外确认启动文件的栈指针初值是否正确烧录这件事说白了就是硬件、工具、配置三者共同作用。硬件优先排查再查工具输出日志最后才怀疑配置顺序不要反。5. 调试配置SVD文件到底去哪找又怎么填5.1 SVD文件是干什么的SVD文件全称System View Description是ARM的CMSIS-SVD规范定义的一种XML格式文件用来描述MCU内部外设寄存器的名字、地址、位域含义、复位值等信息。调试器加载SVD文件后就能在调试界面里图形化地查看和修改外设寄存器不用再对着数据手册手算寄存器地址。SVD文件对嵌入式调试的提升是质变的。没有它你要看USART1的SR寄存器状态只能通过Watch窗口输入USART1-SR或者直接看内存地址有了它调试器左侧外设树里直接展开USART1每个寄存器的每一位都清清楚楚置位和复位状态一眼就能看出来。PY32F002B的调试配置里SVD文件不是可选项而是强烈建议必选项。这颗芯片的参考手册写得比较简略寄存器位域描述也分散靠人肉记忆或者反复翻PDF效率极低。5.2 官方SDK与Keil Pack中的SVD路径SVD文件藏在官方SDK或者Pack包里。几个常见位置Keil Pack安装目录下C:\Keil_v5\ARM\PACK\Puya\PY32F0xx_DFP\版本号\SVD\py32f002b.svd官方SDK解压后PY32F0xx_Firmware_Library\CMSIS\Device\PY32F0xx\SVD\部分SDK版本里会放在Utilities\SVD\目录推荐优先从Pack里找因为Pack发布的SVD版本通常和芯片批次匹配度更高。打开Keil Pack目录看SVD文件时注意文件名可能是PY32F002B.svd全大写也可能是小写py32f002b.svd这取决于Pack版本的命名规范不影响使用。如果你用的是我前面说的PyOCD加载Pack方式还有一个更省事的办法Pack里自带的SVD文件会被PyOCD自动识别配合Cortex-Debug时甚至可以不用手动填svdFile字段Cortex-Debug会自动从PyOCD获取外设信息。不过手动指定路径仍然是最稳妥的做法因为自动识别偶尔会因为版本匹配问题失效。这里分享一个小技巧下载Everything这个文件搜索工具全盘搜*.svd几秒钟就能找到目标SVD文件。不用在文件夹里一层层翻。5.3 launch.json与EIDE调试配置调试配置有两种路径。如果用的是EIDE自带的调试按钮可以在EIDE的调试配置里填DAPLink和OpenOCD参数EIDE会自己生成调试会话。但如果你同时装了Cortex-Debug我建议直接在.vscode/launch.json里手动写一份灵活度和可控性高很多。参考配置如下{ version: 0.2.0, configurations: [ { name: PY32F002B DAP Debug, cwd: ${workspaceFolder}, executable: ${workspaceFolder}/build/Output/PY32F002B_Demo.elf, request: launch, type: cortex-debug, servertype: openocd, device: PY32F002B, interface: swd, gdbPath: arm-none-eabi-gdb, svdFile: ${workspaceFolder}/svd/PY32F002B.svd, runToEntryPoint: main, configFiles: [ interface/cmsis-dap.cfg, target/stm32f0x.cfg ], serverArgs: [-c, transport select swd] } ] }有几个字段特别容易出错executable指向的是GCC编译产出的ELF文件不是hex。ELF文件里才包含调试符号hex是纯机器码没有符号信息svdFile路径建议用${workspaceFolder}变量拼接不要用绝对路径否则别人克隆项目后还要改runToEntryPoint设置为main调试启动时会自动停在main函数入口省得每次手动打断点gdbPath如果没加到系统PATH里这里必须填完整路径我习惯在工程根目录建一个svd文件夹专门放SVD文件。这个目录建议放进Git仓库因为SVD文件属于开发依赖团队成员调试时都需要。5.4 外设寄存器窗口打不开的排查调试会话启动后如果左侧“外设寄存器”面板是空的或者提示No SVD file loaded基本可以断定是SVD路径配置问题。首先检查svdFile路径是否真实有效最简单的方法是在VSCode里打开这个文件看XML能否正常解析。然后检查路径里的盘符和文件夹名大小写Windows下大小写不敏感但Mac和Linux下敏感如果团队环境混杂建议统一用小写英文路径。如果路径没问题但外设寄存器还是空白试试删掉.vscode目录下的调试缓存文件然后重新启动调试会话。Cortex-Debug和EIDE同时存在时EIDE生成的调试配置会干扰Cortex-Debug读取SVD把EIDE的调试按钮停用只用launch.json即可。还有一个容易被忽略的点调试器连接芯片后第一次读取外设寄存器是从芯片内存中扫描的。如果芯片还在复位状态或者内核停住了SVD面板可能显示不出来。在调试工具栏点击“继续”“暂停”交替一下强制内核刷新寄存器状态面板一般就出来了。6. 调试实战与踩坑避雷手册6.1 从点灯到串口打印的联调过程调试会话能正常启动了我建议先跑一次点灯程序验证调试链路和烧录链路都是通的。把断点打在HAL_GPIO_TogglePin这一行单步执行时观察GPIOA的ODR寄存器变化SVD面板里GPIOA - ODR的bit0会在0和1之间翻转。这一步能确认两件事代码确实跑起来了SVD解析也确实生效了。点灯没问题后再上串口打印。PY32F002B的USART1默认引脚一般是PA2作为TX、PA3作为RX具体以数据手册的AF映射表为准。初始化代码大致是void USART1_Init(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStruct {0}; USART_InitTypeDef USART_InitStruct {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_USART1_CLK_ENABLE(); GPIO_InitStruct.Pin GPIO_PIN_2 | GPIO_PIN_3; GPIO_InitStruct.Mode GPIO_MODE_AF_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate GPIO_AF1_USART1; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); USART_InitStruct.BaudRate baudrate; USART_InitStruct.WordLength USART_WORDLENGTH_8B; USART_InitStruct.StopBits USART_STOPBITS_1; USART_InitStruct.Parity USART_PARITY_NONE; USART_InitStruct.Mode USART_MODE_TX_RX; HAL_UART_Init(huart1); }这时候我通常会同时开着串口调试助手一边观察串口输出一边在VS Code里断点暂停。比如串口发出数据到一半时暂停调试串口助手里会突然停住继续运行后接着输出这能直观判断程序卡在哪个环节比纯看日志高效得多。串口乱码的问题多半出在波特率上。PY32F002B的USART时钟源要跟着SYSCLK走如果HSE_VALUE宏定义和实际主频对不上波特率计算就偏了。24MHz主频下9600、115200这些常用波特率都能整数分频出来别用奇怪的非标准波特率。6.2 结构体变量显示与监控模式调试时看结构体变量VS Code的Variables面板比Keil的Watch窗口更直观。局部结构体、全局结构体都可以直接在变量树里展开成员变量一目了然。很多从Keil转过来的朋友会疑惑为什么Keil Watch窗口里展开得好好的结构体到VS Code里就显示不出来大概率是编译优化的问题。GCC在O2优化级别下会把结构体成员优化到寄存器里调试信息和实际寄存器映射对不上所以调试会话里看不到完整的结构体。解决办法是在调试版强制使用-Og或-O0优化级别。另外如果结构体变量被定义在一个没有实际被调用的函数里链接器可能直接把这个变量优化没了调试器当然找不到。类似Keil的Watch窗口VS Code的Watch面板可以输入任意C表达式比如直接输huart1.Instance-BRR调试器会实时计算出这个表达式并显示。表达式后面还可以加格式化修饰符比如/x表示十六进制显示。这个功能多练练调试效率会高很多。热词里提到的“监控模式”本质就是调试器的实时变量刷新。在VS Code的Watch面板里右键一个已添加的表达式选择“Enable Real-Time Watch”或者“自动刷新”调试器会在程序暂停变化时更新该表达式的值。如果你用的是较新版本的Cortex-Debug这个选项可能在“调试控制台”面板里调整为monitor命令触发。6.3 高频问题排查速查表我把这段时间遇到的高频问题整理成一张速查表方便遇到问题时直接对照排查。现象可能原因解决办法编译报错找不到core_cm0plus.hCMSIS路径未添加在EIDE头文件路径里添加CMSIS核心目录链接提示section .text will not fitFlash大小配置错误检查链接器ROM大小PY32F002B为0x5000链接提示region RAM overflowSRAM超限压缩栈空间、减少全局变量或检查堆栈大小配置OpenOCD连不上目标DAPLink接线或供电问题先确认目标板供电再查SWDIO/SWCLK是否接反尝试降低SWD频率到2MHzPyOCD提示unknown target缺少Pack或目标名错误使用pyocd list --targets查看支持的目标指定Pack加载烧录校验失败Flash算法不匹配改用PyOCD加载官方Pack或用官方烧录器程序烧录后不运行启动文件选错或BOOT脚配置不对确认使用GCC版本启动文件BOOT0拉低调试时变量被优化掉编译优化级别太高调试用-Og或-O0确认变量未被丢弃外设寄存器窗口空白SVD路径错误或未加载检查launch.json的svdFile字段重新启动调试会话串口输出乱码主频宏定义错误确认HSE_VALUE和SYSCLK一致SYSCLK应为24MHzKeil下能烧录但EIDE里不能工具链配置不一致检查EIDE里的烧录器型号和接口协议是否匹配实际DAPLink这张表只能覆盖常见部分真正遇到问题还是要学会看日志。OpenOCD和PyOCD输出日志的详细级别都很高Info :、Error :、Debug :三档信息都能在调试控制台里看到。6.4 几个容易忽略的细节PY32F002B的3KB SRAM真的是捉襟见肘。不要只是盯着代码量还要注意函数调用栈的深度。我踩过的一个坑是在中断服务函数里调用了printf而printf的缓冲区申请塞在栈里直接导致栈溢出程序跑了几秒后随机死机。这种问题最难查因为完全随机而且Keil里跑得好好的换到GCC工具链后栈布局变了就暴露了。解决办法有两个方向。一是给printf的缓冲区改成静态内存不要用栈空间二是把调试信息改成用ITM_SendChar一类的单字符输出完全不依赖缓冲区。对小RAM芯片来说后一种方案更可靠。另外一个细节是中断向量表。PY32F002B的向量表默认放在0x08000000开头如果你用Bootloader方案把应用放在别的地址需要正确设置VTOR或者启动文件里的向量表偏移。3KB RAM的芯片想跑Bootloader很吃紧但如果做OTA还是得提前规划好地址分配。还有ADC校准的问题。PY32F002B的ADC在芯片出厂时会有校准系数存放在特定的地址或寄存器里。有些SDK示例代码里没有调用ADC校准函数导致ADC采样偏差比较大。如果你的应用要用ADC测电压记得从数据手册或参考手册里找到校准值在初始化时加载进去。7. 一些个人体会和实用建议整套流程走通之后我最大的感受是PY32F002B本身不难难的是工具链的碎片化。官方SDK版本多、目录乱网上教程又大多是Keil的想用VS Code就得把整个流程自己串起来。如果让我给后来者一个建议那就是先在Keil或者官方示例里跑通一个最简程序确认芯片本身没问题再迁到VS Code EIDE上。这样当EIDE出现问题时可以快速判断是工具链问题还是硬件问题。直接上手VS Code环境遇到问题容易两头怀疑排查效率很低。工具链选择上我最终是OpenOCD DAPLink Cortex-Debug的组合工作稳定PyOCD作为Plan B遇到OpenOCD搞不定的情况时切换过去。SVD文件一定要放到工程目录里管起来这是很多人容易忽略的一步却是调试体验的关键一环。最后分享一个小技巧把EIDE工程里生成的.eide文件夹、.vscode文件夹全部提交到Git仓库别的同事直接clone下来就能编译调试不需要任何额外配置。这条经验来自一次团队协作当时同事电脑上装的是老版本GCC死活编不过后来统一了工具链版本号才解决。工具链版本建议也写进README里省得后人再踩一遍同样的坑。
