如何使用 OpenOCD ping 芯片(检测芯片是否已连接)
How to ping a chip (detect if a chip is connected) with OpenOCD
1。问题解释
我正在尝试将 OpenOCD 用于一些不常见的事情。我只想 检测 芯片,而不是 连接 芯片。
我想到的程序如下所示:
Start OpenOCD with the probe config file (eg. stlink.cfg
) given as -f
parameter. So OpenOCD knows what probe to use, but doesn't know what chip it will find.
OpenOCD detects a chip and reports this somehow (eg. write something to stdout). If possible, this action should not be intrusive to the chip (like resetting it).
OpenOCD shuts down.
以下是有关该过程的更多说明:
注意 1: 如果 OpenOCD 没有达到我需要设置 Telnet 或 GDB 的 服务器状态 就好了客户端与之交互。我很乐意以更方便的方式报告芯片检测,例如在 stdout 通道上获取芯片信息。
注2:检测应该是对芯片无干扰的。但是,如果 OpenOCD 没有找到任何东西,我想要一个备用方法,OpenOCD 会尝试更积极地寻找芯片(比如按住 nRST
引脚)。如果需要,我可以自己调用其他方法(因此 OpenOCD 不需要自动执行此操作)。
注3:一开始,我只是把这个"chip detection"应用在带有STLinkV2或ST[=208的STM32芯片上=]V3 探头,稍后还有其他探头和芯片。
注4:有些板只有一个SWD连接(没有JTAG)。
注意 5: 我正在 Windows 10 计算机上工作,并获得了最新的 OpenOCD 版本(版本 0.10.0_dev00921,基于 2019 年 7 月 6 日)从 https://www.playembedded.org/blog/download/
下载
2。到目前为止我尝试了什么
先生Tommy Murphy 让我参考了 OpenOCD 参考手册中的第 10.7 节(参见 http://openocd.org/doc/pdf/openocd.pdf)。我已阅读该部分并观察了以下示例:
# openocd.cfg file
# -----------------
source [find interface/olimex-arm-usb-tiny-h.cfg]
reset_config trst_and_srst
jtag_rclk 8
因为我的芯片通过STLink probe连接,使用SWD传输协议(而不是JTAG),我对示例做了一些修改:
# openocd.cfg file
# -----------------
source [find interface/stlink.cfg]
transport select hla_swd
reset_config srst_only
adapter_khz 480
我将 NUCLEO_F303K8 板连接到我的 PC 以进行此测试。然后我在控制台中发出以下命令:
> openocd -s "C:\...\scripts" -f "C:\...\openocd.cfg"
OpenOCD 输出以下内容然后终止:
Open On-Chip Debugger 0.10.0+dev-00921-gef8c69ff9 (2019-07-06-01:00)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 480 kHz
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 480 kHz
Error: BUG: current_target out of bounds
所以我最后提出了几个关于自动探测的问题。
3。我的问题
问题一:
"Autoprobing"(如第 10.7 节所述)真的是我需要的吗?如果回答否,请忽略后面的问题。
问题二:
我试图模仿第 10.7 节中给出的示例,并进行一些小的修改以使该示例适合我的 Nucleo 板。不幸的是,自动探测失败了。这是因为 OpenOCD 不支持使用 SWD 协议进行自动探测吗?或者我只是在我的 .cfg
文件中犯了一个错误?
问题三:
我注意到第 10.7 节中的自动探测示例配置了 OpenOCD 的重置行为。这是否意味着 Autoprobing 在重置芯片的意义上总是 "intrusive"?
问题四:
无论如何,第 10.7 节中的自动探测示例似乎将 OpenOCD 带入了 服务器状态 。有可能避免这种情况吗?我想让这个 "chip detection" 事情变得简单,而不需要 Telnet 或 GDB 客户端。
编辑
感谢@nattgris 的精彩回答。不过我还有一些更实际的问题。
1。用ST-Link
假设我们正在使用 ST-Link,尽管它与 OpenOCD 的合作不是最理想的。你说:
.. if all you need is to know is whether a chip is there at all, in some configurations the ST-Link can probably be persuaded to give you that info.
我如何实际说服 ST-Link 这样做?换句话说,我应该在我的 openocd.cfg
文件中放入什么来实现这个?
2。使用 SWD 探针(但不是 ST-Link)
假设我们使用的是真正的 SWD 探针。你说:
Autoprobing, as described in Section 10.7, is only relevant for JTAG [...]. Simply connecting via SWD prints the corresponding information (the DPIDR
register instead of the TAP IDCODE
). So either way, you can get similar info about the chip over both protocols. [...]
For all Cortex-chips, you will basically get "ARM" instead of the actual manufacturer of the chip (e.g. "ST"). Though ST (and perhaps other manufacturers) chips have a separate boundary scan TAP (i.e. JTAG only) that provides an actual ST IDCODE
that can be used for chip identification.
据此,我得出结论:
第 10.7 节中描述的自动探测仅适用于 JTAG,不适用于 SWD。
由于自动探测不适用于 SWD,另一种方法是 简单地连接 到芯片,之后 OpenOCD 自动打印 DPIDR
登记。这个DPIDR
寄存器相当于JTAG TAPIDCODE
的SWD,可以说,可以在一定程度上识别芯片。
但是,如果一开始就不知道 PC 上连接的是什么芯片, 如何简单地将 连接到芯片上呢?如果我没记错的话,OpenOCD 总是需要特定的配置文件,如 stm32f7x.cfg
、stm32f4x.cfg
、stm32l0.cfg
、...来连接到芯片。
显然,JTAG IDCODE
和 SWD 等价物 DPIDR
寄存器提供给芯片设计者,对于 ARM-Cortex 芯片来说总是 "ARM" .这对于完整的芯片识别是不够的。但是,您说 ARM 芯片具有单独的边界扫描 TAP,可提供更多 IDCODE
寄存器以实现更完整的识别。不幸的是,这些都是 JTAG-only。这意味着SWD在芯片识别方面走上了死胡同?
使用 JTAG 进行自动探测(因此读取 IDCODE
reg)可以是完全非侵入式的。因此,可以使系统复位信号不可用:
reset_config none
你说通过 SWD 读取 DPIDR
(我认为它是 JTAG 的 SWD 等价物自动探测)也是非侵入式的。我还可以通过使重置信号不可用来强制执行 "non-intrusiveness" 吗?
3。使用 JTAG 探针(但不是 ST-Link)
JTAG 协议似乎为芯片识别提供了最好的支持(使用 Autoprobing)。我的结论:
第 10.7 节中描述的自动探测将从芯片打印 TAP IDCODE
。对于只打印 "ARM",而不是实际制造商(如 "ST")和芯片名称(如 "STM32F767ZI")的 ARM 芯片。
我如何切实确保该程序还打印这些更多信息,尤其是实际芯片名称?换句话说,我应该在 openocd.cfg
文件(可能还有 openocd 启动命令)中放入什么来实现这个?
非常感谢:-)
问题一:
这是你需要的吗?要看。如 10.7 节所述,自动探测仅与 JTAG 相关。因此,它本身无法满足您的需求。但是简单地通过 SWD 连接会打印出相应的信息(DPIDR 寄存器而不是 TAP IDCODE)所以无论哪种方式,您都可以通过两种协议获得关于芯片的类似信息。
但是,我不确定这对您来说是否足够。如果你只想检测一个芯片(任何芯片)有响应,这可能就足够了。如果您还需要详细识别芯片,通常需要进一步检查,因为您通过这两种方法获得的 ID 代码可以识别芯片的设计者。所以对于所有Cortex-chips,你基本上会得到"ARM"而不是芯片的实际制造商(例如"ST")。虽然 ST(可能还有其他制造商)芯片有一个单独的边界扫描 TAP(即仅 JTAG),它提供可用于芯片识别的实际 ST IDCODE。
但是,由于 SWD 仅与 ARM Cortex-type(或更确切地说是 ADI v5)目标相关,如果您可以使用 SWD,您还可以读取调试组件的 ROM Table,它提供其中包括芯片制造商:
# Your JTAG adapter config
script interface.cfg
transport select swd
adapter_khz 100
swd newdap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
init
dap info
shutdown
STM32F103 的输出:
Info : SWD DPIDR 0x1ba01477
Info : chip.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
AP ID register 0x14770011
Type is MEM-AP AHB
MEM-AP BASE 0xe00ff003
Valid ROM table present
Component base address 0xe00ff000
Peripheral ID 0x00000a0410
Designer is 0x0a0, STMicroelectronics
Part is 0x410, Unrecognized
Component class is 0x1, ROM table
MEMTYPE system memory present on bus
ROMTABLE[0x0] = 0xfff0f003
Component base address 0xe000e000
Peripheral ID 0x04001bb000
Designer is 0x4bb, ARM Ltd.
Part is 0x0, Cortex-M3 SCS (System Control Space)
Component class is 0xe, Generic IP component
ROMTABLE[0x4] = 0xfff02003
Component base address 0xe0001000
Peripheral ID 0x04001bb002
Designer is 0x4bb, ARM Ltd.
Part is 0x2, Cortex-M3 DWT (Data Watchpoint and Trace)
Component class is 0xe, Generic IP component
ROMTABLE[0x8] = 0xfff03003
Component base address 0xe0002000
Peripheral ID 0x04000bb003
Designer is 0x4bb, ARM Ltd.
Part is 0x3, Cortex-M3 FPB (Flash Patch and Breakpoint)
Component class is 0xe, Generic IP component
ROMTABLE[0xc] = 0xfff01003
Component base address 0xe0000000
Peripheral ID 0x04001bb001
Designer is 0x4bb, ARM Ltd.
Part is 0x1, Cortex-M3 ITM (Instrumentation Trace Module)
Component class is 0xe, Generic IP component
ROMTABLE[0x10] = 0xfff41003
Component base address 0xe0040000
Peripheral ID 0x04001bb923
Designer is 0x4bb, ARM Ltd.
Part is 0x923, Cortex-M3 TPIU (Trace Port Interface Unit)
Component class is 0x9, CoreSight component
Type is 0x11, Trace Sink, Port
ROMTABLE[0x14] = 0xfff42002
Component not present
ROMTABLE[0x18] = 0x0
End of ROM table
对于 non-Cortex 芯片,仅使用自动探测的 JTAG TAP IDCODE,您将获得很好的识别,就像这个使用旧 STR750 的示例:
# Your JTAG adapter config
script interface.cfg
transport select jtag
adapter_khz 100
init
shutdown
Info : JTAG tap: auto0.tap tap/device found: 0x4f1f0041 (mfg: 0x020 (STMicroelectronics), part: 0xf1f0, ver: 0x4)
问题二:
如上所述,"autoprobing" 仅与 JTAG 相关,但您也可以通过 SWD 获得相同的功能(读取 ID 代码)。不幸的是,这对您没有帮助,因为您无权访问任何一种协议!
问题是你使用了ST-Link。不管人们倾向于怎么想,这 不是 真正的 JTAG/SWD 适配器。是的,它同时支持 JTAG 和 SWD,但它完全隐藏了适配器固件中的协议。它仅向主机 (OpenOCD) 提供 high-level 命令集,类型为 "Reset the target"、"Step the target"、"Read this memory" 等。因此,OpenOCD 支持 ST-Link 是一个丑陋的 hack,它位于 target 层而不是 adapter 层。因此,OpenOCD 的大多数适配器、传输或 DAP-level 功能根本不存在,并且 OpenOCD 意义上的自动探测与您的设置完全无关。
对于简单的闪烁和非常基本的 GDB 调试,ST-Link 有效。但是对于更多 low-level,请远离 ST-Link。对于 OpenOCD 来说,这根本不是一个很好的匹配项。
也就是说,如果您只需要知道芯片是否存在,在某些配置中,ST-Link 可能会被说服为您提供该信息,例如使用以下配置文件:
script interface/stlink.cfg
transport select hla_swd
adapter_khz 100
hla newtap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
你会得到
Warn : UNEXPECTED idcode: 0x2ba01477
或
Error: init mode failed (unable to connect to the target)
其余问题与 ST-Link 无关,因此我假设您切换到真正的 JTAG/SWD 适配器。
问题三:
JTAG 自动探测,以及通过 SWD 读取 DPIDR,完全是 non-intrusive。对于一般的 Cortex-M 目标,大多数对目标的调试访问是 non-intrusive,因此您可以 read/write 内存等,而目标是 运行 几乎不影响它。
JTAG 根本没有定义或要求系统复位信号可用。没有它自动探测工作正常,你应该可以使用
reset_config none
问题四:
您想完全避免启动 gdb server/telnet 服务器吗?然后您可以使用以下配置禁用它们:
gdb_port disabled
telnet_port disabled
tcl_port disabled
不过如果你只是启动OpenOCD检测一个芯片然后关闭它,暂时启动这些服务可能无论如何都没有问题。
此外,至少 GDB 服务器仅在创建 目标 后启动,这对于执行 JTAG 自动探测不是必需的。
总结
是的,您应该可以做您想做的事,但 ST-Link 可能做不到。使用真正的适配器,您可以执行 JTAG 自动探测以在扫描链上打印检测到的 TAP。对于 SWD,OpenOCD 始终打印检测到的 DPIDR 寄存器(如果未找到目标,通常会中断;输出至少会有所不同)。
Connection/detection 可以完全 non-intrusive,如果目标本身支持它,就像大多数 Cortex-M 一样。如果目标固件已禁用调试引脚或关闭调试逻辑,您可能需要保持或脉冲复位,具体取决于目标。
使用主线 OpenOCD 代码,您可以轻松访问目标内存。您可以从目标读取一些识别数据对其进行解码并检测芯片。
顺便说一句,这可能不适用于 STLink 等高级适配器。请使用通用适配器(J-Link、FTDI-based 适配器、CMSIS-DAP 等)。
source [find interface/jlink.cfg]
transport select swd
adapter_khz 1000
set _CHIPNAME generic_dap_access
# 1. DECLARE A DAP
# -----------------
# Declare a single DAP (a DAP is the SWD counterpart for a JTAG TAP)
# for the chip's cpu. The command `swd newdap` has the same parameters
# as `jtag newtap`.
# param one: Name of the module in the JTAG scan chain (usually a chip).
# param two: Tapname, reflects the role of the TAP (bs, cpu, flash, ...).
# -irlen 4: Instruction register length is 4 bits
# -ircapture 0x1: The bit pattern loaded by the TAP into the JTAG shift register on entry
# to the ircapture state. Default is 0x01.
# -irmask 0xf: A mask used with-ircaptureto verify that instruction scans work correctly.
swd newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf
# 2. CREATE (?) A DAP AND LINK TO JTAG TAP
# -----------------------------------------
# Since OpenOCD version 0.11.0, the Debug Access Port (DAP) is no longer implicitely
# created together with the target. It must be explicitely declared.
# Declare a DAP instance named $_CHIPNAME.dap linked to the JTAG tap $_CHIPNAME.cpu.
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# Note: Observe important note in manual
# for ARMv6-M, ARMv7 and ARMv8 targets.
# 3. DECLARE SOME PROCEDURES
# ---------------------------
# 3.1 Writes 'val' to address 'addr' via AP 'ap'
proc mww_ll { ap addr val } {
global _CHIPNAME
# I'm a bit confused how the following commands achieve just that.
$_CHIPNAME.dap apreg $ap 0x04 $addr
$_CHIPNAME.dap apreg $ap 0x0C $val
}
# 3.2 Reads and displays data from address 'addr' via AP 'ap'
proc mdw_ll { ap addr } {
global _CHIPNAME
$_CHIPNAME.dap apreg $ap 0x04 $addr
$_CHIPNAME.dap apreg $ap 0x0C
}
# 3.3 Reads data from address 'addr' via AP 'ap' and returns it
# Can be used to read data and pass it to other commands
proc mrw_ll { ap addr } {
global _CHIPNAME
$_CHIPNAME.dap apreg $ap 0x04 $addr
set ap [ocd_$_CHIPNAME.dap apreg $ap 0x0C]
regsub -all {(\s*\n)+} $ap "" ap
return $ap
}
# 4. INITIALIZE
# --------------
init # <- What does this actually do? I'm used to see `reset-init`
# everywhere in OpenOCD, but I don't know what simple `init` does.
# 5. READ VALUE AT 0x10000000
# ----------------------------
# Reads and displays value at 0x10000000 <- Why? What's special about
mdw_ll 0 0x10000000 # this memory location?
# 6. MODIFY RAM DATA
# -------------------
# Modify some data in RAM <- Why?
mdw_ll 0 0x08000000
mww_ll 0 0x08000000 0xdeadbeef
mdw_ll 0 0x08000000
exit
OpenOCD 输出:
Open On-Chip Debugger 0.10.0+dev-01116-gfc2e5110d-dirty (2019-07-11-16:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
Info : J-Link Ultra V4 compiled May 27 2019 15:49:24
Info : Hardware version: 4.00
Info : VTarget = 4.850 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x6ba02477
Warn : gdb services need one or more targets defined
0x976562e5
0x20004602
0xdeadbeef
1。问题解释
我正在尝试将 OpenOCD 用于一些不常见的事情。我只想 检测 芯片,而不是 连接 芯片。
我想到的程序如下所示:
Start OpenOCD with the probe config file (eg.
stlink.cfg
) given as-f
parameter. So OpenOCD knows what probe to use, but doesn't know what chip it will find.OpenOCD detects a chip and reports this somehow (eg. write something to stdout). If possible, this action should not be intrusive to the chip (like resetting it).
OpenOCD shuts down.
以下是有关该过程的更多说明:
注意 1: 如果 OpenOCD 没有达到我需要设置 Telnet 或 GDB 的 服务器状态 就好了客户端与之交互。我很乐意以更方便的方式报告芯片检测,例如在 stdout 通道上获取芯片信息。
注2:检测应该是对芯片无干扰的。但是,如果 OpenOCD 没有找到任何东西,我想要一个备用方法,OpenOCD 会尝试更积极地寻找芯片(比如按住 nRST
引脚)。如果需要,我可以自己调用其他方法(因此 OpenOCD 不需要自动执行此操作)。
注3:一开始,我只是把这个"chip detection"应用在带有STLinkV2或ST[=208的STM32芯片上=]V3 探头,稍后还有其他探头和芯片。
注4:有些板只有一个SWD连接(没有JTAG)。
注意 5: 我正在 Windows 10 计算机上工作,并获得了最新的 OpenOCD 版本(版本 0.10.0_dev00921,基于 2019 年 7 月 6 日)从 https://www.playembedded.org/blog/download/
下载2。到目前为止我尝试了什么
先生Tommy Murphy 让我参考了 OpenOCD 参考手册中的第 10.7 节(参见 http://openocd.org/doc/pdf/openocd.pdf)。我已阅读该部分并观察了以下示例:
# openocd.cfg file
# -----------------
source [find interface/olimex-arm-usb-tiny-h.cfg]
reset_config trst_and_srst
jtag_rclk 8
因为我的芯片通过STLink probe连接,使用SWD传输协议(而不是JTAG),我对示例做了一些修改:
# openocd.cfg file
# -----------------
source [find interface/stlink.cfg]
transport select hla_swd
reset_config srst_only
adapter_khz 480
我将 NUCLEO_F303K8 板连接到我的 PC 以进行此测试。然后我在控制台中发出以下命令:
> openocd -s "C:\...\scripts" -f "C:\...\openocd.cfg"
OpenOCD 输出以下内容然后终止:
Open On-Chip Debugger 0.10.0+dev-00921-gef8c69ff9 (2019-07-06-01:00)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 480 kHz
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 480 kHz
Error: BUG: current_target out of bounds
所以我最后提出了几个关于自动探测的问题。
3。我的问题
问题一:
"Autoprobing"(如第 10.7 节所述)真的是我需要的吗?如果回答否,请忽略后面的问题。
问题二:
我试图模仿第 10.7 节中给出的示例,并进行一些小的修改以使该示例适合我的 Nucleo 板。不幸的是,自动探测失败了。这是因为 OpenOCD 不支持使用 SWD 协议进行自动探测吗?或者我只是在我的 .cfg
文件中犯了一个错误?
问题三:
我注意到第 10.7 节中的自动探测示例配置了 OpenOCD 的重置行为。这是否意味着 Autoprobing 在重置芯片的意义上总是 "intrusive"?
问题四:
无论如何,第 10.7 节中的自动探测示例似乎将 OpenOCD 带入了 服务器状态 。有可能避免这种情况吗?我想让这个 "chip detection" 事情变得简单,而不需要 Telnet 或 GDB 客户端。
编辑
感谢@nattgris 的精彩回答。不过我还有一些更实际的问题。
1。用ST-Link
假设我们正在使用 ST-Link,尽管它与 OpenOCD 的合作不是最理想的。你说:
.. if all you need is to know is whether a chip is there at all, in some configurations the ST-Link can probably be persuaded to give you that info.
我如何实际说服 ST-Link 这样做?换句话说,我应该在我的 openocd.cfg
文件中放入什么来实现这个?
2。使用 SWD 探针(但不是 ST-Link)
假设我们使用的是真正的 SWD 探针。你说:
Autoprobing, as described in Section 10.7, is only relevant for JTAG [...]. Simply connecting via SWD prints the corresponding information (the
DPIDR
register instead of the TAPIDCODE
). So either way, you can get similar info about the chip over both protocols. [...]
For all Cortex-chips, you will basically get "ARM" instead of the actual manufacturer of the chip (e.g. "ST"). Though ST (and perhaps other manufacturers) chips have a separate boundary scan TAP (i.e. JTAG only) that provides an actual STIDCODE
that can be used for chip identification.
据此,我得出结论:
第 10.7 节中描述的自动探测仅适用于 JTAG,不适用于 SWD。
由于自动探测不适用于 SWD,另一种方法是 简单地连接 到芯片,之后 OpenOCD 自动打印
DPIDR
登记。这个DPIDR
寄存器相当于JTAG TAPIDCODE
的SWD,可以说,可以在一定程度上识别芯片。
但是,如果一开始就不知道 PC 上连接的是什么芯片, 如何简单地将 连接到芯片上呢?如果我没记错的话,OpenOCD 总是需要特定的配置文件,如stm32f7x.cfg
、stm32f4x.cfg
、stm32l0.cfg
、...来连接到芯片。显然,JTAG
IDCODE
和 SWD 等价物DPIDR
寄存器提供给芯片设计者,对于 ARM-Cortex 芯片来说总是 "ARM" .这对于完整的芯片识别是不够的。但是,您说 ARM 芯片具有单独的边界扫描 TAP,可提供更多IDCODE
寄存器以实现更完整的识别。不幸的是,这些都是 JTAG-only。这意味着SWD在芯片识别方面走上了死胡同?使用 JTAG 进行自动探测(因此读取
IDCODE
reg)可以是完全非侵入式的。因此,可以使系统复位信号不可用:reset_config none
你说通过 SWD 读取DPIDR
(我认为它是 JTAG 的 SWD 等价物自动探测)也是非侵入式的。我还可以通过使重置信号不可用来强制执行 "non-intrusiveness" 吗?
3。使用 JTAG 探针(但不是 ST-Link)
JTAG 协议似乎为芯片识别提供了最好的支持(使用 Autoprobing)。我的结论:
第 10.7 节中描述的自动探测将从芯片打印 TAP
IDCODE
。对于只打印 "ARM",而不是实际制造商(如 "ST")和芯片名称(如 "STM32F767ZI")的 ARM 芯片。我如何切实确保该程序还打印这些更多信息,尤其是实际芯片名称?换句话说,我应该在
openocd.cfg
文件(可能还有 openocd 启动命令)中放入什么来实现这个?
非常感谢:-)
问题一:
这是你需要的吗?要看。如 10.7 节所述,自动探测仅与 JTAG 相关。因此,它本身无法满足您的需求。但是简单地通过 SWD 连接会打印出相应的信息(DPIDR 寄存器而不是 TAP IDCODE)所以无论哪种方式,您都可以通过两种协议获得关于芯片的类似信息。
但是,我不确定这对您来说是否足够。如果你只想检测一个芯片(任何芯片)有响应,这可能就足够了。如果您还需要详细识别芯片,通常需要进一步检查,因为您通过这两种方法获得的 ID 代码可以识别芯片的设计者。所以对于所有Cortex-chips,你基本上会得到"ARM"而不是芯片的实际制造商(例如"ST")。虽然 ST(可能还有其他制造商)芯片有一个单独的边界扫描 TAP(即仅 JTAG),它提供可用于芯片识别的实际 ST IDCODE。
但是,由于 SWD 仅与 ARM Cortex-type(或更确切地说是 ADI v5)目标相关,如果您可以使用 SWD,您还可以读取调试组件的 ROM Table,它提供其中包括芯片制造商:
# Your JTAG adapter config
script interface.cfg
transport select swd
adapter_khz 100
swd newdap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
init
dap info
shutdown
STM32F103 的输出:
Info : SWD DPIDR 0x1ba01477
Info : chip.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
AP ID register 0x14770011
Type is MEM-AP AHB
MEM-AP BASE 0xe00ff003
Valid ROM table present
Component base address 0xe00ff000
Peripheral ID 0x00000a0410
Designer is 0x0a0, STMicroelectronics
Part is 0x410, Unrecognized
Component class is 0x1, ROM table
MEMTYPE system memory present on bus
ROMTABLE[0x0] = 0xfff0f003
Component base address 0xe000e000
Peripheral ID 0x04001bb000
Designer is 0x4bb, ARM Ltd.
Part is 0x0, Cortex-M3 SCS (System Control Space)
Component class is 0xe, Generic IP component
ROMTABLE[0x4] = 0xfff02003
Component base address 0xe0001000
Peripheral ID 0x04001bb002
Designer is 0x4bb, ARM Ltd.
Part is 0x2, Cortex-M3 DWT (Data Watchpoint and Trace)
Component class is 0xe, Generic IP component
ROMTABLE[0x8] = 0xfff03003
Component base address 0xe0002000
Peripheral ID 0x04000bb003
Designer is 0x4bb, ARM Ltd.
Part is 0x3, Cortex-M3 FPB (Flash Patch and Breakpoint)
Component class is 0xe, Generic IP component
ROMTABLE[0xc] = 0xfff01003
Component base address 0xe0000000
Peripheral ID 0x04001bb001
Designer is 0x4bb, ARM Ltd.
Part is 0x1, Cortex-M3 ITM (Instrumentation Trace Module)
Component class is 0xe, Generic IP component
ROMTABLE[0x10] = 0xfff41003
Component base address 0xe0040000
Peripheral ID 0x04001bb923
Designer is 0x4bb, ARM Ltd.
Part is 0x923, Cortex-M3 TPIU (Trace Port Interface Unit)
Component class is 0x9, CoreSight component
Type is 0x11, Trace Sink, Port
ROMTABLE[0x14] = 0xfff42002
Component not present
ROMTABLE[0x18] = 0x0
End of ROM table
对于 non-Cortex 芯片,仅使用自动探测的 JTAG TAP IDCODE,您将获得很好的识别,就像这个使用旧 STR750 的示例:
# Your JTAG adapter config
script interface.cfg
transport select jtag
adapter_khz 100
init
shutdown
Info : JTAG tap: auto0.tap tap/device found: 0x4f1f0041 (mfg: 0x020 (STMicroelectronics), part: 0xf1f0, ver: 0x4)
问题二:
如上所述,"autoprobing" 仅与 JTAG 相关,但您也可以通过 SWD 获得相同的功能(读取 ID 代码)。不幸的是,这对您没有帮助,因为您无权访问任何一种协议!
问题是你使用了ST-Link。不管人们倾向于怎么想,这 不是 真正的 JTAG/SWD 适配器。是的,它同时支持 JTAG 和 SWD,但它完全隐藏了适配器固件中的协议。它仅向主机 (OpenOCD) 提供 high-level 命令集,类型为 "Reset the target"、"Step the target"、"Read this memory" 等。因此,OpenOCD 支持 ST-Link 是一个丑陋的 hack,它位于 target 层而不是 adapter 层。因此,OpenOCD 的大多数适配器、传输或 DAP-level 功能根本不存在,并且 OpenOCD 意义上的自动探测与您的设置完全无关。
对于简单的闪烁和非常基本的 GDB 调试,ST-Link 有效。但是对于更多 low-level,请远离 ST-Link。对于 OpenOCD 来说,这根本不是一个很好的匹配项。
也就是说,如果您只需要知道芯片是否存在,在某些配置中,ST-Link 可能会被说服为您提供该信息,例如使用以下配置文件:
script interface/stlink.cfg
transport select hla_swd
adapter_khz 100
hla newtap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
你会得到
Warn : UNEXPECTED idcode: 0x2ba01477
或
Error: init mode failed (unable to connect to the target)
其余问题与 ST-Link 无关,因此我假设您切换到真正的 JTAG/SWD 适配器。
问题三:
JTAG 自动探测,以及通过 SWD 读取 DPIDR,完全是 non-intrusive。对于一般的 Cortex-M 目标,大多数对目标的调试访问是 non-intrusive,因此您可以 read/write 内存等,而目标是 运行 几乎不影响它。
JTAG 根本没有定义或要求系统复位信号可用。没有它自动探测工作正常,你应该可以使用
reset_config none
问题四:
您想完全避免启动 gdb server/telnet 服务器吗?然后您可以使用以下配置禁用它们:
gdb_port disabled
telnet_port disabled
tcl_port disabled
不过如果你只是启动OpenOCD检测一个芯片然后关闭它,暂时启动这些服务可能无论如何都没有问题。
此外,至少 GDB 服务器仅在创建 目标 后启动,这对于执行 JTAG 自动探测不是必需的。
总结
是的,您应该可以做您想做的事,但 ST-Link 可能做不到。使用真正的适配器,您可以执行 JTAG 自动探测以在扫描链上打印检测到的 TAP。对于 SWD,OpenOCD 始终打印检测到的 DPIDR 寄存器(如果未找到目标,通常会中断;输出至少会有所不同)。
Connection/detection 可以完全 non-intrusive,如果目标本身支持它,就像大多数 Cortex-M 一样。如果目标固件已禁用调试引脚或关闭调试逻辑,您可能需要保持或脉冲复位,具体取决于目标。
使用主线 OpenOCD 代码,您可以轻松访问目标内存。您可以从目标读取一些识别数据对其进行解码并检测芯片。
顺便说一句,这可能不适用于 STLink 等高级适配器。请使用通用适配器(J-Link、FTDI-based 适配器、CMSIS-DAP 等)。
source [find interface/jlink.cfg]
transport select swd
adapter_khz 1000
set _CHIPNAME generic_dap_access
# 1. DECLARE A DAP
# -----------------
# Declare a single DAP (a DAP is the SWD counterpart for a JTAG TAP)
# for the chip's cpu. The command `swd newdap` has the same parameters
# as `jtag newtap`.
# param one: Name of the module in the JTAG scan chain (usually a chip).
# param two: Tapname, reflects the role of the TAP (bs, cpu, flash, ...).
# -irlen 4: Instruction register length is 4 bits
# -ircapture 0x1: The bit pattern loaded by the TAP into the JTAG shift register on entry
# to the ircapture state. Default is 0x01.
# -irmask 0xf: A mask used with-ircaptureto verify that instruction scans work correctly.
swd newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf
# 2. CREATE (?) A DAP AND LINK TO JTAG TAP
# -----------------------------------------
# Since OpenOCD version 0.11.0, the Debug Access Port (DAP) is no longer implicitely
# created together with the target. It must be explicitely declared.
# Declare a DAP instance named $_CHIPNAME.dap linked to the JTAG tap $_CHIPNAME.cpu.
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# Note: Observe important note in manual
# for ARMv6-M, ARMv7 and ARMv8 targets.
# 3. DECLARE SOME PROCEDURES
# ---------------------------
# 3.1 Writes 'val' to address 'addr' via AP 'ap'
proc mww_ll { ap addr val } {
global _CHIPNAME
# I'm a bit confused how the following commands achieve just that.
$_CHIPNAME.dap apreg $ap 0x04 $addr
$_CHIPNAME.dap apreg $ap 0x0C $val
}
# 3.2 Reads and displays data from address 'addr' via AP 'ap'
proc mdw_ll { ap addr } {
global _CHIPNAME
$_CHIPNAME.dap apreg $ap 0x04 $addr
$_CHIPNAME.dap apreg $ap 0x0C
}
# 3.3 Reads data from address 'addr' via AP 'ap' and returns it
# Can be used to read data and pass it to other commands
proc mrw_ll { ap addr } {
global _CHIPNAME
$_CHIPNAME.dap apreg $ap 0x04 $addr
set ap [ocd_$_CHIPNAME.dap apreg $ap 0x0C]
regsub -all {(\s*\n)+} $ap "" ap
return $ap
}
# 4. INITIALIZE
# --------------
init # <- What does this actually do? I'm used to see `reset-init`
# everywhere in OpenOCD, but I don't know what simple `init` does.
# 5. READ VALUE AT 0x10000000
# ----------------------------
# Reads and displays value at 0x10000000 <- Why? What's special about
mdw_ll 0 0x10000000 # this memory location?
# 6. MODIFY RAM DATA
# -------------------
# Modify some data in RAM <- Why?
mdw_ll 0 0x08000000
mww_ll 0 0x08000000 0xdeadbeef
mdw_ll 0 0x08000000
exit
OpenOCD 输出:
Open On-Chip Debugger 0.10.0+dev-01116-gfc2e5110d-dirty (2019-07-11-16:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
Info : J-Link Ultra V4 compiled May 27 2019 15:49:24
Info : Hardware version: 4.00
Info : VTarget = 4.850 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x6ba02477
Warn : gdb services need one or more targets defined
0x976562e5
0x20004602
0xdeadbeef