STM32F103+FreeRTOS上电无反应?先别怀疑芯片,排查这些坑

发布时间:2026/9/5 1:47:20
STM32F103+FreeRTOS上电无反应?先别怀疑芯片,排查这些坑 01. 先别急着骂芯片这颗旧料八成是“背锅侠”玩STM32F103的老人基本都有过这种经历板子打样回来程序下载完按一下复位灯不亮、串口没反应、FreeRTOS的任务调度器就像死机一样卡住——第一反应就是“卧槽买到假芯片了”。然后开始翻淘宝记录、查防伪码、拍照找卖家理论。结果折腾一圈下来发现芯片是正品是你自己的电路和工程配置在作妖。STM32F103这颗芯片在市面上流通了十几年确实存在打磨片、翻新片、刻字片但说实话真正“上电全无反应”的情况绝大多数不是芯片本身挂了而是你给了它一个没法正常启动的环境。尤其是当你把FreeRTOS引入工程之后问题更容易被放大了原本裸机点亮LED跑得挺顺一上RTOS就“卡死”这时候很多人第一反应是系统移植错了但其实芯片的底层状态可能从一开始就不对。这篇文章就围绕“STM32F103 FreeRTOS 上电无反应”这件事把最常见的坑点完整捋一遍。从硬件最小系统到启动配置从下载器连接到FreeRTOS移植全部覆盖适合正在做入门项目、毕业设计、或者用F103做量产产品的开发者参考。02. 最小系统都没搭对芯片凭什么给你反应2.1 电源不只是“接上3.3V”这么简单先说最简单也是最容易翻车的一环电源。STM32F103的供电设计要求不算苛刻但也不是随便拿个LDO焊上去就能稳定跑的。VDD与VDDA主电源和模拟电源引脚都要接且不建议用一根细跳线串联。VDDA上建议串一个10Ω左右的磁珠或电阻再并一个1μF电容就近接到地。如果VDDA悬空或者纹波过大ADC可能不准严重的会导致芯片复位异常。VREF引脚如果你的封装是LQFP100或者LQFP144VREF必须接3.3VVREF-接地。部分国产替代芯片对VREF的要求更苛刻空着不走会直接导致启动异常。去耦电容的布局每个VDD引脚旁边放一个100nF陶瓷电容这是ST官方手册的基本要求但很多人只会铺一个。芯片在FreeRTOS启动时会有多任务同时切换的瞬间大电流如果去耦电容离引脚太远寄生电感会让芯片内部电压瞬间跌落跑裸机还好上RTOS之后莫名其妙HardFault、或者卡在启动阶段完全无输出很大概率就是这个原因。电源这块我的测试习惯是上电之后先量一下芯片VDD引脚电压要求3.3V ± 5%以内且用示波器看纹波不超过50mV。如果万用表量出来是3.28V左右大概率没问题但如果是2.8V甚至更低就不要急着怀疑芯片假先检查你的电源模组。2.2 BOOT引脚的电平状态决定你按下复位后往哪跑STM32F103的上电启动模式引脚是BOOT0和BOOT1这两个引脚的组合决定了芯片从哪段存储区启动BOOT0BOOT1启动区域0X从Flash启动正常模式10从系统存储器启动出厂Bootloader11从内置SRAM启动调试模式大部分用户画板子的习惯是在BOOT0上接一个10k下拉电阻到地BOOT1随便悬空或者接一个下拉。这个配置在90%的情况下是没问题的但如果你使用的是自制最小系统板或者从某个小厂买的开发板BOOT0可能默认被拉高。此时芯片上电后直接从系统存储区启动你的应用程序代码完全不会执行表现出来就是串口没打印、LED没翻转、FreeRTOS毫无动静就跟没烧程序一样。排查方法很简单用万用表量一下BOOT0引脚电压。如果上电后量出来是高电平先用镊子把BOOT0短接到地按一下复位如果芯片正常跑起来了说明硬件没问题是BOOT0的上下拉配置不对。还有一个经验BOOT0尽量不要用飞线或跳线帽去控制。量产环境下跳线帽松脱会造成一批板子“间歇性无反应”这种故障非常难排查而且很多人会把这锅甩给“芯片批次不好”。2.3 复位电路RC延时不够上电瞬间就是“薛定谔的复位”STM32F103的NRST引脚内部有一个约40kΩ的上拉电阻不同批次略有差异官方推荐外接一个100nF的电容到地形成RC延时复位电路。时间常数大概是τ R × C40kΩ × 100nF 4ms芯片内部的POR上电复位电路还需要一些时间才能完成所以整个复位周期一般在几十毫秒以内。这个电路几乎所有开发板上都有但问题往往出现在这几个细节上电容漏装或者贴错有些SMT代工厂会用0.1μF的电容贴到复位位置理论上没问题但如果漏贴芯片上电瞬间NRST引脚被内部上拉拉到高电平复位时序不对偶尔会导致启动失败。外部复位芯片不兼容如果设计里加了复位监控芯片如MAX809、CAT809等它的复位输出是推挽结构的低电平脉冲与STM32内部的上拉电阻配合没问题但有些复位芯片比如带看门狗的复位输出是开漏结构需要外部加一个上拉电阻否则NRST在释放后可能一直处于不确定状态。2.4 时钟源外部晶振不起振FreeRTOS调度器等于没有脉搏STM32F103内部有一个HSI高速内部时钟频率是8MHz经过PLL倍频后最高可以跑到72MHz。如果外部晶振没接或者没起振芯片用内部HSI也能运行。但问题在于很多人建工程时用的SystemInit函数或者库函数默认配置是“优先外部晶振HSE”如果HSE一直检测不到系统就会卡在等待HSE就绪的循环里出不来了。FreeRTOS比裸机更依赖稳定的时基。裸机上如果HSE没起振可能还能用HSI跑起来闪个灯整体时序是乱的但至少“有反应”。FreeRTOS移植时如果使用了SysTick作为时基SysTick的时钟源不管用HSE还是HSI都能配但调度器的执行节拍要求极高的确定性。如果你外部晶振偶尔能起振、偶尔不起振虚焊、电容不匹配、负载电容太大表现出来就是十次上电有两三次没反应剩下的时候FreeRTOS跑得又很正常。排查时钟问题的办法用示波器直接量OSC_IN引脚看有没有正弦波实际上是近似正弦波或削顶正弦。或者更简单写一个10行的裸机程序初始化HSE并尝试切换系统时钟如果切换失败点亮一个故障LED。如果量出来是幅度极小的噪声而不是稳定的波形那就是晶振没起振。常见的处理是把外部晶振的两个负载电容通常是18pF或20pF拆掉或者换成8pF左右再试。我自己遇到过一批板子晶振焊盘底下刚好有地过孔过孔离焊盘太近产生寄生电容导致晶振停振概率30%温度越高越明显。这种问题在180块钱打样的快速原型上很难避免但因为“芯片没反应”的故障表现太像芯片坏了往往要排查很久才能绕回来。03. 不是芯片假是你的FreeRTOS工程压根没“烧进去”3.1 下载器连不上芯片和芯片坏了是两码事很多人的“芯片没反应”实际从下载这一步就开始了点击Keil的Download按钮弹出“Cannot connect to target”或者“RDDI-DAP Error”。这时候第一反应又是“芯片坏了”。但下载连不上原因非常多样而且90%跟芯片损坏无关SWDIO和SWCLK接反别笑这个错误非常常见。SWDIO是数据线SWCLK是时钟线两者对调后下载器根本识别不到内核。GND没有连接或者接触不良SWD调试要求调试器与目标板共地。如果只用杜邦线连了信号线没连GND会导致复位和时序信号完全乱掉。目标板供电不足如果ST-Link直接给板子供电而板子的负载偏大例如接了摄录模块、显示屏背光ST-Link的3.3V输出能力只有100mA级别电压被拉低到2.5V以下SWD协议直接失效。芯片被读保护锁死如果你的芯片之前烧录过开启了RDP读保护级别1的固件SWD口只能做全擦除级别的操作普通连接会被拒绝。此时用STM32CubeProgrammer选择“Under reset”模式连接可以强制恢复。所以我建议遇到“芯片没反应”第一步别急着拆芯片先把下载器断开只用USB转TTL连PA9、PA10USART1看芯片有没有任何Bootloader的回应——比如你按住BOOT0为高然后复位这时候芯片进入ROM Bootloader在某些波特率下会主动回应0x7F。如果BOOTROM都有回应说明芯片内核和存储都活着硬件基本没坏。3.2 新芯片首次烧录Flash烧写算法不对假芯片案发现场新打样回来的芯片第一次烧录失败最常见的原因是Flash编程算法Flash Algorithm没有配置正确。Keil MDK默认情况下会自动选择匹配器件的Flash算法但如果你在工程设置中手动点了或换了器件型号比如从F103C8T6 64KB改到F103RCT6 256KB但没改Flash算法烧录时就会报错。还有一种情况你用的是国产替代芯片比如GD32F103、APM32F103它们的Flash烧写时序与ST原厂芯片不是100%兼容。用ST-Link配合Keil的ST芯片Flash算法去烧录GD32芯片有一定概率烧写中途报错或者烧完之后能连上但运行几分钟后程序丢失。处理方法是去对应厂商官网下载专用的Flash算法文件或者先用官方烧录工具如GD32提供的GigaDevice MCU ISP Programmer完成第一轮烧写。提醒如果没有特殊需求做STM32F103的FreeRTOS项目时强烈建议首次烧录用SWD方式连接并勾选Keil中Flash Download选项卡里的“Reset and Run”选项。这样烧完立刻运行能第一时间看到程序是否正常工作避免“烧录完成后拔掉下载器再上电才发现没反应”的重复返工。3.3 PA8、PA9、PA10这些“调错了就没输出”的引脚有一个很容易被忽略的坑F103系列很多引脚的默认复用功能不是你想的那个。比如PA8很多人直接当普通GPIO用推挽输出驱动一个LED但PA8同时也是TIM1_CH1和MCO主时钟输出引脚。如果你的工程初始化里某段代码把PA8配置为AFIO重映射它可能先输出MCO时钟信号而MCO输出电平在你配置前是不确定的。你用示波器量PA8看到不是正常的高低电平翻转而是一堆几MHz的方波就以为“引脚坏了”、“芯片是假货”。PA9和PA10是USART1的TX和RX引脚。如果你在FreeRTOS里创建了一个串口打印任务但GPIO模式配错了比如把PA9配置成开漏输出且没有接外部上拉那串口的IDLE电平是高阻态用USB转TTL看什么数据都收不到。这些引脚的坑并不是芯片的问题而是你对STM32的引脚复用功能表不够熟。遇到引脚无输出先打开STM32F103中文参考手册或者数据手册查引脚定义附表确认有没有复用功能冲突再确认GPIO配置是否匹配。这是排查“假芯片”最基础的动作。04. FreeRTOS工程实践从裸机切到多任务哪些配置最容易让芯片“装死”4.1 堆与栈FreeRTOS任务栈溢出会让调度器静默崩溃从裸机切到FreeRTOS最大的变化是内存管理。裸机时你用的是系统栈由启动文件里定义的Stack_Size决定。FreeRTOS跑起来之后每个任务都有自己独立的栈空间系统栈只给中断服务函数ISR和特权模式使用。如果任务栈分配不够比如你在任务里定义了一个512字节的局部数组但任务栈只给了256字节运行时会直接踩踏任务控制块TCB。FreeRTOS在configASSERT开启的情况下会捕获部分溢出但很多入门工程根本没有开configASSERT于是表现就是系统偶尔工作正常偶尔一运行到某个函数就“卡死”或者看门狗超时复位。从裸机转FreeRTOS时我的建议是STEP BY STEP来先不要把所有外设逻辑搬进去只创建一个最简单的LED翻转任务验证调度器能正常跑。使用vTaskList()或者uxTaskGetStackHighWaterMark()检查每个任务的栈余量栈余量低于20%就要调大。开启FreeRTOS的堆栈溢出检测功能configCHECK_FOR_STACK_OVERFLOW设为1或2并实现vApplicationStackOverflowHook()回调。4.2 中断优先级分组FreeRTOS在Cortex-M3上最狠的陷阱在树莓派、ESP32这类平台上写FreeRTOS中断优先级的概念很模糊。但在STM32F103上中断优先级和前导分组配置出错会让FreeRTOS直接跑不起来。Cortex-M3内核支持最多8位中断优先级但STM32F103只使用了其中4位高4位有效。FreeRTOS的端口层代码要求你调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)把它设为4位全部作为抢占优先级、0位子优先级。如果你在裸机代码或者外设初始化里调用了NVIC_PriorityGroup_2FreeRTOS的临界区保护就会失效。临界区失效的后果非常隐蔽两个任务同时访问共享外设比如串口发送缓冲区时数据被冲掉调度器在关中断失败的瞬间被高优先级中断抢占导致上下文切换不完整系统在运行几秒到几十秒后死机。由于这种死机是随机的、不易复现的很多人会怀疑硬件问题。所以移植FreeRTOS之前打开 stm32f10x.c 或者你的系统初始化文件确认NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)在此之前被调用过。4.3 SysTick与HAL_Delay的终极冲突如果你使用的是标准库STM32标准外设库FreeRTOS默认是用SysTick作为时基的。此时你的主循环里不能再用delay_ms()或者SysTick_Handler里的裸机延时函数。因为SysTick中断已经被FreeRTOS接管了你再占用它会破坏系统节拍。表现就是任务里调用了一个Delay_Ms(1000)调度器在那个时刻突然停止调度所有任务都不跑了看起来就像芯片死机了。FreeRTOS的单片机移植书中一直强调“不要在任务里使用阻塞延时”但很多从51单片机转过来的人还是习惯性用delay函数。如果你确实需要在任务里做延时请使用vTaskDelay()或者vTaskDelayUntil()。如果希望在中断服务函数里做延时可以临时关掉FreeRTOS的SysTick中断但最好还是别这么做。另外如果使用HAL库STM32CubeMX生成要注意HAL库有自己的HAL_GetTick()机制它会占用SysTick或TIM6/TIM7。你需要在CubeMX中把RTOS时基改为TIM7SysTick留给HAL。忘了改时基的双重占用是CubeMX FreeRTOS项目最常见的翻车原因之一。05. 通过串口确认芯片“到底是死是活”5.1 串口打印是排查“假芯片”的最佳工具当你的板子看起来“无反应”时不要干瞪眼试着往串口发点东西。如果芯片固件可以运行串口是最好的“心跳”指示器。前提是你的芯片已经至少成功烧录过一次固件。如果连固件都烧不进去那先用SWD连上调试器看看。我的常用做法在FreeRTOS项目的main函数开头加入一段永不删除的串口初始化代码输出一行System Boot OK, FreeRTOS Version: X.X.X。然后在每个任务循环里周期性打印任务名称和剩余栈空间。这样哪怕任务调度出问题我也能通过最后一条打印内容判断死在哪一步。串口打印还有一个好处验证时钟频率。如果你在初始化里配置了72MHz但实际外部晶振是8MHz串口波特率计算就会差一个倍频系数输出乱码。通过乱码的方向可以反推PLL配置错误。5.2 USART配置步骤标准库工程中串口打印的完整流程配置一个可以配合FreeRTOS使用的USART1步骤并不复杂但有几个细节需要注意// 1. 开启 GPIOA 和 USART1 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // 2. 配置 TX 为复用推挽输出RX 为浮空输入或上拉输入 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; // TX GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; // RX GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // 3. 配置串口参数 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); // 4. 使能 USART USART_Cmd(USART1, ENABLE);在FreeRTOS任务里发串口数据时整包发送期间不要让其他任务或中断插入同一句USART寄存器操作。最简单的方式是基于信号量做互斥保护或者使用带互斥的环形缓冲区。很多人把printf重定向到USART后直接多任务同时调用打印乱码、死锁、甚至是HardFault都不奇怪。06. 实战排查一个“芯片没反应”案例的完整走查过程6.1 故障现象记录前段时间帮朋友排查一块自制板现象非常典型芯片STM32F103C8T6淘宝买的五片装工程标准库 V3.5 FreeRTOS V10.0.1操作ST-Link V2烧录烧录提示成功按复位后LED无反应USART1无输出朋友第一句话就是“这芯片是不是假的”因为他在同一个工程、同一个板子上焊了第二颗芯片还是一样的问题。6.2 排查步骤与结论我没有立刻换芯片而是按照下面这个顺序一步步查第一步万用表量VDD3.29V正常。纹波手头没示波器但电源用的是AMS1117-3.3输入5V稳定大概率没太大问题。第二步量BOOT0电压0V正常从Flash启动。BOOT1悬空不影响。第三步量NRST电压3.3V正常。上电瞬间用万用表测不到复位脉冲但RC复位本来就只有几十毫秒万用表响应不过来所以这一步只是排除NRST被外部拉低。第四步用示波器量PA9USART1_TX发现上电后静默没有数据。量OSC_IN引脚发现有一个接近8MHz的波形幅度很低仔细看是正弦波但被削了顶部。第五步不接ST-Link单独用USB转TTL接PA9、PA10复位后程序正常打印启动信息。到这里问题已经锁定了不是芯片假而是ST-Link的SWD连接严重影响了PA9附近的信号环境或者更准确地说ST-Link的GND与USB转TTL的GND没有共同参考导致复位瞬间的噪声干扰了启动时序。后来发现朋友的ST-Link是那种十几块钱的“裸板”下载器它的GND线被掰断过之前一直靠着USB口的外壳地与板子耦合。换了一根杜邦线重新接上GND问题彻底消失。整个过程里芯片从未坏过FreeRTOS工程也完全正常纯粹是工具链的连接质量问题。6.3 这个案例的三条总结烧录成功不代表程序正常执行还涉及复位时序、电源完整性、时钟起振等多个环节。SWD调试与USB转TTL同时连接时必须确保两者共地否则复位瞬间的电流回路不稳定芯片启动时序会被干扰。遇到“芯片没反应”先从客户环境角度排查——电源电压、BOOT电平、复位电平、时钟波形全部确认之后再考虑芯片本身。07. 如何判断“这块STM32F103是不是真被搞坏了”7.1 明确的芯片损坏迹象如果怀疑芯片本身损坏可以参考这些相对明确的迹象检查项正常状态异常状态VDD对GND电阻几百Ω到几kΩ在线测量接近0Ω短路击穿NRST引脚电压上电后3.3V左右被拉低或持续脉冲芯片表面温度常温明显发烫超过60℃SWD IDCODE读取能读取到0x1BA01477Cortex-M3读取不到或读取值异常BOOT0引脚内部上拉后启动能从ROM Bootloader响应0x7F无任何响应如果你成功读取到SWD的IDCODE说明芯片内核活着。唯一的“假芯片”可能在于Flash容量、SRAM容量与标称不符这种情况需要额外跑一段程序测试容量而不是凭“无反应”判断为假。7.2 某宝“假芯片”的真实重灾区淘宝上买到打磨片、以次充好的芯片确实存在但主要集中在这些渠道商家明确标注“拆机片”“散新”这类芯片温度冲击后可能会有引脚氧化、内部键合线疲劳上电无反应的概率高于全新原装。超低价批量片正常市场价十几块一片的STM32F103C8T6如果有人卖三块五基本不可能是全新原装正品。丝印字母模糊、批次号重复同一批货十几片丝印完全一样大概率是后期重新打字。这些情况下确实可能买到坏片。但即便如此“上电无反应”的坏片比例依然远低于“电路没搭对”的比例所以排查顺序不能乱。7.3 手里没有示波器时如何用最简单的方式判断死活很多初学者手上只有万用表和LED灯没有示波器、没逻辑分析仪。这种情况下怎么判断芯片是不是真的死了有一个非常实用的小技巧利用芯片内部的ROM Bootloader。将BOOT0拉到高电平。用USB转TTL连接USART1PA9、PA10。手动给芯片复位。在PC上用串口助手发送0x7F字节波特率可以用9600、57600、115200依次尝试。如果芯片能从ROM Bootloader返回一串数据通常首字节是0x79或者0x1F说明芯片的内核、Flash控制器、串口外设基本都还活着。能走到这一步你几乎可以排除“芯片损坏”的可能剩下就是启动配置和应用代码问题。这个办法在没有任何调试工具的情况下也成立强烈建议大家学会。它比SWD调试更适合在没有仿真器的现场排查问题也是判断“假芯片”最有力的一招。08. 对FreeRTOS移植到STM32F103的一些项目落地建议8.1 工程模板的经典组合标准库 FreeRTOS / HAL库 CubeMX如果你准备从零开始做一个STM32F103 FreeRTOS项目工程模板的选型非常关键。标准库 FreeRTOS代码小巧启动快适合阅读源码、学习RTOS原理网上教程最多。但标准库已经停止更新如果你用到F103的高版本外设特性可能找不到太好的参考。HAL库 CubeMX图形化配置外设和FreeRTOS生成代码后添加业务逻辑适合快速做项目。但HAL库的代码层级多在F103这种72MHz的芯片上要关注延迟和代码体积FreeRTOS堆也要预留充足建议大于5KB。无论用哪种组合第一次移植的验证项目不要加太多外设。先做一个LED闪烁任务和一个串口打印任务确认两个任务能正常“同时运行”再逐步增加互斥信号量、队列、软件定时器这些组件。直接一顿操作全上出问题时根本说不清是移植问题还是业务逻辑问题。8.2 FreeRTOSConfig.h中几个必须关注的核心配置项很多人的FreeRTOS“移植失败”其实是配置文件有问题。以下配置项是我每次都要检查的#define configUSE_PREEMPTION 1 // 抢占式调度 #define configCPU_CLOCK_HZ 72000000 // 根据实际CPU频率填写 #define configTICK_RATE_HZ 1000 // 系统节拍 #define configMAX_PRIORITIES 5 // 最大任务优先级 #define configMINIMAL_STACK_SIZE 128 // 单位是字即512字节 #define configTOTAL_HEAP_SIZE (10 * 1024) // 堆大小至少10KB #define configUSE_MUTEXES 1 #define configUSE_COUNTING_SEMAPHORES 1 #define configSUPPORT_DYNAMIC_ALLOCATION 1 #ifdef __GNUC__ #define configCHECK_FOR_STACK_OVERFLOW 2 #endif如果你用的是标准库且configCPU_CLOCK_HZ填错了系统实际是72MHz但填成8MHz所有基于时间的APIvTaskDelay间隔都会按错误比例拉长看起来就像任务卡死了。configMINIMAL_STACK_SIZE 128表示128个字512字节这对于最简单的任务勉强够用。如果你的任务里调用了printf注意Keil MDK的printf重定向到串口后会使用较多的栈空间通常在500字节以上任务栈不要给得太抠。8.3 调试FreeRTOS的通用方法断点、打印、状态导出三件套如果移植的FreeRTOS程序出现了“偶发死机”建议不要把时间浪费在“反复上电看运气”上直接上工具断点法在vApplicationStackOverflowHook和vApplicationMallocFailedHook两个回调函数里设置断点或者点亮故障LED。一旦触发就能定位到堆栈溢出或者内存分配失败。打印法在每个任务的循环里打印任务名和时间戳出现卡顿之后看最后一条消息能锁定是哪个任务在哪个阶段出了异常。状态导出法使用vTaskList和vTaskGetRunTimeStats需要配置configUSE_TRACE_FACILITY和configGENERATE_RUN_TIME_STATS为1查看每个任务的状态、运行时间占比。如果某个任务占据了99%的CPU时间说明你的任务里存在忙等或者轮询阻塞调度器空转看起来就像系统死了。我在实际项目中还遇到过一种情况FreeRTOS任务里使用sprintf格式化浮点数库函数在高优先级抢占下不够安全导致随机HardFault。用状态导出法看到任务CPU占比异常高进一步追踪才发现是格式化消耗太严重。这类问题不打打印、不打状态表真的很难定位到。09. 踩坑回忆最后分享一个我自己的“假芯片”乌龙有一次我自己画了一块F103VET6的板子焊接完成后下载程序按复位屏幕没反应串口没输出连LED都不亮。因为之前在这个型号上吃过一次“淘宝打磨片”的亏那次确实换了一片就好这次我直接下单买了三片新芯片。等快递的间隙我闲着没事拿万用表测了一圈板子电源正常、BOOT正常、NRST正常。又用示波器量了OSC_IN发现外部晶振完全没有起振波形。拆掉外部晶振用HSI跑起来程序马上正常工作。问题出在焊接我用的是热风枪手工焊接温度过高导致PCB焊盘与晶振本体之间的焊锡坍塌形成了一座小“锡桥”把OSC_IN和OSC_OUT短接到了一起。晶振当然无法起振。把焊锡清理后贴回原来的晶振一切正常。这次经历给我最大的教训是遇到STM32“无反应”先看晶振、再看BOOT、再看电源、再看下载器连接最后才考虑换芯片。排查顺序对了基本上半小时能找到问题一上来就换芯片往往白烧三片新片子钱。后来我买芯片都会多买几片备用但每次都提醒自己去“先找软件和硬件原因再怀疑芯片质量”。STM32F103这颗芯片皮实得很多数情况下它只是在替你背黑锅。