ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32F103+FreeRTOS假芯片排查:从硬件问题到系统异常的完整定位指南

STM32F103+FreeRTOS假芯片排查:从硬件问题到系统异常的完整定位指南 STM32F103 FreeRTOS程序烧进去之后芯片一点反应都没有供电正常、复位正常、代码编译零错误——这种时候绝大多数人的第一反应是“我代码写错了”。改了一整天查了FreeRTOS配置、查了启动文件、查了时钟初始化问题还在。后来被资深工程师点了一句“你确定你手上的芯片是真的”拿去一查果然是打磨重标片。这篇文章就把我自己那次“假芯片”排查经历展开聊聊包括怎么区分真假芯片、怎么用最不折腾的方式避开假片坑以及FreeRTOS跑不起来时到底该怎么一步步定位是软件还是硬件的问题。1. 芯片没反应先别急着怀疑你写的FreeRTOS代码先说一下我当时遇到的情况手头一个STM32F103C8T6最小系统板用的是标准库程序逻辑很简单——上电后初始化一个LED闪烁任务再加一个串口打印任务跑FreeRTOS。代码本身是从一个验证过的工程改过来的芯片型号选择、启动文件、宏定义这些都核对过。烧录的时候一切正常校验也通过了。但一上电LED不闪串口没有任何输出用示波器量了PA8当时用定时器输出一个1kHz的PWM做“心跳”什么波形都没有。程序就像压根没跑起来一样。大多数人的排查顺序是先怀疑FreeRTOS配置、然后怀疑延迟函数、然后怀疑时钟初始化、然后怀疑启动文件。我也一样前前后后折腾了几个小时。不过后来回头看第一轮排查漏掉了一件最基础的事——芯片本身的供电和复位引脚状态。STM32F103的复位脚NRST是低电平复位内部有上拉理论上悬空也能工作。但如果最小系统板上的复位电路有问题比如复位电容漏电、按键短路芯片会一直卡在复位状态程序永远跑不起来。我当时量了NRST引脚电压只有0.8V左右明显不对——不是高电平。这个现象用“代码逻辑”解释不了问题出在硬件。测下来发现是板子上复位电容焊错了贴了一个10uF的电容上电瞬间复位时间过长加上板子电源纹波大导致芯片上电后反复复位。换回100nF电容顺便给电源并了一个10uF的钽电容问题立刻消失了。所以芯片没反应第一步永远是确认硬件基础三要素电源VDD引脚实测3.3V纹波控制在100mV以内注意用示波器看万用表量出来的直流值参考意义有限。复位NRST引脚在高位不能用万用表量一下3.3V就完事最好复位一下看波形。时钟外部晶振是否起振用示波器探头点OSC_IN和OSC_OUT引脚。这三个没问题了再往软件层面找原因。不要一上来就怀疑FreeRTOS更不要一上来就怀疑“假芯片”——虽然这篇文章标题说的是假芯片但很多“芯片没反应”的案例排查到最后其实是硬件外围的问题。1.1 最小系统这几个坑最容易误判为“芯片坏了”做STM32F103最小系统大部分人用的是网上买的开发板或者最小系统板但还有人喜欢自己画板子。自己画板子踩坑概率高得多尤其是下面几个细节第一BOOT0和BOOT1引脚的处理。BOOT0默认接10K下拉到地从主Flash启动这个大家都清楚。但BOOT1如果要悬空建议也加一个下拉电阻防止干扰导致意外进入Bootloader。我就见过一个板子BOOT0没接电阻直接接地BOOT1悬空结果上电后偶尔能跑、偶尔不能跑非常诡异——后来用镊子碰了一下BOOT1引脚芯片直接进入了Bootloader模式串口还往外发数据。第二VCAP1引脚。STM32F103C8T6没有VCAP引脚但F103ZE这类大容量芯片有VCAP1和VCAP2需要接2.2uF电容到地。如果这个电容没焊或者焊错容量芯片内核电压不稳定现象也是“完全不工作”而且用调试器连上去会报“Cannot access target CPU”。第三VDDA引脚。很多人画原理图的时候VDDA直接跟VDD连一起中间不加磁珠或电感也不加滤波电容。这会导致ADC参考电压不干净但如果只是跑GPIO和FreeRTOS影响不大。真正的问题在于有些芯片对VDDA的电压跌落非常敏感电源上电瞬间如果3.3V建立太慢芯片会锁死在一个异常状态必须重新断电再上电才能恢复。第四NRST复位电路。上面已经提到了复位电容不要太大100nF是正常值有些板子为了“抗干扰”加了1uF甚至10uF结果上电复位时间太长程序跑到一半又复位了看起来就像“芯片没反应”。1.2 Keil下载正常不等于程序在跑先确认调试连接还有一个常见误判——Keil提示下载成功、校验通过就觉得程序肯定烧进去了。但有一种情况是芯片读保护被打开过调试器连接时自动做了全片擦除程序烧进去了但Option Bytes里读保护状态可能不正常。早期某些盗版ST-Link在对F103操作时这种情况很容易出现。另外如果用的是ST-Link下载程序跑不起来还有一个经典问题SWDIO和SWCLK引脚复用冲突。F103的PA13和PA14默认是SWD调试引脚但如果你在代码里把这俩引脚重映射成GPIO或者复用功能并且初始化代码执行太快调试器还没来得及保持连接SWD就直接断开了。断开之后如果你在代码里禁用了调试端口比如设置了DBGMCU_CR那芯片再上电后调试器就连不上了——现象就是芯片没反应程序好像没烧进去。遇到这种问题可以先用ST-Link Utility或者STM32CubeProgrammer连接芯片如果连接成功说明芯片本身是好的问题大概率还是出在代码上。如果连接都失败再去怀疑硬件和芯片本身。2. 什么情况下才需要怀疑“假芯片”以及假芯片的常见套路把硬件基础和调试连接都排查了一遍之后还是没思路这时候再把“假芯片”放到台面上来算是合理的怀疑路径。但“假芯片”这词太笼统了其实市面上流通的STM32F103问题芯片主要分这么几类。2.1 打磨重标片最典型的“假芯片”陷阱打磨重标片就是回收旧板子上的芯片把表面原来的丝印打磨掉重新印上一个市场上容易卖好价钱的型号丝印。比如把STM32F103C8T6Flash 64KB、RAM 20KB磨掉印成STM32F103CBT6Flash 128KB、RAM 20KB甚至印成STM32F103RCT6Flash 256KB、RAM 48KB拿去卖。这种打磨片你说它完全不能用吧也不一定——如果只是做简单的GPIO控制64KB Flash的芯片当CBT6用可能跑好久都发现不了。但如果代码量超过了64KB烧录的时候Keil会提示“No space in execution regions”这还算好的至少能发现。怕的是代码量不到64KB但RAM用超了或者用到了被“阉割”的外设那问题就隐蔽多了。F103系列不同型号除了Flash和RAM容量有差异外设也有区别C8T6没有USB OTGCBT6也没有但RCT6有USB OTG_FS。某些型号的串口数量不同C8T6只有3个USARTRCT6有5个。某些型号的定时器数量不同高级定时器TIM1和TIM8在C8T6上也有但如果是打磨自更小容量的芯片就可能缺失。我在一个项目里就遇到过用了一个“CBT6”代码里初始化了USART3上电后发不出数据折腾了一整天最后发现这个芯片其实是C8T6打磨的——C8T6上USART3引脚确实存在但硬件连接到了另一个USART上具体是USART2因为芯片本身只是C8T6的Die。这种情况最坑因为不仔细对比数据手册里的外设映射根本看不出问题。2.2 翻新片引脚氧化、内部键合损伤是隐雷翻新片是从旧板子上拆机下来的芯片清理引脚、重新植球后二次流入市场。这种芯片最大的问题不是“能不能用”而是“能用多久”和“是否稳定”。拆机片在拆焊过程中引脚和内部键合线可能受到热应力损伤短期内测试可能一切正常但上电跑几天甚至几小时后突然就死机了复位也没用必须断电重启。如果你在产品里用了这种片子售后问题会让你想砸了自己的脚。翻新片从外观上比较难分辨但有几个观察点引脚尖端是否有焊锡残留痕迹、引脚是否有重新整形过的压痕、芯片底面是否有被加热过的变色印记。当然这些观察手段只能作为参考因为有些翻新片处理得相当干净。2.3 低端型号冒充高端型号容量与ID都能造假还有一种情况是拿更低端的芯片冒充。比如用STM32F103T8U6QFN36封装冒充C8T6或者用STM32F030系列芯片打磨成STM32F103——因为F103的价格比F030高出好几倍利润空间大。这种“跨系列”冒充其实很容易识破因为F030和F103的内核都不一样一个是Cortex-M0一个是Cortex-M3。上电后直接读DBGMCU IDCODE就能看出来。但普通用户如果只看丝印很容易被忽悠。还有更狠的用国产的GD32F103、APM32F103来冒充ST的STM32F103。GD32F103和STM32F103引脚完全兼容程序也基本兼容但外设寄存器有细微差别有些外设的时钟分频方式不一样。如果你在STM32F103上跑得好好的代码放到GD32上可能偶尔工作正常、偶尔不正常。这种“李鬼”芯片你用串口指令读取芯片ID0xE0042000地址的UUID就能看出区别但前提是你得先怀疑它。2.4 假芯片怎么鉴定几块钱成本就能搞定说了这么多假芯片的类型具体怎么鉴定我列一个自己用过的操作流程第一步看丝印。正品ST芯片的丝印工艺很稳定字体边缘清晰锐利激光打标的深度一致。打磨重印的丝印往往字体发虚、边缘有毛刺、油墨感偏重。另外ST的丝印上有一个“M”标志是马来西亚封装工厂的标识正品的M标志拉丝工艺细节在40倍放大镜下非常清晰翻新打磨片很难模仿。第二步读芯片ID。用ST-Link或者J-Link连接芯片读DBGMCU的IDCODE寄存器正常STM32F103应该是0x410或0x411不同批次有差异。如果读出来不是这个值甚至读不出来那就非常可疑了。STM32F103C8T6的UID唯一设备标识在0x1FFFF7E8地址读取96位。虽然UID不能直接证明真假但至少能排除“连ID都读不出来”的低端假货。第三步读Flash容量选项字节。STM32F103的Flash容量存储在0x1FFFF7E0地址Option Bytes区域是一个16位值单位是KB。读出来如果是64说明是C8T6如果是128说明是CBT6。如果丝印写着CBT6但读出来是64恭喜你买到重标片了。第四步跑一个跨引脚测试程序。把所有GPIO口都配置成推挽输出轮流输出高低电平用万用表或示波器逐个量。有的假芯片某些引脚内部没绑定Die这个测试能直接暴露问题。不过这一步比较耗时我一般是在已经怀疑到具体芯片时才做。第五步用功耗判断。工作状态下STM32F103C8T6跑8MHz外部晶振空循环电流大约在10mA左右关闭外设时如果芯片一上电电流就异常大或者异常小都值得怀疑。当然这个判断需要经验积累只能做辅助参考。3. FreeRTOS运行异常的排查链路先判断软件还是硬件排查完芯片本身假设确认了芯片没问题但FreeRTOS还是跑不起来这时候就需要一条系统的排查链路。我见过太多人卡在FreeRTOS上最后发现其实跟FreeRTOS半毛钱关系没有。3.1 第一步用裸机代码验证基础外设不要一上来就上FreeRTOS。先用裸机代码只初始化时钟、一个GPIO、一个定时器让LED以固定频率闪烁。如果这个程序都跑不起来那就别折腾FreeRTOS了回到第一章的基础硬件排查。这一步看着简单但真能省下大量时间。FreeRTOS像一个精密的调度系统它默认让你觉得“代码写得对不对”是关键但实际上底层硬件没跑通系统再复杂也白搭。我自己的习惯是所有新板子、新芯片先烧一个经典的“LED闪烁裸机程序”然后配一个串口打印。这两个都正常了再往上面叠加FreeRTOS。裸机验证时要注意一个坑STM32F103的标准库和HAL库在时钟初始化上是有差异的。标准库是SystemInit() 用户在main里调用RCC配置函数HAL库是SystemClock_Config()。如果你之前在HAL库工程上跑通了某个外设切到标准库时忘了重新配置时钟树外设初始化可能没问题但实际外设时钟频率不对导致串口波特率完全不准——这时候看起来就像“程序没跑起来”但LED可能其实在闪只是你没注意。3.2 第二步FreeRTOS能编译能下载但任务不执行这是FreeRTOS入坑最常见的问题编译通过、下载成功但任务要么一个都不执行要么只有一个任务执行。优先级配置是第一个检查点。FreeRTOS的调度规则是高优先级任务就绪时会抢占低优先级任务。如果你在main函数里创建了一个高优先级任务然后这个任务里有一个死循环且没有调用任何可能阻塞的API比如vTaskDelay、vTaskDelayUntil、xQueueReceive等那么低优先级任务永远不会被执行。还有一个非常隐蔽的坑空闲任务Idle Task的优先级是0理论上最低。但FreeRTOS要求至少有一个任务处于就绪态否则会触发configASSERT。如果你把所有任务都阻塞了空闲任务会接管但如果你在钩子函数里做了什么耗时操作会影响系统节拍。更好的检查方式是在任务A里加一个计数器变量在其他任务里加另一个计数器然后在主循环或一个低优先级任务里比较两个计数器的增长速率。如果哪个计数器不增长就知道哪个任务没跑。另外一个经典问题FreeRTOS堆栈溢出检测。configCHECK_FOR_STACK_OVERFLOW这个宏可以设置成1或2但很多人的工程里是0关闭。如果任务内使用了较大的局部数组导致任务栈溢出FreeRTOS的行为是未定义的——可能是直接HardFault也可能是系统卡死但最诡异的是“看起来一切正常只是某个任务偶尔不跑”。我之前排查过一个案例一个任务里定义了一个512字节的局部数组任务栈分配了256字1024字节按理说够用但加上函数调用栈帧和中断嵌套开销实际栈使用已经接近顶格运行几个小时后栈溢出系统崩了。所以新工程建议直接把configCHECK_FOR_STACK_OVERFLOW设为1同时打开一个串口打印或者LED指示在vApplicationStackOverflowHook里打一个标记。3.3 第三步SysTick被占用FreeRTOS的时间脉搏断了STM32F103上跑FreeRTOS系统节拍默认是用SysTick实现的。如果你在裸机工程里用了delay函数比如著名的delay_ms()它也是基于SysTick的——这样就会跟FreeRTOS产生冲突。典型现象是程序烧进去后LED闪了一下就再也不动了或者干脆连第一次闪烁都没有。因为SysTick_Handler里既有裸机的延时递减逻辑又有FreeRTOS的xPortSysTickHandler两者互相干扰系统节拍直接错乱。排查方法很简单——屏蔽掉所有裸机延时函数相关的SysTick处理逻辑统一使用FreeRTOS的vTaskDelay和vTaskDelayUntil。还有另一种情况你的工程用到了HAL库的HAL_Delay()它内部用的也是SysTick但HAL库在初始化时会把SysTick优先级设置成最低而FreeRTOS要求SysTick中断优先级是最高优先级组里的最低优先级数值最大两者一冲突同样会导致调度异常。幸好FreeRTOS的移植层里有vPortSetupTimerInterrupt这个函数你可以在里面重新配置SysTick但如果你用的是默认的HAL配置就需要手动覆盖掉。3.4 第四步中断优先级分组FreeRTOS最苛刻的要求FreeRTOS在Cortex-M3上有一个硬性要求NVIC中断优先级分组必须设置为优先级组4全部4位用于抢占优先级即NVIC_PriorityGroup_4。这是因为FreeRTOS的临界区保护依赖BASEPRI寄存器它限制了可屏蔽的中断优先级阈值。如果优先级分组不是组4BASEPRI机制就无法正常工作临界区代码会被高优先级中断打断导致FreeRTOS内核数据结构损坏。这个错误不会导致编译失败甚至不会立即导致崩溃。它往往是系统运行了一段时间后某个中断触发了FreeRTOS的链表操作被破坏然后系统进入HardFault或者任务行为完全不可预测。在STM32F103标准库中调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)即可。HAL库中是HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)。关键是在系统初始化早期就设置好最好是在main函数的第一行任何外设中断初始化之前。3.5 第五步堆分配器选错内存管理直接崩掉FreeRTOS源码里提供了5种堆分配器从heap_1.c到heap_5.c。F103这种小内存芯片常用的是heap_2.c或heap_4.c。heap_1是最简单的分配器只支持分配不支持释放适合所有任务都是常驻创建、从不删除的场景。如果你用了任务删除功能、队列删除功能heap_1会直接报错。heap_2支持释放但不会合并相邻空闲块容易产生碎片。heap_4是heap_2的改进版会合并相邻空闲内存块是比较推荐的选择。常见错误是工程里同时添加了多个heap_x.c文件导致链接时出现重复符号定义编译报错。还有一种情况是你在main里申请了很大一块内存比如128KB的数组然后把configTOTAL_HEAP_SIZE也设置得很大结果芯片总共只有20KB RAM程序一启动就爆了。怎么确认堆分配器够不够用最简单方法xPortGetFreeHeapSize()函数返回当前空闲堆大小把它打印出来。如果你的任务栈加堆的总需求超过芯片总RAMFreeRTOS会在初始化时直接断言失败。在FreeRTOSConfig.h里把configASSERT定义为自定义函数可以打印出错行号排查起来效率高很多。3.6 第六步HardFault处理的野路子系统跑着跑着突然HardFault了但没有接调试器不知道卡在哪个位置。这时候用一个原始的黑科技在HardFault_Handler里加一个死循环同时翻转一个LED引脚。看LED闪烁的频率变化就能粗略判断是哪个中断导致的问题——比如“滴答”提示音频率跳变时崩溃的可能是定时器中断优先级配置出了问题。更正规的做法是在HardFault_Handler里读栈指针MSP或PSP把压栈的8个寄存器R0-R3、R12、LR、PC、xPSR解析出来PC值就是触发HardFault的指令地址配合Keil的map文件就能定位到具体函数。这个流程两步走先用IPSR寄存器判断是否在中断上下文再根据CONTROL寄存器判断用的是MSP还是PSP。不过说实话对大多数FreeRTOS初学者来说与其分析寄存器和栈不如先跑一遍裸机、再逐步加任务——把问题缩小到某一个任务或某一个外设中断上往往更快。4. 实测中“假芯片FreeRTOS”的联合坑症状比单一问题更迷惑前面说的都是单一问题。但在实际项目中最头疼的是“假芯片”和“FreeRTOS”两个问题叠加那排查起来才真是炼狱模式。4.1 假芯片的RAM容量不足FreeRTOS任务莫名消失我经历过一个项目用的是从某宝买的STM32F103C8T6丝印看起来没毛病C8T6该有的标记都有。但项目里跑了一个比较复杂的FreeRTOS应用6个任务每个任务栈1-2KB加上各种队列和信号量预估RAM需求大约17KB。C8T6的RAM是20KB理论上是够的。但程序跑起来经常出现这样的情况某个任务执行了一会儿就再也不执行了其他任务正常。用调试器看任务状态发现那个任务不在了但这不像是被删除了更像是任务控制块被破坏了。最终定位到那批芯片实际封装的是F103C6RAM 10KB剩余内存根本不够跑6个任务。任务创建时的内存分配其实已经失败了但xTaskCreate返回的错误被忽略了空指针任务控制块被塞进了就绪链表系统没有立即崩溃而是运行几秒后才开始出现各种奇怪现象。这种问题有一个规律代码量不大、芯片内Flash也够用但运行时间越长越容易出问题。因为任务栈和堆的内存分配依赖可用RAMRAM不足不会在编译时报警只有在运行时才会暴露。排查思路是把configTOTAL_HEAP_SIZE打印出来看xPortGetFreeHeapSize()在初始化后剩余多少如果少得离谱就要怀疑芯片RAM容量是否真实了。4.2 假芯片外设缺失导致任务阻塞后无人唤醒另一种让人崩溃的场景某任务使用xQueueReceive等待一个数据队列数据由USART中断或DMA中断填充。程序烧进去后这个任务永远等不到数据系统看起来就像“卡死”了。这种情况先排查的不是FreeRTOS而是USART中断到底有没有触发。用调试器在USART中断服务函数里打断点如果断点根本没有被命中说明中断没有进来。然后查外设寄存器。如果芯片是假的——尤其用更低端型号打磨的——某些外设的基地址确实存在但对应的外设时钟门控寄存器RCC_APB2ENR/RCC_APB1ENR中对应的位可能被“阉割”了Die上没有实际外设逻辑使能时钟后外设寄存器没有任何反应。我遇到过最离谱的情况伪造芯片上的SPI1寄存器读取值全是0xFFFF初始化时写入CR1寄存器后回读永远是0xFFFF。在代码里加了回读校验后程序立刻停在断言处这才发现是芯片问题。所以在FreeRTOS的代码里建议给关键外设的初始化加上校验逻辑。比如SPI配置完后回读CR1确认设置的使能位真的写进去了。正常芯片回读值应该是预期值如果完全是0xFFFF或0x0000说明外设不存在或引脚没映射对。4.3 假芯片的系统节拍不准确任务调度看着像“随机”还有一种情况芯片是高频晶振启动的翻新片但内部RC振荡器校准值已经丢失或偏差过大。FreeRTOS的vTaskDelay用SysTick计数SysTick的时钟源来自内部RC还是外部晶振取决于RCC配置。如果外部晶振没起振但代码配置的是外部晶振SysTick就卡在等待时钟标志位的死循环里系统表现就是“完全没反应”。如果芯片内部HSI校准偏差大外部晶振又不起振但HSI被配置成系统时钟源系统能跑但时间基准漂移严重。原本1000ms的vTaskDelay可能变成800ms也可能变成1300ms具体取决于芯片内部RC振荡器的真实频率。排查方法用一个外部秒表计时看LED闪烁周期是否稳定。如果周期明显偏差超过5%先把时钟配置改成外部晶振或者检查晶振两脚的波形。如果晶振不起振多半是芯片的RTC域Vbat引脚没接电源有些最小系统板的VBAT直接接地了但F103的VBAT和VDD在内部有切换VBAT接地虽然能工作但在某些芯片版本上会影响外部晶振起振。4.4 用软件手段识别“FreeRTOS跑不动”是否源于硬伤识别假芯片和软件问题的干扰不能只靠硬件测量纯软件也能做几件事。第一任务创建时检查返回值。xTaskCreate返回pdPASS才说明创建成功。之前见过有人在main里连写6个xTaskCreate完全忽略返回值任务创建失败了就静默失败系统“看起来”跑起来了但任务少了功能就不正常。把返回值打印出来如果某个任务返回的是errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY那就是内存不足得调大堆或者缩小任务栈。第二用vTaskList或者vTaskGetRunTimeStats查看任务运行状态。vTaskList需要打开configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS它能把任务名、状态、栈高水位线、优先级都列出来。如果某个任务的栈高水位线几乎为0说明这个任务栈快爆了。第三监控空闲任务的运行时间占比。如果是假芯片RAM不足导致内存分配失败空闲任务的运行时间比例会异常高超过99%因为大部分任务都没被调度起来。如果空闲任务占比正常但任务诡异的“失联”那大概率是某个任务进入了死循环或永久阻塞跟芯片关系不大了。5. 如何从源头避开假芯片以及买到芯片后的三道验证关排查了半天最终还是要从源头解决问题。买STM32F103几个渠道的靠谱程度完全不一样。5.1 采购渠道按优先级排原厂授权分销商比如得捷电子、贸泽电子、安富利价格偏高但货源最可靠。ST官方天猫旗舰店或者ST代理商的电商平台良莠不齐要看是不是官方背书。某宝个人店铺价格诱人但翻车概率极高尤其是标注“国产替代”“兼容ST”的基本可以默认是GD32或者APM32的打磨片除非你明确要买国产型号。拆机板/二手市场只适合做实验和验证代码千万别用在批量产品上。5.2 三种验证手段我只挑最实用且成本可控的说第一用J-Flash或者STM32CubeProgrammer读芯片的IDCODE和Flash容量选项字节。这个方法最直接成本为零只需要一个ST-Link。连上芯片后如果Flash容量选项字节和丝印型号对不上直接退货。第二用示波器测外部晶振引脚波形。正常外部晶振起振后OSC_OUT引脚能测到稳定正弦波频率跟晶振标称值一致。如果完全没有波形大概率是代码配置了内部时钟或者晶振相关的负载电容有问题但结合“芯片丝印正常却怎么都不起振”这种情况就要考虑芯片内部的RTC振荡器是否损坏。第三跑一个压力测试程序。把芯片的所有外设全部初始化一遍——SPI、I2C、USART、ADC、定时器、PWM——每个外设都做一个回环测试。这个方法能发现“引脚内部未连接”“外设被阉割”的假芯片。写测试程序不需要太复杂关键是覆盖所有功能模块。我一般用UART回环测试TX接RX外部短路发送固定数据再接收校验是否正确、SPI内部Flash/外部EEPROM读写测试、定时器输出波形比对测试这三项基本能发现大部分问题。5.3 复盘当时那批“假芯片”到底是怎么回事回到文章开头说的那次经历。当时查到最后我把芯片拆下来用显微镜看丝印确实发现M标志有点异样但程度有限还不是一眼假。真正让我确认的是读Flash容量选项字节——丝印上写着CBT6128KB实际读出来是64KB。而FreeRTOS跑不起来的直接原因也很清晰CBT6和C8T6的Flash布局虽然容量不同但在硬件上CRC校验寄存器地址有差异。我用CBT6的选项字节参数替换工程后代码重新编译烧录仍然跑不起来。最后换成一颗从可靠渠道买的正品CBT6同样的代码、同样的FreeRTOS配置上电后一切正常。那一次经历让我养成了一个习惯无论是拿开发板做实验还是做小批量产品新芯片到手先花三分钟读ID和Flash容量再烧一个几分钟就能跑完的裸机外设自检程序。这“三分钟”看起来耽误工夫实际上比后面几天排查问题划算得多。6. 写在最后的一些经验和建议跟STM32F103和FreeRTOS打了这么些年交道踩过数不清的坑有些经验对刚入门的朋友可能更有用。6.1 如果调试器连不上先检查这几样ST-Link驱动是否正常设备管理器里识别到的是什么设备。目标板供电电压是否是3.3V如果调试器给板子供电注意板子是否存在短路导致电压被拉低。连线长度和接线方式。SWD其实只需要4根线SWDIO、SWCLK、GND、3.3V但线序接反是最常见的低级错误。如果还连不上试试用STM32CubeProgrammer的连接选项里选“Connect under reset”在复位期间建立初始连接能解决很多“芯片锁死”的误判。6.2 FreeRTOS配置的一个推荐基准值给用F103的朋友一个可以直接抄作业的FreeRTOSConfig.h关键配置基准当然要根据自己的项目调整configCPU_CLOCK_HZ如果是外部8MHz晶振系统时钟72MHz填(72000000)。configTICK_RATE_HZ默认1000如果任务切换很频繁可以降到100减少SysTick中断开销。configMAX_PRIORITIES5就够用任务优先级范围0-4优先级5以上不要直接使用。configMINIMAL_STACK_SIZE128字不是字节这是空闲任务的最小栈也就是512字节。configTOTAL_HEAP_SIZE我一般用12KB起步任务多、队列多就按需调整。C8T6有20KB RAM堆全局变量任务栈的总和不要超过18KB留一点余量给中断嵌套。configUSE_TIME_SLICING1启用时间片轮转尤其适合多个同优先级任务轮流执行。6.3 最后分享一个我常说的“三板斧”排查法遇到STM32F103FreeRTOS的“芯片没反应”从怀疑假芯片开始当然可以但更高效的做法是先把“假芯片”问题放在最后怀疑先走三板斧第一板斧确认硬件基础供电、复位、时钟、BOOT。用示波器看NRST引脚电平用示波器看外部晶振是否起振用万用表量VDD和VDDA确认BOOT0是低电平。 第二板斧烧裸机最小程序LED闪烁串口打印。如果裸机程序跑不通跟FreeRTOS没关系。 第三板斧把FreeRTOS任务逐一添加每加一个任务就验证一下。如果加某个任务后系统开始异常问题就锁定在你刚加的这个任务里——不管是栈溢出、内存不足、优先级配置还是硬件外设冲突都能快速暴露。三板斧都走完了还没解决再去找供应商的麻烦。先自己排查到能排除99%的可能性再怀疑芯片本身才能做到有理有据。假芯片在市场上的比重虽然不算低但也不至于每块都是假的——盲目怀疑芯片反倒容易把自己带偏。
返回列表