前言

在STM32开发中,你可能会遇到一种情况:同一批采购的芯片,型号和电路完全相同,但有的能顺利下载程序,有的却始终失败。这很可能是因为其中混入了仿冒或Remark(重新打标)的芯片。这些芯片在关键细节上与正品存在差异,导致下载失败。本文将介绍一种使用J-Link命令行工具进行快速初步判别的方法,虽然不能保证100%准确,但能有效筛查绝大多数异常芯片,为你的项目质量把关。

使用JLink命令行

首先我们需要打开JLink的命令行,这里推荐几种方法:

  • 如果安装了JLink驱动,可以在桌面上直接找到JLink.exe程序,双击打开
  • 如果安装了Keil5:
    • 打开Keil5安装目录,按照这个目录寻找:Keil\ARM\Segger\JLink.exe,双击打开
    • 打开Keil5软件,点击魔法棒(Options for Target),点击右上角Debug,右上角选择J-LINK,点击Settings,点击右下角JLink Cmd

初步判定STM32芯片

大致流程

读 DBGMCU_IDCODE(设备 ID / 修订版)

读地址:0xE0042000(F1/F4 都是这个调试寄存器地址)
作用:拿到 DEV_ID(芯片型号族) + REV_ID(修订版)
命令:mem32 0xE0042000 1
解释:这个寄存器在 ST 的参考手册里定义(F1 在 RM0008 里就能查到)。
注意:很多兼容/仿品会刻意做成相同 DEV_ID,所以它是“入门筛查”,不是铁证。

读 电子签名区(Electronic signature)

这是最常用、最好用的一组“像不像 ST”的证据:
Flash 容量寄存器(Flash size register)
F1:0x1FFFF7E0(16-bit)
F4:0x1FFF7A22(16-bit)
唯一 ID(Unique device ID / UID)
F1:0x1FFFF7E8 起(96-bit = 3 个 32-bit)
F4:0x1FFF7A10 起(96-bit = 3 个 32-bit)
如果读出来全是 0xFFFFFFFF 或者读不到,往往说明:
选错了系列地址(比如把 F4 当 F1 去读),或目标被读保护/映射限制(少见),或芯片实现不兼容(可疑点)。

读 System Memory(Bootloader ROM)向量表看“有没有 ST 的系统 Bootloader”

F1 System memory:0x1FFFF000 起
F4 System memory:0x1FFF0000 起(很多 F4 都是这个区间,RM0401 给出 system memory 映射范围)
读前 64 字节通常能看到一张“像样的向量表”(首字是栈顶指针,第二个字是 Reset_Handler 地址,且地址落在 system memory 范围内)。这对“像 ST”很有帮助。

读 Option Bytes 看布局/典型值是否像 ST

F1 Option bytes:0x1FFFF800 起
F4 Option bytes(在 system memory 空间的 option bytes 区):0x1FFFC000 起(见 ST 编程手册 PM0081)

JLink命令行基本知识

连接与基础设置命令

J-Link>device STM32F407VG      ; 或 STM32F103C8 等
J-Link>si SWD                  ; 选择 SWD 接口
J-Link>speed 4000              ; SWD 时钟 4MHz(不稳定就降到 1000/400)
J-Link>connect                 ; 连接目标
J-Link>r                       ; reset
J-Link>h                       ; halt(停核,读内存更稳)

device:告诉 J-Link 用哪个芯片的 flash 算法/内存布局(不影响 mem32 读寄存器,但影响擦写/下载)。
si / speed / connect:连接步骤。
r / h:复位并停住内核,避免程序跑飞导致调试口不稳定。

注意:使用时将J-Link>这部分去除

读内存命令(mem8 / mem16 / mem32)的SEGGER 语法是:

Mem8 [<Zone>:]<Addr> <NumItems>
Mem16 [<Zone>:]<Addr> <NumItems>
Mem32 [<Zone>:]<Addr> <NumItems>

判断F4的完整命令

说明:Flash/UID 地址来自 ST 参考手册的 Electronic signature 章节:UID=0x1FFF7A10,FlashSize=0x1FFF7A22

device STM32F407VG
si SWD
speed 4000
connect
r
h

; 1) 设备ID/修订版(通用)
mem32 0xE0042000 1

; 2) Flash容量(F4:0x1FFF7A22,16-bit)
mem16 0x1FFF7A22 1

; 3) UID(F4:0x1FFF7A10 起,3个32-bit)
mem32 0x1FFF7A10 3

; 4) System memory 向量表(F4 system memory 0x1FFF0000)
mem8  0x1FFF0000 64

; 5) Option bytes(常见在 0x1FFFC000)
mem32 0x1FFFC000 4

这些地址怎么来的?
0x1FFF7A10 / 0x1FFF7A22:ST 参考手册 Electronic signature / Flash size register 定义给出的。
0x1FFF0000 system memory 区间:RM0401 的 memory mapping / flash organization 表里给出 system memory 映射范围。
0x1FFFC000 option bytes:ST 编程手册 PM0081 明确写了 Option bytes 地址范围。

判断F1的完整命令

说明:F1 的电子签名/系统区地址来自 RM0008:
Flash size register:0x1FFFF7E0
UID:0x1FFFF7E8
System memory:0x1FFFF000
Option bytes:0x1FFFF800

device STM32F103C8
si SWD
speed 4000
connect
r
h

; 1) 设备ID/修订版(通用)
mem32 0xE0042000 1

; 2) Flash容量(F1:0x1FFFF7E0,16-bit)
mem16 0x1FFFF7E0 1

; 3) UID(F1:0x1FFFF7E8 起,3个32-bit)
mem32 0x1FFFF7E8 3

; 4) System memory 向量表(F1:0x1FFFF000)
mem8  0x1FFFF000 64

; 5) Option bytes(F1:0x1FFFF800)
mem8  0x1FFFF800 64

如何判断

先读 Flash size + UID(用正确系列地址)
能读到合理值(不是全 FF/全 00),且 Flash size 符合买的型号标称 → 很像 ST/兼容实现正常
读 system memory 向量表
前两个 word 像样(SP 在 0x2000xxxx,Reset_Handler 在 system memory 范围内)→ 极像 ST 带 ROM bootloader
读 option bytes
看到 AA/55 互补、写保护/读保护字段像 ST → 再加分
DBGMCU_IDCODE
DEV_ID 若完全不对 → 基本就不是选的那颗系列(或强不兼容实现)
DEV_ID 对也不代表一定原厂(高仿能伪造)

当然还有更简单的方法,就是将之前的命令得到的值全部扔给AI,让他帮你判断(非常推荐)

解析

用 J-Link 判断的通用思路

用 SWD 连上以后,要读三类“很难伪装”的信息:

DBGMCU_IDCODE(设备ID + 修订版)

  • 地址固定:0xE0042000
  • 读出来的 DEV_ID(低 12bit)能判断“属于哪个系列/哪类芯片”,REV_ID(高 16bit)能看硅版本。
  • 这是调试模块寄存器,很多“贴标/移植内核”的芯片这里会暴露差异。
    来源:F1 参考手册 RM0008 明确给出 DBGMCU_IDCODE Address: 0xE0042000,并定义 REV_ID/DEV_ID 位域。

Device electronic signature(电子签名区):Flash 容量寄存器 + UID

  • Flash size register:读出工厂烧录的“官方声明容量(KB)”
  • Unique ID (96-bit UID):读出 96bit 唯一ID
    这些地址随系列不同(F1 和 F4 不一样),都在各自参考手册的 Device electronic signature 章节里给出:
  • F1:RM0008:Flash size 基址 0x1FFF F7E0,UID 基址 0x1FFF F7E8
  • F4:常用基址:UID 0x1FFF7A10、Flash size 0x1FFF7A22(很多资料/代码也按这个)

System memory(系统存储器/Bootloader 区)+ Option bytes(选项字节)

  • system memory 用来放 ST 出厂 Bootloader,读它的“向量表开头”通常不会全是 FF。
  • option bytes 能看 RDP 读保护 等状态(如果开了读保护,读某些区域可能全 FF/报错)。
    来源(F1):RM0008 内存映射表给出System memory 0x1FFF F000 - 0x1FFF F7FF、Option Bytes 0x1FFF F800 - 0x1FFF F80F
    来源(F4):PM0081 明确给出 F4 选项字节在 0x1FFF C000

每条 J-Link 命令:是在干什么?

J-Link>device STM32F407VG
  • 告诉 J-Link 目标芯片型号。
  • 作用:让 J-Link 选择正确的 Flash 编程算法、内存布局、复位方式 等。
  • 如果这里选错型号:loadfile/erase 之类可能失败,或者写到不对的地方。
J-Link>si SWD
  • 选择调试接口:SWD(两线)而不是 JTAG(四/五线)。
J-Link>speed 4000
  • 设置 SWD 时钟(kHz)。4000 = 4MHz。
  • 线长/板子差时可降到 1000/500 提升稳定性。
J-Link>connect
  • 连接目标并做一次目标探测:读取 DPIDR、扫描 AP、读 CPUID、识别内核等。
J-Link>r
J-Link>h
  • reset(复位)。通常等价于让 MCU 复位一次(具体方式看 J-Link 实现/芯片支持)。
  • halt(停核)。让 CPU 停在当前状态,避免读写内存时程序在跑导致数据变化。

mem8 / mem16 / mem32:为什么要分 8/16/32?

J-Link>mem32 <addr> <count>
J-Link>mem16 <addr> <count>
J-Link>mem8  <addr> <count>
  • 这是 按 32位/16位/8位宽度 读内存/寄存器。
  • 之所以要区分,是因为很多寄存器在手册里写了“只支持 32bit 访问”或“该字段是 16bit”。
  • 例如 F1 的 DBGMCU_IDCODE 明确写 Only 32-bits access supported,所以用 mem32 0xE0042000 1 最标准。
  • F1 的 Flash size register 位域是 15:0,用 mem16 读更直观

这些地址的由来

通用:0xE0042000 为什么是设备ID?

  • 这是 DBGMCU(调试支持模块)里的 IDCODE 寄存器,用来给调试器识别芯片型号/修订版。
  • F1 的 RM0008 直接写了:
  • DBGMCU_IDCODE Address: 0xE0042000
  • 高 16 位 REV_ID,低 12 位 DEV_ID(其余保留)
    怎么用它判断?
  • 读出一个 32 位值,比如读到的 0x101F6413:
  • DEV_ID = value & 0xFFF = 0x413(这类值经常对应 F4 系列的某些器件ID;如果选的是 F407,但 DEV_ID 明显不对,就高度可疑)
  • REV_ID = value >> 16 = 0x101F(硅版本)
    注意:DEV_ID 只能说明“芯片属于哪一类 die/系列”,不能 100% 证明“原厂/国产”。但它是第一道门槛:贴标很容易在这里露馅。

STM32F1(以 STM32F103C8 为例):这些地址在 RM0008 哪里?

Flash 容量寄存器:0x1FFF F7E0

  • RM0008 “Device electronic signature” → “Flash size register” 写明:
    • Base address: 0x1FFF F7E0
    • F_SIZE 表示 Flash 容量(单位 KB)
J-Link>mem16 0x1FFFF7E0 1

读出来若是 0x0040 就是 64KB(典型 F103C8 标称)。
如果读出 0x0080 就是 128KB(常见“C8 实际是 CB/128KB”的情况)。

UID:0x1FFF F7E8

  • 同一章节写明:UID 基址 0x1FFF F7E8,96bit 读三次 32bit 即可。
J-Link>mem32 0x1FFFF7E8 

System memory:0x1FFF F000(Bootloader 所在)

  • RM0008 内存映射表写了 System memory 0x1FFF F000 - 0x1FFF F7FF
J-Link>mem8 0x1FFFF000 64

看向量表开头是否“像样”(一般不是全 FF)。

Option bytes:0x1FFF F800

  • 同一张表给了 Option Bytes 0x1FFF F800 - 0x1FFF F80F。
J-Link>mem8 0x1FFFF800 64

这里能间接判断是否开了读保护、写保护等(但具体位意义要看 Flash programming manual/该系列说明)。

STM32F4(以 STM32F407 为例):这些地址怎么来的?

Flash 容量寄存器:0x1FFF7A22(16-bit)
UID:0x1FFF7A10 起,读 3 个 32-bit
这两组地址属于 F4 系列“电子签名区”的常用固定映射(很多库/资料/例程都会按这个读),例如这里给出了读取方式:

  • flash_read(0x1FFF7A10 + 0x00/+0x04/+0x08) 读 UID 三个 word
  • 读取 Flash size 的地址是 0x1FFF7A22
J-Link>mem16 0x1FFF7A22 1
J-Link>mem32 0x1FFF7A10 3

Option bytes:0x1FFF C000(F4 常见)

  • F4 的 Flash programming manual PM0081 的表格直接写:option bytes word 地址 0x1FFF C000
J-Link>mem32 0x1FFFC000 4

System memory:用的 0x1FFF0000

  • 这是 F4 系列常用的 system memory(bootloader)映射起点之一(不同系列/子系列会略有差异),做法上就是:
    • 去该系列 Reference Manual 的 memory map 找 “System memory” 的起始地址
    • 然后 mem8 读前 64 字节看向量表

完整命令

F4(以 F407 为例)

J-Link>device STM32F407VG      ; 选芯片型号(影响 flash 算法/内存布局)
J-Link>si SWD                 ; 选 SWD
J-Link>speed 4000             ; SWD 时钟 4MHz
J-Link>connect                ; 连接并探测
J-Link>r                      ; 复位
J-Link>h                      ; 停核

J-Link>mem32 0xE0042000 1     ; DBGMCU_IDCODE:设备ID/修订版(通用,强识别点)

J-Link>mem16 0x1FFF7A22 1     ; F4 Flash size(KB)
J-Link>mem32 0x1FFF7A10 3     ; F4 UID(96-bit)

J-Link>mem8  0x1FFF0000 64    ; F4 System memory 向量表(bootloader 区开头)
J-Link>mem32 0x1FFFC000 4     ; F4 Option bytes(读保护/写保护等)

注意:J-Link命令行中输入时,需要去掉每行开头的 J-Link> 提示符

F1(以 F103C8 为例)

J-Link>device STM32F103C8
J-Link>si SWD
J-Link>speed 4000
J-Link>connect
J-Link>r
J-Link>h

J-Link>mem32 0xE0042000 1     ; DBGMCU_IDCODE(通用):contentReference[oaicite:14]{index=14}

J-Link>mem16 0x1FFFF7E0 1     ; F1 Flash size(基址 0x1FFF F7E0):contentReference[oaicite:15]{index=15}
J-Link>mem32 0x1FFFF7E8 3     ; F1 UID(基址 0x1FFF F7E8):contentReference[oaicite:16]{index=16}

J-Link>mem8  0x1FFFF000 64    ; F1 System memory(0x1FFF F000 起):contentReference[oaicite:17]{index=17}
J-Link>mem8  0x1FFFF800 64    ; F1 Option bytes(0x1FFF F800 起):contentReference[oaicite:18]{index=18}

注意:J-Link命令行中输入时,需要去掉每行开头的 J-Link> 提示符

判定真伪/贴标操作

先看 DBGMCU_IDCODE 的 DEV_ID 是否合理

  • F1(中密度常见)DEV_ID=0x410 在 RM0008 就明确列出来了。
  • 如果选的是 F103C8,但读出来 DEV_ID 完全不是 0x410/0x412/0x414 这类范围,基本就不是对应 die。
    再看 Flash size register 是否和丝印/选择的型号一致
  • F4 读到 0x0200=512KB,如果丝印是 1MB 档,就很可疑(贴标/选型错误/翻新混料)。
  • F1 很多“C8 实际是 128KB”会表现为 0x0080,这更像“同系列不同容量”而不一定是国产仿品。
    如果读出来一片 FFFFFFFF
  • 优先怀疑:地址用错系列
  • 其次才怀疑:RDP/安全保护、连线不稳、掉电等。
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐