JTAG SWD 是什么?

是一种协议,用来调试、烧录 CPU

JTAG 线多

SWD 线少

JLink = USB 转 JTAG

安装 openocd

编写脚本

liyongjun@liyongjun-desktop:~/project/c/openocd-code/tcl$ cat board/my103.cfg
#
# This is an STM32F429 discovery board with a single STM32F429ZI chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF259090
#

source [find interface/jlink.cfg]	# jlink

transport select swd				# swd

# increase working area to 128KB
set WORKAREASIZE 0x20000

source [find target/stm32f1x.cfg]

reset_config srst_only

运行 openocd

liyongjun@liyongjun-desktop:~/project/c/openocd-code/tcl$ sudo ../src/openocd -f board/my103.cfg
[sudo] password for liyongjun:
Open On-Chip Debugger 0.11.0+dev-00590-g2586fec-dirty (2022-03-12-02:34)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : DEPRECATED target event trace-config; use TPIU events {pre,post}-{enable,disable}
srst_only separate srst_nogate srst_open_drain connect_deassert_srst

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link ARM-OB STM32 compiled Aug 22 2012 19:52:04
Info : Hardware version: 7.00
Info : VTarget = 3.300 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: Cortex-M3 r1p1 processor detected
Info : stm32f1x.cpu: target has 6 breakpoints, 4 watchpoints
Info : stm32f1x.cpu: external reset detected
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections

telnet 方式连接

liyongjun@liyongjun-desktop:~$ telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Open On-Chip Debugger
> halt	// 停止运行
target halted due to debug-request, current mode: Thread
xPSR: 0x81000000 pc: 0x08000200 msp: 0x20000430
> resume	// 继续运行
> mdw 0x08000000	// 读取 0x08000000 内存地址处数据,由 STM32f103C8 数据手册可知,0x08000000 为 flash 空间起始地址(外设、内存、flash 统一编址。0x20000000 为 SRAM 起始地址)。
0x08000000: 20000450	// 此处的数据为 0x20000450,与 test.axf 的程序数据内容一致,见下图

> mdw 0x20000444	// 读取内存地址为 0x20000444 的数据,和下图打印的 a = 100 一致
0x20000444: 00000064

> mdw 0x20000440	// 读取内存地址为 0x20000440 的数据,和下图打印的 b = 200 一致
0x20000440: 000000c8

>

test_axf

test_变量地址和值

gdb 方式连接


liyongjun@liyongjun-desktop:~/project/c/openocd-code$ arm-none-eabi-gdb my/test.axf	// 这里要用 arm-none-eabi-gdb,是为了【反汇编】、【打断点】使用。test.axf 是使用 Keil5 编译产生的程序文件
GNU gdb (7.6.50.20131218-0ubuntu1+1) 7.6.50.20131218-cvs
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from my/test.axf...
warning: Loadable section "RW_IRAM1" outside of ELF segments
done.
(gdb) target remote 127.0.0.1:3333	// 连接 OpenOCD
Remote debugging using 127.0.0.1:3333
warning: Loadable section "RW_IRAM1" outside of ELF segments
HAL_Delay (Delay=1000)
    at ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c:328
328     ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c: 没有那个文件或目录.
(gdb) monitor reset	// monitor 意为向连接的外部软件发送指令,此处即向 OpenOCD 发送指令。因为 reset、halt 不是 gdb 的内部指令,而是 OpenOCD 的指令。reset:复位目标板
(gdb) monitor halt	// 中断目标板的运行
target halted due to debug-request, current mode: Thread
xPSR: 0x81000000 pc: 0x08000540 msp: 0x20000430
(gdb) disassemble main	// 反汇编 main 函数
Dump of assembler code for function main:
   0x08001cf8 <+0>:     push    {r2, r3, r4, lr}
   0x08001cfa <+2>:     bl      0x800055c <HAL_Init>
   0x08001cfe <+6>:     bl      0x8001640 <SystemClock_Config>
   0x08001d02 <+10>:    bl      0x8001534 <MX_GPIO_Init>
   0x08001d06 <+14>:    bl      0x80015b8 <MX_USART1_UART_Init>
   0x08001d0a <+18>:    movs    r0, #100        ; 0x64
   0x08001d0c <+20>:    str     r0, [sp, #4]
   0x08001d0e <+22>:    movs    r0, #200        ; 0xc8
   0x08001d10 <+24>:    str     r0, [sp, #0]
   0x08001d12 <+26>:    ldrd    r1, r0, [sp]
   0x08001d16 <+30>:    bl      0x8001d8c <sum>
   0x08001d1a <+34>:    b.n     0x8001d54 <main+92>
   0x08001d1c <+36>:    mov.w   r1, #8192       ; 0x2000
   0x08001d20 <+40>:    ldr     r0, [pc, #52]   ; (0x8001d58)
   0x08001d22 <+42>:    bl      0x800052c <HAL_GPIO_TogglePin>
   0x08001d26 <+46>:    add     r0, pc, #52     ; (adr r0, 0x8001d5c)
   0x08001d28 <+48>:    bl      0x80019d4 <__2printf>
   0x08001d2c <+52>:    add     r1, sp, #4
   0x08001d2e <+54>:    add     r0, pc, #52     ; (adr r0, 0x8001d64)
   0x08001d30 <+56>:    bl      0x80019d4 <__2printf>
   0x08001d34 <+60>:    add     r0, pc, #56     ; (adr r0, 0x8001d70)
   0x08001d36 <+62>:    ldr     r1, [sp, #4]
   0x08001d38 <+64>:    bl      0x80019d4 <__2printf>
   0x08001d3c <+68>:    mov     r1, sp
   0x08001d3e <+70>:    add     r0, pc, #56     ; (adr r0, 0x8001d78)
   0x08001d40 <+72>:    bl      0x80019d4 <__2printf>
   0x08001d44 <+76>:    add     r0, pc, #60     ; (adr r0, 0x8001d84)
   0x08001d46 <+78>:    ldr     r1, [sp, #0]
   0x08001d48 <+80>:    bl      0x80019d4 <__2printf>
   0x08001d4c <+84>:    mov.w   r0, #1000       ; 0x3e8
   0x08001d50 <+88>:    bl      0x80001f4 <HAL_Delay>
   0x08001d54 <+92>:    b.n     0x8001d1c <main+36>
End of assembler dump.
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x08000204 in HAL_Delay (Delay=1000)
    at ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c:328
328     in ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
(gdb) monitor reset
(gdb) ^CQuit
(gdb) monitor halt
target halted due to debug-request, current mode: Thread
xPSR: 0x81000000 pc: 0x08000200 msp: 0x20000430
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x08000204 in HAL_Delay (Delay=1000)
    at ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c:328
328     in ../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
(gdb) b *0x08001d50	// 将断点打在 0x08001d50(HAL_Delay) 之前
Breakpoint 1 at 0x8001d50: file ../Src/main.c, line 110.
(gdb) c	// 继续运行
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, 0x08001d50 in main () at ../Src/main.c:110
110     ../Src/main.c: 没有那个文件或目录.
(gdb) c
Continuing.

Breakpoint 1, 0x08001d50 in main () at ../Src/main.c:110
110     in ../Src/main.c

(gdb) monitor mdw 0x08000000
0x08000000: 20000450

(gdb) monitor mdw 0x20000444
0x20000444: 00000064

(gdb) monitor mdw 0x20000440
0x20000440: 000000c8

注:

berak、continue、Ctrl + C 这是 gdb 的内部命令

reset、halt、resume 这是 OpenOCD 的命令

实测:使用 resume 恢复目标板运行,无视断点;使用 continue 继续执行程序,遇到断点会停止。

小结:

monitor xxx 其实就是调用 OpenOCD 本身的 xxx 命令,也就相当于 telnet 连接 OpenOCD 后执行的原生命令。

编写脚本

liyongjun@liyongjun-desktop:~/project/c/openocd-code/tcl$ cat board/my107.cfg
#
# This is an STM32F429 discovery board with a single STM32F429ZI chip.
# http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF259090
#

source [find interface/jlink.cfg]	# jlink

transport select jtag				# jtag

# increase working area to 128KB
set WORKAREASIZE 0x20000

source [find target/stm32f4x.cfg]

reset_config srst_only

gdb 方式连接

报错

(gdb) target remote 127.0.0.1:3333
Remote debugging using 127.0.0.1:3333
Remote connection closed

OpenOCD 报错

Warn : Cannot identify target as a STM32 family.
Error: auto_probe failed
Error: Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect, or use 'gdb_memory_map disable'.
Error: attempted 'gdb' connection rejected

目前结论:stm32 不支持使用 jtag 方式调试?

telnet 方式连接

liyongjun@liyongjun-desktop:~/project/c/openocd-code/my$ telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Open On-Chip Debugger
> resume
> halt
target halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x080001f6 msp: 0x20000680
> resume

运行 openocd

注释掉 mini2440.cfg 第 124 行: jtag interface

liyongjun@liyongjun-desktop:~/project/c/openocd-code/tcl$ sudo ../src/openocd -f interface/jlink.cfg -f board/mini2440.cfg
[sudo] password for liyongjun:
Open On-Chip Debugger 0.11.0+dev-00590-g2586fec-dirty (2022-03-12-02:34)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
force hard breakpoints
Error: No valid NAND flash driver found (0)
Info : J-Link ARM V8 compiled Nov 28 2014 13:44:46
Info : Hardware version: 8.00
Info : VTarget = 3.313 V
Info : clock speed 12000 kHz
Info : JTAG tap: s3c2440.cpu tap/device found: 0x0032409d (mfg: 0x04e (Samsung), part: 0x0324, ver: 0x0)
Info : Embedded ICE version 2
Info : s3c2440.cpu: hardware has 2 breakpoint/watchpoint units
Info : starting gdb server for s3c2440.cpu on 3333
Info : Listening on port 3333 for gdb connections

-------------------------------------------
--- login with - telnet localhost 4444  ---
--- then type help_2440                 ---
-------------------------------------------

help_2440
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

telnet 方式连接

liyongjun@liyongjun-desktop:~/project/c/openocd-code/my$ telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Open On-Chip Debugger
> help_2440


-----------------------------------------------------------
---- The following mini2440 funcs are supported        ----
----   init_2440 - initialize clocks, DRAM, IO         ----
----   flash_config - configures nand flash            ----
----   load_uboot - loads uboot into ram               ----
----   flash_uboot - flashes uboot to nand (untested)  ----
----   help_2440 - this help display                   ----
-----------------------------------------------------------


> halt
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x80000093 pc: 0xc0031078
MMU: enabled, D-Cache: enabled, I-Cache: enabled
> resume
>

gdb 方式连接

liyongjun@liyongjun-desktop:~/project/c/openocd-code/my$ gdb
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote 127.0.0.1:3333
Remote debugging using 127.0.0.1:3333
warning: while parsing target description (at line 4): Target description specified unknown architecture "arm"
warning: Could not load XML target description; ignoring
0x3001f0d4 in ?? ()
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x3001f0d4 in ?? ()
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x3001f0d4 in ?? ()
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x004155a2 in ?? ()
(gdb) monitor resume
(gdb) monit halt
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x80000093 pc: 0xc0031078
MMU: enabled, D-Cache: enabled, I-Cache: enabled
(gdb) monitor resume
(gdb)

进阶

在源码目录下执行 arm-none-eabi-gdb 有助于 gdb 分析代码。

错题集

没插 J-Link

liyongjun@liyongjun-desktop:~/project/c/openocd-code/tcl$ sudo ../src/openocd -f board/my107.cfg
Open On-Chip Debugger 0.11.0+dev-00590-g2586fec-dirty (2022-03-12-02:34)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_deassert_srst

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Error: No J-Link device found

目标板未上电

liyongjun@liyongjun-desktop:~/project/c/openocd-code/tcl$ sudo ../src/openocd -f board/my107.cfg
Open On-Chip Debugger 0.11.0+dev-00590-g2586fec-dirty (2022-03-12-02:34)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_deassert_srst

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link ARM V8 compiled Aug 18 2009 09:06:07
Info : Hardware version: 8.00
Info : VTarget = 0.000 V
Error: JTAG I/O operation failed: 0x5.
Error: jaylink_jtag_io() failed: device: unspecified error
Info : clock speed 2000 kHz
Error: JTAG I/O operation failed: 0x5.
Error: jaylink_jtag_io() failed: device: unspecified error
Error: JTAG I/O operation failed: 0x5.
Error: jaylink_jtag_io() failed: device: unspecified error
Error: JTAG I/O operation failed: 0x5.
Error: jaylink_jtag_io() failed: device: unspecified error
embedded:startup.tcl:56: Error:
in procedure 'jtag_init' called at file "src/jtag/core.c", line 1678
in procedure 'init_reset' called at file "embedded:startup.tcl", line 39
at file "embedded:startup.tcl", line 56
embedded:startup.tcl:56: Error:
in procedure 'jtag_init' called at file "src/jtag/core.c", line 1678
in procedure 'init_reset' called at file "embedded:startup.tcl", line 39
at file "embedded:startup.tcl", line 56

参考

浅论各种调试接口(SWD、JTAG、Jlink、Ulink、STlink)的区别

跟我一起学OpenOCD(一)

OpenOCD-JTAG调试 OpenOCD命令

openocd+jlink为mini2440调试u-boot

JTAG接口定义与其他简介 jtag 接口图片

树莓派JTAG详细使用笔记

JTAG各类接口针脚定义及含义 哪些 jtag 引脚是强制要求的

树莓派3B+底层玩法:OP-TEE、Kernel module、JTAG 成功案例呀

2440开发板处理坏块之换nand flash 换 flash

友善之臂之mini22440开发环境搭建

Preparing Raspberry PI for JTAG Debugging 最终成功了,TDI 引脚不同,含设置引脚模式的 C++ 代码