rk3568.cfg#
[!/usr/local/share/openocd/scripts/target/rk3568.cfg]
# SPDX-License-Identifier: GPL-2.0-or-later reset_config trst_and_srst separate if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME rk3568 } # # Main DAP # if { [info exists DAP_TAPID] } { set _DAP_TAPID $DAP_TAPID } else { set _DAP_TAPID 0x2ba01477 } adapter driver jlink adapter speed 12000 transport select swd # declare the one SWD tap to access the DAP swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID -ignore-version # create the DAP dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu target create $_CHIPNAME.ahb mem_ap -dap $_CHIPNAME.dap -ap-num 0 set _TARGETNAME $_CHIPNAME.lcore # declare the 6 main application cores set _smp_command "" set $_TARGETNAME.base(0) 0x81004000 set $_TARGETNAME.base(1) 0x81005000 set $_TARGETNAME.base(2) 0x81006000 set $_TARGETNAME.base(3) 0x81007000 set $_TARGETNAME.cti(0) 0x81014000 set $_TARGETNAME.cti(1) 0x81015000 set $_TARGETNAME.cti(2) 0x81016000 set $_TARGETNAME.cti(3) 0x81017000 set _cores 4 for { set _core 0 } { $_core < $_cores } { incr _core 1 } { set _TARGETNAME $_CHIPNAME.lcore cti create cti$_core -dap $_CHIPNAME.dap -baseaddr [set $_TARGETNAME.cti($_core)] -ap-num 0 target create \${_TARGETNAME}$_core aarch64 -dap $_CHIPNAME.dap -coreid $_core -cti cti\$_core -dbgbase [set $_TARGETNAME.base($_core)] if { $_core != 0 } { ${_TARGETNAME}$_core configure -defer-examine } else { # uncomment to use hardware threads pseudo rtos # ${_TARGETNAME}$_core configure -rtos hwthread" ${_TARGETNAME}$_core configure -work-area-size 0x30000 -work-area-phys 0xff8c0000 \ -work-area-backup 0 } set _smp_command "$_smp_command ${_TARGETNAME}$_core" } # Add the second flash bank. #set QUADSPI 1 #set _FLASHNAME $_CHIPNAME.flash1 #flash bank $_FLASHNAME stmqspi 0 0x4000000 2 2 ${_TARGETNAME}0 #flash bank $_FLASHNAME fespi 0 0 0 0 ${_TARGETNAME}0 0xfe610000 target smp $_smp_command targets rk3568.lcore0
本文主要以上述配置文件为例,讲解 [[openocd]] 每条配置命令的作用。
reset_config#
reset_config trst_and_srst separate
Command: reset_config mode_flag ...
该命令在目标配置脚本中显示或修改 JTAG 板和目标组合的复位配置。
本节前面的信息描述了该命令要解决的问题类型(参见 SRST 和 TRST 问题)。一般来说,该命令仅适用于电路板配置文件,用于描述 board doesn't connect TRST 等问题;或适用于用户配置文件,用于解决接口和电路板的特定组合所带来的限制。(一个不太可能的例子是将仅连接 TRST 的适配器与仅连接 SRST 的电路板一起使用)。
模式标志(mode_flag)选项可以任意顺序指定,但信号、组合、门、trst_type、srst_type 和 connect_type 每种类型一次只能指定一个。如果不为给定类型提供新值,其先前值(可能是默认值)将保持不变。例如,这意味着如果 JTAG 适配器要驱动 SRST,则必须明确地将其驱动为高电平(srst_push_pull),而无需对 TRST 做任何说明。
- 信号可以指定连接哪些复位信号。例如,如果 JTAG 接口提供 SRST,但电路板没有正确连接该信号,则 OpenOCD 无法使用它。可能的值有:无(默认值)、trst_only、srst_only 和 trst_and_srst。
> **提示:** 如果您的电路板通过 JTAG 连接器提供 SRST 和/或 TRST,您必须声明,以便可以使用这些信号。
该组合是一个可选值,指定损坏的复位信号实现。如果没有给出任何选项,则默认行为是单独的,表示一切正常。 srst_pulls_trst 表示测试逻辑与系统重置一起重置(例如 NXP LPC2000,“损坏的” 电路板布局),trst_pulls_srst 表示系统与测试逻辑一起重置(仅假设,我还没有看到硬件与这样的错误,并且可以解决)。组合意味着 srst_pulls_trst 和 trst_pulls_srst。
SRST_gates_jtag (默认)表示断定 SRST 时,JTAG 时钟将被门控。这意味着当 SRST 被断言时,JTAG 上不会发生任何通信。其反义词是 srst_nogate,表示在 SRST 处于活动状态时,可以安全地发出 JTAG 命令。
connect_type 标记控制描述 SRST 在连接目标时被断言的某些情况的标志。 connect_deassert_srst(默认)表示 SRST 在连接目标时不会被断言。与之相反的 connect_assert_srst,表示 SRST 将在任何目标连接之前被断言。只有部分目标支持该功能,例如 STM32 和 STR9。如果由于不正确的选项字节配置或非法程序执行导致无法连接目标,该功能将非常有用。
可选的 trst_type 和 srst_type 参数允许指定每条复位线的驱动模式。这些值仅影响支持不同驱动模式的 JTAG 接口,如 Amontec JTAGkey 和 JTAG Accelerator。此外,如果未连接相关信号(TRST 或 SRST),这些值必然会被忽略。
- 测试复位信号 (TRST) 可能的 trst_type 驱动模式有默认的 trst_push_pull 和 trst_open_drain。大多数电路板将该信号连接到下拉,因此 JTAG TAP 除非连接到 JTAG 适配器,否则永远不会离开复位。
- 系统复位信号 (SRST) 的 srst_type 驱动模式有默认的 srst_open_drain 和 srst_push_pull。大多数电路板将该信号连接至上拉器,并允许通过各种事件(包括系统上电和按下复位按钮)将该信号拉低。
info exit#
Config File Guidelines (OpenOCD User’s Guide)
Note
所有目标配置文件应以类似的代码开头,让电路板配置文件表达环境特定的差异。
电路板可以覆盖芯片名称,可能基于角色,
但默认值应与供应商使用的名称匹配
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME sam7x256
}
# 仅在可以更改的目标上使用 ENDIAN。
if { [info exists ENDIAN] } {
set _ENDIAN $ENDIAN
} else {
set _ENDIAN little
}
# TAP 标识符可能会随着芯片的成熟而变化,例如带有
# 新修订字段(这里的“3”)。选择一个好的默认值;您
# 可以将多个此类标识符传递给“jtag newtap”命令。
if { [info exists CPUTAPID ] } {
set _CPUTAPID $CPUTAPID
} else {
set _CPUTAPID 0x3f0f0f0f
}
记住: 电路板配置文件可以包含多个目标配置文件,或者多次使用相同的目标文件(至少更改 CHIPNAME
)。
同样,目标配置文件应定义 _TARGETNAME
(或 _TARGETNAME0
等)并在定义调试目标时使用:
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME arm7tdmi -chain-position $_TARGETNAME
set#
set _CHIPNAME rk3568
set _DAP_TAPID 0x2ba01477
set _TARGETNAME $_CHIPNAME.lcore
set _smp_command ""
set $_TARGETNAME.base(0) 0x81004000
set $_TARGETNAME.base(1) 0x81005000
set $_TARGETNAME.base(2) 0x81006000
set $_TARGETNAME.base(3) 0x81007000
set $_TARGETNAME.cti(0) 0x81014000
set $_TARGETNAME.cti(1) 0x81015000
set $_TARGETNAME.cti(2) 0x81016000
set $_TARGETNAME.cti(3) 0x81017000
set _cores 4
set 为变量赋值命令,参数可以是字符串,数字,其他变量
adapter#
adapter driver jlink
adapter speed 12000
Debug Adapter Configuration (OpenOCD User’s Guide)
Config Command: adapter driver name
使用适配器驱动程序 name 连接到目标。
名称列表详见 Interface-Drivers
Command: adapter speed max_speed_kHz非零速度以 KHZ 为单位。因此:3000 是 3mhz。JTAG 接口通常支持有限数量的速度。实际使用的速度不会超过指定的速度。
芯片数据表通常包括最高 JTAG 时钟速率。实际速率通常是 CPU 核心时钟的函数,通常低于该峰值速率。例如,大多数 ARM 核心最多接受 CPU 时钟的六分之一。
速度 0(khz)选择 RTCK 方法。请参见 FAQ RTCK。如果您的系统使用 RTCK,则在设置后无需更改 JTAG 时钟。并非所有接口、电路板或目标都支持 “rtck”。如果接口设备不支持它,尝试使用 RTCK 时会返回错误。
transport select and swd newdap#
transport select swd
swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID -ignore-version
SWD(串行线调试)是 ARM 特定的传输方式,暴露一个调试访问点(DAP,必须明确声明)。(SWD 使用的信号线比 JTAG 少。) SWD 以调试为导向,不支持边界扫描测试。闪存编程支持建立在调试支持之上。(一些处理器同时支持 JTAG 和 SWD。)
使用命令
transport select swd
选择 SWD 传输。除非您的适配器使用 hla 接口驱动程序(在这种情况下命令为transport select hla_swd
)或 [st-link 接口驱动程序](https://openocd.org/doc/html/Debug-Adapter-Configuration.html#st_005flink_005fdap_005finterface)(在这种情况下命令为transport select dapdirect_swd
)。Config Command: swd newdap ...
声明一个使用 SWD 传输的单个 DAP。参数目前与 "jtag newtap" 相同,但预计会发生变化。
更新的 SWD 设备(SW-DP v2 或 SWJ-DP v2)支持 SWD 协议的多点扩展:两个或多个设备可以连接到一个 SWD 适配器。如果 DAP 配置了
-dp-id
和-instance-id
参数,则 SWD 传输在多点模式下工作,无论创建了多少 DAP。并非所有适配器和适配器驱动程序都支持 SWD 多点。只有以下适配器驱动程序支持 SWD 多点:cmsis_dap(使用 CMSIS-DAP 版本 2.0 的适配器)、ftdi、所有基于 bitbang 的适配器。
Config Command: jtag newtap chipname tapname configparams...
声明一个新的 TAP,带有点名 chipname.tapname,并根据各种 configparams 进行配置。chipname 是芯片的符号名称。通常目标配置文件使用
$_CHIPNAME
,默认为芯片供应商提供的型号名称,但可以覆盖。tapname 反映该 TAP 的角色,应遵循以下约定:
bs
– 如果这是一个单独的 TAP,则用于边界扫描;cpu
– 芯片的主 CPU,或者在同时具有 ARM 和 DSP CPU 的芯片上使用arm
和dsp
,在具有两个 ARM 的芯片上使用arm1
和arm2
,依此类推;etb
– 用于嵌入式跟踪缓冲区(例如:ARM ETB11);flash
– 如果芯片具有闪存 TAP,例如 str912;jrc
– 用于 JTAG 路由控制器(例如:许多德州仪器芯片上的 ICEPick 模块,如 Beagleboards 上的 OMAP3530);tap
– 仅应用于具有单个 TAP 的 FPGA 或 CPLD 类设备;unknownN
– 如果您不知道该 TAP 的用途(N 是一个数字);- 当不确定时 – 使用芯片制造商在其数据表中的名称。例如,Freescale i.MX31 具有一个带 JTAG TAP 的 SDMA(智能 DMA);该 TAP 应命名为
sdma
。每个 TAP 至少需要以下 configparams:
-irlen
NUMBER
指令寄存器的位长度,例如 4 或 5 位。TAP 还可以提供可选的 configparams:
-disable
(或-enable
)
使用-disable
参数标记在使用 TRST 或 JTAG 状态机的 RESET 状态重置后未链接到扫描链的 TAP。您可以使用-enable
突出显示默认状态(TAP 已链接)。请参见 启用和禁用 TAPs。
-expected-id
NUMBER
非零 number 表示您期望在检查扫描链时找到的 32 位 IDCODE。这些代码并非所有 JTAG 设备都要求。根据需要重复该选项,如果可能出现多个 ID 代码(例如,多个版本)。如果要抑制关于找到但未包含在列表中的 IDCODE 值的警告,请将 number 指定为零。如果可能,请提供此值,因为它可以让 OpenOCD 知道它看到的扫描链不正确。这些值在供应商的芯片文档中提供,通常是技术参考手册。有时您可能需要探测 JTAG 硬件以找到这些值。请参见 自动探测。
-ignore-version
指定此选项以忽略-expected-id
选项中的 JTAG 版本字段。当供应商发布多个版本的芯片,或对几个大致兼容的芯片使用相同的 JTAG 级 ID 时,忽略版本字段可能比更新配置文件以处理所有各种芯片 ID 更实际。版本字段定义为 IDCODE 的第 28-31 位。
-ignore-bypass
指定此选项以忽略 idcode 的 “旁路” 位。一些供应商在此位上放置了无效的 idcode。指定此选项以忽略此位,并且不将此 TAP 视为旁路模式。
-ircapture
NUMBER
TAP 在进入 IRCAPTURE 状态时加载到 JTAG 移位寄存器的位模式,例如 0x01。JTAG 要求该值的两个 LSB 为 01。默认情况下,-ircapture
和-irmask
设置为验证该两位值。如果您知道其他位,可以提供它们,或者指示 TAP 不符合 JTAG 规范。
-irmask
NUMBER
与-ircapture
一起使用的掩码,以验证指令扫描是否正常工作。OpenOCD 不使用此类扫描,除非验证 JTAG 扫描链操作似乎没有问题。
-ignore-syspwrupack
指定此选项以在初始检查和检查粘性错误位时忽略 ARM DAP DP CTRL/STAT 寄存器中的 CSYSPWRUPACK 位。通常在设置 CSYSPWRUPREQ 位后检查此位,但某些设备在稍后才设置确认位。
dap create#
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
Command: dap create dap_name -chain-position dotted.name configparams...
声明一个名为 dap_name 的 DAP 实例,链接到 JTAG tap dotted.name。这还创建了一个新命令(
dap_name
),用于各种目的,包括额外配置。系统中每个 JTAG tap 只能有一个 DAP。DAP 还可以提供可选的 configparams:
-adiv5
指定它是 ADIv5 DAP。如果未指定,则为默认值。-adiv6
指定它是 ADIv6 DAP。-ignore-syspwrupack
指定此选项以在初始检查和检查粘性错误位时忽略 ARM DAP DP CTRL/STAT 寄存器中的 CSYSPWRUPACK 位。通常在设置 CSYSPWRUPREQ 位后检查此位,但某些设备在稍后才设置确认位。-dp-id
number
SWD DPv2 多点的调试端口识别号。该 number 写入 DP TARGETSEL 的第 0..27 位。在单个连接设备中查找 id 号,请读取 DP TARGETID:device.dap dpreg 0x24
使用 TARGETID 的第 0..27 位。-instance-id
number
SWD DPv2 多点的实例识别号。该 number 写入 DP TARGETSEL 的第 28..31 位。在单个连接设备中查找实例号,请读取 DP DLPIDR:device.dap dpreg 0x34
实例号在 DLPIDR 值的第 28..31 位。
target create and ${_TARGETNAME}$_core configure -defer-examine#
target create $_CHIPNAME.ahb mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create ${_TARGETNAME}$_core aarch64 -dap $_CHIPNAME.dap -coreid $_core -cti cti$_core -dbgbase [set $_TARGETNAME.base($_core)]
${_TARGETNAME}$_core configure -defer-examine
${_TARGETNAME}$_core configure -work-area-size 0x30000 -work-area-phys 0xff8c0000 -work-area-backup 0
Config Command: target create target_name type configparams...
此命令创建一个 GDB 调试目标,引用特定的 JTAG tap。它将该目标输入到列表中,并创建一个新命令(
target_name
),用于各种目的,包括额外配置。
target_name ... 是调试目标的名称。根据约定,这应与与此目标相关联的 TAP 的 dotted.name 相同,必须在此处使用
-chain-position dotted.name
configparam 指定。此名称还用于创建目标对象命令,在此称为
$target_name
,在其他地方需要识别目标。type ... 指定目标类型。请参见 target types。
configparams ... 所有参数都可以由
$target_name configure
接受。如果目标是大端,则在此处使用-endian big
。您 must 在此处设置
-chain-position dotted.name
或-dap dap_name
。Command: $target_name configure configparams...
此命令接受的选项也可以作为参数指定给
target create
。其值可以稍后通过使用$target_name cget
命令逐一查询。警告: 在设置后更改其中一些内容是危险的。例如,将目标从一个 TAP 移动到另一个 TAP;以及更改其字节序。
-chain-position
dotted.name – 命名用于访问此目标的 TAP。
-dap
dap_name – 命名用于访问此目标的 DAP。请参见 DAP declaration,了解如何创建和管理 DAP 实例。
-endian
(big|little) – 指定 CPU 使用大端或小端约定
-event
event_name event_body – 请参见 Target Events。请注意,这会更新命名事件处理程序的列表。用两个不同的事件名称调用两次会分配两个不同的处理程序,但用相同的事件名称调用两次只分配一个处理程序。当前目标在处理程序代码开始之前临时覆盖为发出事件的目标,处理程序完成后切换回。
-work-area-backup
(0|1) – 指示工作区是否备份;默认情况下,不备份。如果可能,请使用不需要备份的工作区域,因为执行备份会减慢操作。例如,SRAM 块的开头可能会被大多数构建系统使用,但结尾通常未使用。
-work-area-size
size – 指定工作区域大小,以字节为单位。无论使用物理地址还是虚拟地址,均适用相同的大小。
-work-area-phys
address – 设置在没有 MMU 活动时使用的工作区域基地址。
-work-area-virt
address – 设置在 MMU 活动时使用的工作区域基地址。除非在具有 MMU 的目标上,否则不要指定此值。 该值通常应与当前操作系统设置的-work-area-phys
地址的静态映射相对应。
-rtos
rtos_type – 为目标启用 rtos 支持, rtos_type 可以是 auto、none、eCos、ThreadX、FreeRTOS、linux、ChibiOS、embKernel、mqx、uCOS-III、nuttx、RIOT、Zephyr、rtkernel,见 RTOS Support。
-defer-examine
– 跳过初始 JTAG 链扫描和重置后的目标检查。需要手动调用 arp_examine 以访问目标进行调试。
-ap-num
ap_number – 设置目标的 DAP 访问端口。在 ADIv5 DAP 中,ap_number 是目标连接的 DAP AP 的数字索引。在 ADIv6 DAP 中,ap_number 是目标连接的 DAP AP 的基地址。使用此选项的系统中,多个独立核心连接到同一 DAP 的不同访问端口。
-cti
cti_name – 设置连接到目标的交叉触发接口(CTI)。目前,只有aarch64
目标使用此选项,这是目标运行控制的强制配置。请参见 ARM Cross-Trigger Interface,了解如何声明和控制 CTI 实例。
-gdb-port
number – 请参见命令gdb_port
以获取参数 number 的可能值,这些值不仅是数字值。使用此选项仅覆盖此目标的全局参数,该参数通过命令gdb_port
设置。请参见 命令 gdb_port。
-gdb-max-connections
number – 实验性:设置允许的目标最大 GDB 连接数。默认值为 1。number 的负值表示无限连接。请参见 使用 GDB 作为非侵入式内存检查器。
但是上述内容中没有关于-coreid
和-dbgbase
选项的说明,在 SMP 相关章节有提到一点:
Define-CPU-targets-working-in-SMP
Note
在设置目标后,您可以定义在 SMP 中工作的目标列表。
set _TARGETNAME_1 $_CHIPNAME.cpu1
set _TARGETNAME_2 $_CHIPNAME.cpu2
target create $_TARGETNAME_1 cortex_a -chain-position $_CHIPNAME.dap \
-coreid 0 -dbgbase $_DAP_DBG1
target create $_TARGETNAME_2 cortex_a -chain-position $_CHIPNAME.dap \
-coreid 1 -dbgbase $_DAP_DBG2
#定义 2 个在 smp 中工作的目标。
target smp $_CHIPNAME.cpu2 $_CHIPNAME.cpu1
在上述 cortex_a 示例中,2 个 CPU 在 SMP 中工作。在 SMP 中,仅创建一个 GDB 实例:
- 一组硬件断点在列表中的所有目标上设置相同的断点。
- halt 命令触发列表中所有目标的停止。
- resume 命令触发上下文写入和列表中所有目标的重启。
- 在断点后:由断点停止的目标显示在 GDB 会话中。
- 为切换 / 检索 GDB 会话中显示的目标实现了专用 GDB 串行协议数据包,见 使用 OpenOCD SMP 与 GDB。
SMP 行为可以动态禁用 / 启用。在 cortex_a 上实现了以下命令。
- cortex_a smp on : 启用 SMP 模式,行为如上所述。
- cortex_a smp off : 禁用 SMP 模式,当前目标是 GDB 会话中显示的目标,只有该目标现在由 GDB 会话控制。此行为在系统启动期间非常有用。
- cortex_a smp : 显示当前 SMP 模式。
- cortex_a smp_gdb : 显示 / 修复在 GDB 会话中显示的核心 ID,见以下示例。
cortex_a smp_gdb
gdb coreid 0 -> -1
#0 : coreid 0 is displayed to GDB ,
#-> -1 : next resume triggers a real resume
cortex_a smp_gdb 1
gdb coreid 0 -> 1
#0 :coreid 0 is displayed to GDB ,
#->1 : next resume displays coreid 1 to GDB
resume
cortex_a smp_gdb
gdb coreid 1 -> 1
#1 :coreid 1 is displayed to GDB ,
#->1 : next resume displays coreid 1 to GDB
cortex_a smp_gdb -1
gdb coreid 1 -> -1
#1 :coreid 1 is displayed to GDB,
#->-1 : next resume triggers a real resume
上述例子中除了 target create 之外,以及 target smp 命令也有涉及到
cti create#
cti create cti$_core -dap $_CHIPNAME.dap -baseaddr [set $_TARGETNAME.cti($_core)] -ap-num 0
ARM-Cross_002dTrigger-Interface
Command: cti create cti_name -dap dap_name -ap-num apn -baseaddr base_address
创建一个 CTI 实例 cti_name 在 DAP 实例 dap_name 上,位于 MEM-AP apn。在 ADIv5 DAP 中,apn 是 CTI 连接的 DAP AP 的数字索引。在 ADIv6 DAP 中,apn 是 CTI 连接的 DAP AP 的基地址。base_address 必须与相应 MEM-AP 上 CTI 的基地址匹配。所有参数都是必需的。这创建了一个新命令
$cti_name
,用于各种目的,包括额外配置。
targets#
targets rk3568.lcore0
所有已设置的目标都是一个列表的一部分,每个成员都有一个名称。该名称通常应与 TAP 名称相同。您可以使用
targets
(复数!)命令显示列表。此显示通常只有一个 CPU;如果有多个,可能如下所示:
TargetName | Type | Endian | TapName | State |
---|---|---|---|---|
0* at91rm9200.cpu | arm920t | little | at91rm9200.cpu | running |
1 MyTarget | cortex_m | little | mychip.foo | tap-disabled |
该列表的一个成员是 current target,许多命令隐式引用它。它是标记为目标名称旁边的
*
的目标。特别是,内存地址通常指的是当前目标所看到的地址空间。像mdw
(内存显示字)和flash erase_address
(擦除 NOR 闪存块)这样的命令就是例子;还有很多其他的。几个命令让您检查目标列表:
Command: target current
返回当前目标的名称。
Command: target names
列出列表中所有当前目标的名称。
foreach t [target names] {
puts [format "Target: %s\n" $t]
}Command: targets [name]
注意:此命令的名称是复数。其他目标命令名称是单数。
如果没有参数,此命令以用户友好的形式显示所有已知目标的表。
如果有参数,此命令将当前目标设置为给定名称的目标;这只适用于有多个目标的电路板。