OpenOCD 通过 JTAG 调试树莓派
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenOCD 通过 JTAG 调试树莓派相关的知识,希望对你有一定的参考价值。
硬件环境
Linux 主机 + JLink v8 + 树莓派
OpenOCD 简介
OpenOCD(Open On-Chip Debugger)开源片上调试器,是一款开源软件,旨在提供针对嵌入式设备的调试、系统编程、边界扫描功能。
OpenOCD 的功能是在仿真器的辅助下完成的,仿真器是必须的。
更多详细介绍请看这里。
安装 OpenOCD
下载源码,编译,安装
https://openocd.sourceforge.io/
硬件连接
主机通过 USB 连接 JLink,JLink 另一端接在树莓派上(JLink 可以理解为:USB + JTAG)。树莓派上留有 JTAG 引脚,但是没有标准的 JTAG 插槽,所以需要使用杜邦线将 JLink 和 树莓派连接起来,引脚对应如下:
由于杜邦线连线比较乱,所以我打了个板,这样线就不乱了
树莓派引脚设置为 JTAG 功能
这里是个坑。一般芯片引脚都有多个功能,树莓派的 JTAG 功能所对应的引脚,其第一功能也不是 JTAG。所以要先设置这些引脚的功能模式,使其处于 JTAG 模式。代码如下
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define BCM2835_PERI_BASE 0x3f000000
#define GPIO_BASE (BCM2835_PERI_BASE + 0x200000)
#define GPIO_ALT_FUNCTION_4 0b011
#define GPIO_ALT_FUNCTION_5 0b010
volatile unsigned *m_pAltFunctionRegisters;
void SetGPIOFunction(int GPIO, int functionCode)
int registerIndex = GPIO / 10;
int bit = (GPIO % 10) * 3;
unsigned oldValue = m_pAltFunctionRegisters[registerIndex];
unsigned mask = 0b111 << bit;
printf("Changing function of GPIO%d from %x to %x\\n", GPIO, (oldValue >> bit) & 0b111, functionCode);
m_pAltFunctionRegisters[registerIndex] = (oldValue & ~mask) | ((functionCode << bit) & mask);
int main()
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0)
return -1;
m_pAltFunctionRegisters = (volatile unsigned *)mmap(NULL, 0x18, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
if (m_pAltFunctionRegisters == MAP_FAILED)
return -1;
close(fd);
if (m_pAltFunctionRegisters == MAP_FAILED)
printf("Cannot open /dev/mem! Re-run me as root!\\n");
return 1;
SetGPIOFunction(22, GPIO_ALT_FUNCTION_4);
SetGPIOFunction(4, GPIO_ALT_FUNCTION_5);
SetGPIOFunction(27, GPIO_ALT_FUNCTION_4);
SetGPIOFunction(25, GPIO_ALT_FUNCTION_4);
SetGPIOFunction(23, GPIO_ALT_FUNCTION_4);
SetGPIOFunction(24, GPIO_ALT_FUNCTION_4);
if (m_pAltFunctionRegisters != MAP_FAILED)
munmap((void *)m_pAltFunctionRegisters, 0x18);
printf("Successfully enabled JTAG pins. You can start debugging now.\\n");
return 0;
交叉编译,放入树莓派中运行就行了。
启动 OpenOCD
$ sudo ../src/openocd -f interface/jlink.cfg -f board/myrpi3b+.cfg
如果未连接 JLink,会报如下错误
$ sudo ../src/openocd -f interface/jlink.cfg -f board/myrpi3b+.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
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Error: No J-Link device found
如果未连接树莓派,会报如下错误
$ sudo ../src/openocd -f interface/jlink.cfg -f board/myrpi3b+.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
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
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 1000 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
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
如果树莓派未处于 JTAG 模式,会报如下错误
$ sudo ../src/openocd -f interface/jlink.cfg -f board/myrpi3b+.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
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
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 = 3.267 V
Info : clock speed 1000 kHz
Error: JTAG scan chain interrogation failed: all zeroes
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: rpi3.tap: IR capture error; saw 0x00 not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Invalid ACK (0) in DAP response
下面是正常连接的 log
$ sudo ../src/openocd -f interface/jlink.cfg -f board/myrpi3b+.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
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
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 = 3.267 V
Info : clock speed 1000 kHz
Info : JTAG tap: rpi3.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : rpi3.a53.0: hardware has 6 breakpoints, 4 watchpoints
Info : rpi3.a53.1: hardware has 6 breakpoints, 4 watchpoints
Info : rpi3.a53.2: hardware has 6 breakpoints, 4 watchpoints
Info : rpi3.a53.3: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for rpi3.a53.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for rpi3.a53.1 on 3334
Info : Listening on port 3334 for gdb connections
Info : starting gdb server for rpi3.a53.2 on 3335
Info : Listening on port 3335 for gdb connections
Info : starting gdb server for rpi3.a53.3 on 3336
Info : Listening on port 3336 for gdb connections
接着就可以通过 telnet 或 gdb 连接 OpenOCD 进行调试了。telnet 和 gdb 相当于是客户端,OpenOCD 相当于是服务端
telnet 方式
$ 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
> resume
gdb 方式
$ 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
0x81031bbf in ?? ()
(gdb) c
Continuing.
gdb 连接后,一上来就会将板子 hold 住,我们输入 continue 指令,板子继续运行。
更多调试方法和命令后面有机会再介绍。
以上是关于OpenOCD 通过 JTAG 调试树莓派的主要内容,如果未能解决你的问题,请参考以下文章