ARTICLE DETAIL

资讯详情

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

STM32F103假芯片排查实录:从系统“变砖”到真相大白

STM32F103假芯片排查实录:从系统“变砖”到真相大白 上周调一块 STM32F103 的板子差点把我整失眠。这块板子用的是 STM32F103RCT6 主控标准库 V3.5 FreeRTOS串口走 RS232MAX3232 转电平移植了 FreeModbus V1.6 跑 Modbus RTU 从站另外还挂了一路 WS2812B 灯带、一路定时器 PWM 控制加热器。代码逻辑全部写完就在实验室上电测试的那一瞬间芯片彻底“没反应”了状态灯不闪、ST-Link 连不上、串口没有输出整个系统像一块砖头。我一开始以为是程序某处把时钟搞崩了或者 FreeRTOS 配置有问题戴上示波器和万用表从硬件到软件查了两天最后把芯片拆下来拿微距镜头一看丝印才意识到问题根源——这颗打着“全新原装”招牌的 STM32F103是一颗打磨过后重新印字的假芯片。这个排查过程很有代表性今天完整写出来希望能帮正在被同样问题折磨的人少走弯路。1. 项目背景与故障现象1.1 这套方案到底做了什么先交代一下这套方案为什么是这样设计的。项目是一台小型工业控制板STM32F103RCT6 负责数据采集、逻辑控制、通信和驱动输出。选择 F103 的理由很简单资源够用、外设丰富、生态成熟标准库代码随手能跑一颗芯片搞定所有功能。FreeRTOS 用来做任务调度把 Modbus 通信、灯带刷新、PWM 控制、按键扫描拆成独立任务避免前后台轮询导致主循环卡死。Modbus RTU 部分没有自己造轮子直接用 FreeModbus V1.6 移植只做从站挂在 RS232 总线上和上位机进行寄存器的读写交互。这个组合在市面上很常见也是很多入门工程师选择的第一套“RTOS 工业通信”实践项目。但也正因为通用一旦出问题网上照着抄的代码和真实板子之间会对不上排查起来非常痛苦。这次故障发生的阶段是代码已经写完下载到某几块板子上都能正常工作唯独有一批新到的样片焊上去就是“死”的。1.2 故障现象完全复盘为了后面排查方便我先把当时观察到的现象一条条列出来。注意这些现象单独拿出来都挺像软件问题但组合在一起就隐隐指向更底层的东西。上电后 3.3V 电源正常电流大约 30mA没有明显短路也没有芯片发热。板上的电源指示灯亮但用户状态灯从头到尾不闪。用 ST-Link V2 连接提示No target connected偶尔强制复位时能识别到一次接着再次连接又失败。用示波器抓 PA8 配置为 MCO 输出内部时钟始终没有任何波形。外部 8MHz 晶振两端的波形非常微弱只有几十毫伏的噪声完全看不到正常振荡的幅度。当时我的第一反应是“外部晶振没起振导致 SystemInit 卡死”。但换了几种配置、甚至改用内部 HSI 时钟后芯片依然没有任何反应这就很不正常了。因为就算外部晶振有问题代码里如果配置成 HSIMCU 至少应该能跑起来SWD 也应该能连上。2. 先别怀疑芯片把这些硬件环节全部排除遇到“芯片没反应”最忌讳的是直接甩锅给芯片。我自己的习惯是先把最小系统所有外围一个一个量过去确认硬件没有低级错误再考虑芯片本身。下面这几个排查点顺序不能乱省得绕远路。2.1 供电、复位、电容一个都不能少第一步一定是电源。STM32F103 的工作电压范围是 2.0V 到 3.6V板上实测 3.3V 没问题但这只是表面。还要注意芯片有几个电源引脚是独立供电的VDDA 通常要接和 VDD 一样的电压VREF 接模拟参考电压如果这两个引脚悬空或者电压异常芯片虽然数字部分能供上电但模拟电路和复位电路可能不工作表现就是“上电后没动静”。所以检查的时候不能只盯 VDD要把 MCU 所有电源相关引脚全部量一遍。第二步看复位电路。STM32F103 的 NRST 引脚内部有上拉外部可以再加一个 100nF 电容到地做上电复位延时。如果这个电容短路NRST 就一直被拉低芯片无法启动如果外接复位芯片没有配置好也可能让 MCU 一直处于复位态。用万用表量 NRST 对地电压正常工作时应该是 3.3V如果被拉低问题就在复位电路。第三步是 VCAP 引脚。很多新手会忽略这个细节STM32F103 的 VCAP1 和 VCAP2 是内部 1.8V 电压调节器的输出引脚必须外接电容datasheet 上要求接 2.2μF有说法也能用 1μF但按手册来最稳。如果电容脱落、焊盘虚焊或者容值不对内部电压调节器工作不稳定芯片上电后根本进入不了正常运行状态。这块我踩过坑一开始量 VDD 都正常就是没量 VCAP后来补焊电容才恢复。所以这一项在排查清单里优先级很高。2.2 启动模式与 BOOT 引脚最容易看漏的一环电源和复位没问题后接着看启动模式。STM32F103 的 BOOT0 和 BOOT1 引脚决定复位后从哪段存储器启动BOOT0 0BOOT1 任意从主 Flash 启动这是正常用户模式。BOOT0 1BOOT1 0从系统存储器启动也就是出厂 Bootloader。BOOT0 1BOOT1 1从 SRAM 启动。如果板子上 BOOT0 被外部电阻拉高或者不小心跳线跳到了 1芯片复位后不会执行用户 Flash 里的程序表现就是“烧录好像成功了但运行没反应”。而且这时候 ST-Link 依然是可以连接和下载程序的所以很容易被误导。我还遇到过一个更隐蔽的情况BOOT0 用 10kΩ 电阻下拉本来没事但 PCB 设计时走线太细阻焊层又有污染导致等效阻抗偏高偶尔上电 BOOT0 被干扰拉高程序时好时坏。这类问题在排查时要留意不要只看原理图要实际量引脚电平。2.3 外部晶振与 PA8 引时钟最小系统最容易出问题的第三个环节是时钟。STM32F103 可以用内部 HSI8MHz也可以用外部 HSE 晶振跑 FreeRTOS 时通常需要把系统时钟通过 PLL 倍频到 72MHz。如果工程里配置了外部晶振作为时钟源而外部晶振没有起振代码会卡在 SystemInit 的等待循环里芯片同样“没反应”。出现这种情况最有效的调试手段就是引时钟。STM32F103 可以把 MCU 内部的系统时钟、PLL 时钟或者 HSE 时钟映射到 PA8 引脚PA8 复用为 MCO 功能。如果 PA8 能输出方波说明时钟树已经跑起来了如果始终低电平要么是 MCO 配置没生效要么是时钟源本身就没有。实际操作时可以暂时把工程简化成最小化测试不初始化 FreeRTOS也不做复杂外设配置只打开 GPIOC 时钟把 PC13 配置成推挽输出然后在 while(1) 里翻转电平点灯。如果这样能在 HSI 下跑起来说明芯片执行核心没问题如果连这个都跑不动那就真要考虑芯片本身的问题了。3. 软件层面FreeRTOS 和调试接口布下的“假雷区”硬件检查做到位后我开始怀疑软件。毕竟 FreeRTOS 标准库的工程配置坑非常多调试器连不上、程序跑飞、任务不调度都有可能是软件问题。3.1 ST-Link 连不上不一定是硬件坏了ST-Link 连不上目标芯片最常见的原因其实就三类SWDIO/SWCLK 引脚被复用成普通 GPIO、代码进入了低功耗模式、目标板供电不稳定。排查顺序我习惯这样走先检查 SWD 接线ST-Link 的 SWDIO、SWCLK、GND、3.3V 四根线是否接触良好线材是否太长如果有 10cm 以上的杜邦线尽量换短一点SWD 对高速信号质量还是有要求的。尝试降低 SWD 通信速率ST-Link 在 Keil 和 STM32CubeProgrammer 里都可以调降到 1MHz 以下往往能解决接触不良导致的连接失败。然后确认芯片有没有跑进低功耗模式。如果 FreeRTOS 的任务里调用了WFI指令或者工程里配置了 STOP/STANDBY 模式调试器在唤醒前可能访问不到内核。处理方式是按住板子上的复位键让它一直处于复位状态同时在调试器连接那一刻松开复位也就是“复位连接”。这个方法在 Keil 的 Debug 设置里也能配合使用非常实用。再强调一点很多人用 VSCode 插件或 clangd 的时候看到#include freertos/freertos.h报错就以为工程配置有问题。这种 IDE 报错只是没配置编译数据库compile_commands.json跟芯片能不能跑没有半点关系别被它带偏。3.2 FreeRTOS 跑不起来的那些“误导性症状”FreeRTOS 跑不起来的症状非常有迷惑性最常见的是 HardFault、任务不切换、系统节拍异常。如果芯片是正常的很多时候原因就几个任务栈太小默认configMINIMAL_STACK_SIZE是 128Word也就是 512 字节。如果任务里用了大的局部变量数组或者调用了 printf 之类的库函数栈会瞬间爆掉触发 HardFault。堆空间不足FreeRTOS 在FreeRTOSConfig.h里通过configTOTAL_HEAP_SIZE配置堆大小使用heap_4.c时如果堆不够xTaskCreate会返回失败但代码可能没有检查返回值导致任务根本没有被创建。SysTick 或 PendSV 被干扰如果工程里其他地方重新定义了SysTick_Handler或者标准库的中断函数跟 FreeRTOS 端口文件里的初始化逻辑冲突时间片轮转就会停摆。排查时建议在FreeRTOSConfig.h里开启栈溢出检测#define configCHECK_FOR_STACK_OVERFLOW 2 #define configUSE_IDLE_HOOK 1 #define configUSE_MALLOC_FAILED_HOOK 1然后实现对应的钩子函数在vApplicationStackOverflowHook和vApplicationMallocFailedHook里设置一个标志位或者直接点错误灯。这样能快速缩小范围。不过这次的情况稍微特殊一点我甚至用一个最简裸机工程去测试芯片依然没有反应。这时候“软件配置问题”的可能性已经变得很低焦点终于回到了芯片自身。3.3 裸机点灯法把软硬件问题一刀切开这里把我的“裸机点灯法”具体写出来给遇到同样问题的人一个可以直接复制的路标。新建一个几乎空的工程不要初始化系统时钟、不要初始化 FreeRTOS、不要初始化串口直接操作寄存器点亮板载 LED。比如把 PC13 配置成推挽输出void delay(void) { volatile uint32_t i; for (i 0; i 1000000; i); } int main(void) { /* 使能 GPIOC 时钟RCC_APB2ENR 的 bit4 */ RCC-APB2ENR | (1U 4); /* PC13 配置为推挽输出50MHz */ GPIOC-CRH ~(0xFUL 20); GPIOC-CRH | (0x3UL 20); while (1) { GPIOC-ODR ^ (1UL 13); delay(); } }这段代码不依赖启动文件里的 SystemInit 做复杂时钟配置直接用上电默认的 HSI。如果它能让 LED 闪烁说明芯片的 Cortex-M3 内核、Flash、SRAM、GPIO 外设都在正常工作。如果它完全没反应那就要考虑是不是芯片在更底层的地方就有问题。我用这段代码测了手上的样片结果 LED 纹丝不动。到这一步我才正式开始怀疑“芯片是假的”。4. 真相大白这块芯片到底“假”在哪先说明一下“假芯片”这个词。市场上说的假 STM32F103大致分几类一是翻新片从旧板子上拆下来洗脚、打磨、重新打标二是 Remark 片把低容量型号的丝印磨掉重新打上高容量型号三是直接用国产兼容芯片冒充 ST。这几类芯片在电气参数、Flash 可靠性和外设行为上和正品存在明显差异在 FreeRTOS、Modbus 这类需要稳定运行的场景下很容易暴露。4.1 外观丝印的鉴别经验这是最直观、也最容易学会的一步。正品 STM32F103 的丝印是激光打标字迹由微小的点阵颗粒组成边缘锐利颜色偏灰白用放大镜或手机微距镜头看能明显感觉到字的“质感”是烧灼出来的而不是印上去的。正品表面整体均匀批号行和型号行的字体清晰数字和字母的间距一致。假芯片常见的特征有几类芯片表面有一层“雾面”打磨纹像细砂纸磨过一样。丝印颜色偏黑、发亮边缘有轻微晕染像普通油墨印刷。引脚根部有残留焊锡或助焊剂痕迹说明是拆机料。丝印型号和批号格式不规范比如STM32F103RCT6中的“C”应该代表 256KB Flash但批号逻辑对不上。我手里这批芯片表面就有一层明显的打磨纹丝印字体在微距下模糊发虚和以前用的正片放在一起对比一眼就能看出来。但话说回来单凭外观并不能 100% 判定尤其是现在高仿技术也在进步必须配合下面的电性能验证。4.2 用 STM32CubeProgrammer 读穿它的底细外观不够就得让芯片自己“说话”。官方工具 STM32CubeProgrammer 能够通过 SWD 接口读取芯片内部的身份信息寄存器这些信息很难被完全伪装。连接方式先确认 SWD 四线连接正常打开 STM32CubeProgrammer选择 ST-LINK点击 Connect。连接成功后在右边的 Device information 里可以看到Device IDSTM32F103 中容量和大容量产品一般是0x410。实际上 F103 系列有两种 ID0x410对应 256KB 以上 Flash 的大容量型号0x414对应中容量128KB 以下。不同批次和型号会有区别但至少应该落在合法的范围内。Flash size存储在芯片选项字节区域地址是0x1FFFF7E0内容是 16 位值单位是 KB。对于 RCT6正常应该是0x0100也就是 256KB。UID地址0x1FFFF7E8开始共 96 位正品每一颗芯片的 UID 都不同且不会是全 FF。我当时读到的情况是Device ID 是0x410看着像那么回事但 Flash size 只有0x004064KB与 RCT6 完全不符。UID 更是厉害直接全 FF。这就说明这颗芯片根本不是真正的 RCT6 大容量型号而是用低容量芯片打磨重新打的丝印。检查项正版 STM32F103RCT6这块假芯片Device ID0x4100x410Flash Size 寄存器0x0100256KB0x004064KBUID96bit唯一且非全FF全FF芯片表面激光点阵边缘锐利打磨纹字体模糊引脚状态全新无焊痕引脚根部有轻微氧化如果你的芯片也读出类似结果基本可以直接判定为假芯片。尤其是 Flash Size 和丝印不一致这是最硬气的证据。4.3 行为特征下载和保存数据最容易露馅除了读身份信息运行行为也能暴露假芯片。假芯片最大的问题往往不是内核不工作而是内部 Flash 质量差、容量映射不对、电气参数漂移。最典型的行为是烧录时频繁报错。用 ST-Link 下载程序时正品 F103 一般几十秒就能写完并校验通过假芯片可能在擦除或者写入过程中直接报Flash Download failed - Cortex-M3或者写完以后校验不一致。这是因为低容量芯片的 Flash 物理大小不够或者劣质 Flash 的写入时序已经不可靠。另一个容易露馅的场景是掉电保存数据。项目里经常用到内部 Flash 模拟 EEPROM保存参数和校准值。正品 F103 的 Flash 可以承受大约 10k 次擦写掉电后数据保持几十年没问题。假芯片的 Flash 往往几十次擦写后就出现坏块甚至写入时数据就写偏了重新上电读到的是全 FF 或者随机值。这个特性在“STM32F103 掉电保存数据失效”的讨论里被反反复复提到本质原因经常就是 Flash 质量不过关。如果遇到烧录报错、掉电数据丢失、运行一段时间后固件莫名其妙失效的先别急着改代码把芯片的 Flash 容量和 UID 读出来看看能省很多无用功。4.4 确认流程与结论综合上面的证据我自己整理了一套假芯片判定流程分享给各位参考先用放大镜/微距观察丝印和引脚记录是否存在打磨痕、字体模糊、引脚焊痕。用 STM32CubeProgrammer 连接读取 Device ID、Flash Size、UID。对 Flash 执行一次全片擦除和写入再读回校验。重复擦写同一地址至少 50 次检查是否出现坏块。跑一个简单的裸机点灯程序再跑一个完整的 FreeRTOS 串口程序观察运行稳定性。我这次在第二步就已经确认了问题所在。那颗芯片最终被我拆下来当作反面教材贴在工位上时刻提醒自己不要为了省几块钱在非正规渠道买芯片。5. 假芯片引发的“移植翻车”现场复盘确定是假芯片以后我再回头看项目里那些“移植问题”发现很多现象都能解释了。这里挑选几个典型来复盘因为它们看起来和 FreeRTOS/Modbus 移植关系很大但实际上源头都是假芯片。5.1 RS232 FreeModbus 的乱码与超时问题Modbus RTU 的移植本身不难FreeModbus V1.6 使用标准库 V3.5 时可以非常顺畅地桥接到串口和定时器上。我最开始调试的时候发现从站响应很怪用上位机做主站去读寄存器数据常常读到一半就超时偶尔返回的报文里还有乱码。第一反应是 FreeModbus 的 3.5 个字符时间间隔没有调好。因为 Modbus RTU 要求一帧报文要能根据字符间隔来断帧如果定时器重载值算错了就会出现收半个包、断帧错乱的问题。我反复检查波特率 9600 下的定时器分频和重载值加上串口中断里的处理逻辑怎么看都没有问题但现象还是间歇性出现。后来把示波器同时夹在 RS232 的 TX 和 RX 上发现从站在回复报文时TX 引脚上偶尔会出现一段异常宽的脉冲后续字节也不稳定。这不是协议栈的问题而是芯片内部 Flash 读取错乱导致某些代码段取指异常串口发送函数执行到一半就跳走了。换句话说如果你的 FreeModbus 移植反复核对都没问题但运行起来时好时坏可以考虑在芯片身份和 Flash 可靠性上找找原因。5.2 定时器 PWM 占空比到不了 100% 的迷思项目里有一路定时器 PWM用来控制加热器功率。当时遇到一个特别奇怪的现象调节占空比时只要目标值设置成 100%输出反而变成低电平或者极窄的毛刺加热器不工作。看起来非常像代码里比较寄存器设置错误。在正版 STM32F103 上PWM 输出占空比达到 100% 的常规操作是把比较寄存器 CCR 设置得比自动重载寄存器 ARR 还大或者直接等于 ARR此时输出保持有效电平。这个逻辑本身非常简单几乎不可能写错。当时我检查了定时器模式、极性、预装载甚至怀疑是不是标准库的某个宏定义用错了。后来用逻辑分析仪抓了那几个引脚发现 PWM 输出毛刺并不是稳定的而是偶尔出现、偶尔消失。结合前面 Flash 读取不稳定的现象可以推断是 CPU 加载指令时出错导致定时器寄存器在某几个周期内被异常改写。所以如果你的 PWM 占空比“到不了 100%”而且伴随其他运行时偶发抖动先别急着怀疑定时器配置不妨先验证芯片是否可靠。5.3 项目中加一道自检程序把假芯片拦在出厂前经过这次踩坑我在工程模板里加入了一个“上电自检模块”专门用来识别芯片身份异常。这个模块在系统时钟初始化完成后、FreeRTOS 调度器启动之前执行逻辑不复杂读取 DBGMCU_IDCODE 寄存器地址0xE0042000确认 Device ID。读取 Flash Size 寄存器地址0x1FFFF7E0核对 Flash 容量。读取 UID 寄存器地址0x1FFFF7E8检查是否为全 FF。检查内部 Flash 前 4KB 的 CRC 校验和如果读取错误立刻报警。把检查结果通过串口打印出来不合格就进入死循环同时闪烁错误指示灯。这段自检代码对正式产品同样有价值。硬件工程师可以在产线烧录阶段统一运行一次自检固件把 UID、Flash Size 和校验结果打上标签存档到 Excel。后续如果客户退回板子可以直接比对哪个批次、哪颗芯片出了异常排查效率会高很多。6. 采购与来料检验建议别让假芯片毁掉项目最后聊采购。很多工程师只关注代码和硬件设计对供应链不够上心结果项目周期被假芯片拖了两周实在不划算。这里分享一些实操经验。6.1 靠谱渠道和下单后第一件事我的建议是优先走 ST 授权分销商或者有长期合作的、可追溯来源的元器件代理商。虽然单价可能比某些现货商贵一点但省下的调试时间和售后成本远不止这一点差价。下单时保留正品凭证、批次号、质保信息这些都是后面追溯的抓手。货到了以后不要急着把整批芯片全部贴片。先抽几颗做外观检查再上测试座或做个最小系统板验证。如果发现任何一颗有问题就要整批冻结并要求供应商解释和退换。芯片这种核心物料一颗异常品流到产线上就可能让整批板子陷入排查泥潭。6.2 三分钟快速抽检流程针对新到货的 STM32F103我整理了一个三分钟抽检清单供大家参考测试项通过标准说明外观丝印字体清晰表面无打磨痕用微距镜头放大查看Device ID与型号匹配如 0x410用 STM32CubeProgrammer 读Flash Size与丝印容量一致如 RCT6 应为 256KBUID 唯一性非全FF且每颗不同连续读多颗对比Flash 反复擦写50次擦写后读回一致用自检固件测试系统运行稳定性裸机点灯和 FreeRTOS 任务正常至少跑 10 分钟如果抽检中出现任何一项不合格直接整批退回。这一步操作在实验室里几分钟就能完成但能避免后续整车间的返工。6.3 供应链紧张时的替代思路这几年芯片供应链波动很多人买不到正品 STM32F103就开始找各种“现货”。这个时候我的建议是如果买不到正品优先选择正规国产兼容芯片比如 GD32、APM32 等。它们是有一套完整数据手册、烧录工具和售后支持的正规产品虽然不能保证和 ST 完全一致但至少有据可查、有源可溯。要注意的是FreeRTOS 移植到这些国产兼容芯片时不能直接无脑用 STM32 的启动文件。比如 GD32 的 Flash 等待周期设置、时钟树和外设寄存器地址可能有差异串口、定时器的行为和 STM32F103 也不是 100% 一样。用 CubeMX 这类工具生成 STM32 工程后手工修改让代码适配 GD32需要重新做一轮完整的回归测试。选择兼容芯片是合法的设计决策但“假芯片”是另一回事。用假冒 ST 芯片会带来不可控的质量风险和数据隐患无论从哪个角度讲都不值得。最后分享一个我自己的土办法每个新批次芯片到货后我都会在实验室写一个自检固件把 UID、Flash Size、Flash CRC 全部打印出来归档到一个 Excel 表里。这次如果不是芯片 ID 和 Flash 容量对不上我可能还在傻乎乎地改 FreeRTOS 配置不知道要折腾多久。电子行业就是这样很多“疑难杂症”翻到最后往往是供应链的问题。多做一层验证多留一份记录能省下好几个通宵。
返回列表