当前位置: 首页 > 工具软件 > OpenOCD > 使用案例 >

OpenOCD安装与使用(JTAG调试)

夹谷和裕
2023-12-01

本文介绍openocd开源软件的安装以及搭配JTAG对Xilinx u500VC707devkit的调试
PC OS: Ubuntu20.04 LTS
Target ARCH: riscv64
JTAG: Olimex-ARM-USB-TINY-H
OpenOCD version: OpenOCD v0.10.0


1、OpenOCD简介

  OpenOCD(Open On-Chip Debugger)是一款开源的开放式片上调试软件,需要在调试适配器(如: JTAG、SWD等)的配合下可以对片上系统进行相应调试,以及在嵌入式设备上测试系统内程序或边界接扫描测试。

2、下载OpenOCD

  可以通过OpenOCD官网下载源码,已经有很多平台提供配套目标平台的OpenOCD源码,也可以通过这些来下载带有相应目标平台配置文件的OpenOCD,本文主要介绍支持riscv64OpenOCD下载和使用。
riscv-openocd下载链接: https://github.com/sifive/riscv-openocd
通过git下载:

git clone https://github.com/sifive/riscv-openocd.git

3、编译与安装

<0> 准备工作

以下步骤需要安装一些依赖包来支持。

imaginemiracle@:openocd$ sudo apt-get install -y lib-tool make automake gcc autoheader pkg-config libusb-dev  libusb-1.0-0-dev

<1> 进入riscv-openocd源码目录

imaginemiracle@:openocd$ cd riscv-openocd
imaginemiracle@:riscv-openocd$ ls
AUTHORS            ChangeLog         COPYING       HACKING      NEWS-0.10.0  NEWS-0.5.0  NEWS-0.9.0  README.Windows  TODO
AUTHORS.ChangeLog  config_subdir.m4  doc           jimtcl       NEWS-0.2.0   NEWS-0.6.0  NEWTAPS     src             tools
bootstrap          configure.ac      Doxyfile.in   Makefile.am  NEWS-0.3.0   NEWS-0.7.0  README      tcl             uncrustify.cfg
BUGS               contrib           guess-rev.sh  NEWS         NEWS-0.4.0   NEWS-0.8.0  README.OSX  testing

<2> 执行bootstrap生成configure文件,通过configure配置OpenOCD,主要需要配置OpenOCD支持的调试器的类型,笔者使用的JTAGFTDI类型,因此需要OpenOCD支持FTDI

[注] 通过查看JTAG手册了解所使用的JTAG是什么类型,通过./configure --help 命令查看所需要开启的类型以及其它配置参数

#创建安装目录
imaginemiracle@:riscv-openocd$ mkdir install_IM
#执行bootstrap
imaginemiracle@:riscv-openocd$ ./bootstrap

bootstrap执行的正常输出:

+ aclocal
+ libtoolize --automake --copy
+ autoconf
+ autoheader
+ automake --gnu --add-missing --copy
configure.ac:26: installing './compile'
configure.ac:37: installing './config.guess'
configure.ac:37: installing './config.sub'
configure.ac:16: installing './install-sh'
configure.ac:16: installing './missing'
Makefile.am:46: warning: wildcard $(srcdir: non-POSIX variable name
Makefile.am:46: (probably a GNU make extension)
Makefile.am: installing './INSTALL'
Makefile.am: installing './depcomp'
Makefile.am:23: installing './mdate-sh'
Makefile.am:23: installing './texinfo.tex'
Setting up submodules
Submodule 'jimtcl' (https://github.com/msteveb/jimtcl) registered for path 'jimtcl'
Cloning into '/media/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/File_System_test/openocd/riscv-openocd/jimtcl'...
Submodule path 'jimtcl': checked out '51f65c6d38fbf86e1f0b036ad336761fd2ab7fa0'
Submodule path 'jimtcl': checked out '51f65c6d38fbf86e1f0b036ad336761fd2ab7fa0'
Generating build system...
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'build-aux'.
libtoolize: copying file 'build-aux/config.guess'
libtoolize: copying file 'build-aux/config.sub'
libtoolize: copying file 'build-aux/install-sh'
libtoolize: copying file 'build-aux/ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4'
configure.ac:42: installing 'build-aux/ar-lib'
configure.ac:37: installing 'build-aux/compile'
configure.ac:30: installing 'build-aux/missing'
Makefile.am: installing './INSTALL'
libjaylink/Makefile.am: installing 'build-aux/depcomp'
Bootstrap complete. Quick build instructions:
./configure ....

成功生成configure文件

#配置安装目录路径必须为绝对路径
imaginemiracle@:riscv-openocd$ ./configure --prefix=/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/File_System_test/openocd/openocd-0.10.0/install_IM/ --enable-ftdi
###################只显示关键输出####################
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating libjaylink/Makefile
config.status: creating libjaylink/version.h
config.status: creating libjaylink.pc
config.status: creating Doxyfile
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands

看到成功成生Makefile文件且没有报错,则说明配置成功。

<3> 配置成功后直接编译并安装即可

直接使用make; make install编译并安装

#编译后并且安装
imaginemiracle@:riscv-openocd$ make; make install

make; make install直接通过,则跳过<4>这一节直接看下一节的openocd使用介绍。

<4> 编译openocd可能会遇到如下几种错误

<4.0> 报错 0: ./src/helper/log.h:130:9: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
#错误0
./src/helper/log.h:130:9: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  130 |         log_printf_lf(LOG_LVL_ERROR, __FILE__, __LINE__, __func__, expr)
      |         ^~~~~~~~~~~~~
src/flash/nor/jtagspi.c:262:18: note: ‘status’ was declared here
  262 |         uint32_t status;
      |                  ^~~~~~
src/flash/nor/jtagspi.c: In function ‘jtagspi_wait’:
src/flash/nor/jtagspi.c:249:29: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  249 |                 if ((status & SPIFLASH_BSY_BIT) == 0) {
      |

解决方案 0: 通过错误类型可以看出编译器检测到使用了未初始化的变量,在高版本的编译器中不允许使用未初始化的变量,将其初始化即可。

vim src/flash/nor/jtagspi.c +262
static int jtagspi_write_enable(struct flash_bank *bank)
{
        // ------------Alter by wxn-----------
        uint32_t status = 0;
        // ------------End of Alter-----------

        jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
vim src/flash/nor/jtagspi.c +249
static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
{
        // ------------Alter by wxn-----------
        uint32_t status = 0;
        // ------------End of Alter-----------
        int64_t t0 = timeval_ms();
        int64_t dt;

        do {
                dt = timeval_ms() - t0;
<4.1> 报错 1: src/svf/svf.c:663:7: error: this statement may fall through [-Werror=implicit-fallthrough=]
#错误1
src/svf/svf.c: In function ‘svf_read_command_from_file’:
src/svf/svf.c:663:7: error: this statement may fall through [-Werror=implicit-fallthrough=]
  663 |     i = -1;
      |     ~~^~~~
src/svf/svf.c:664:4: note: here
  664 |    case '\r':
      |    ^~~~
src/svf/svf.c:667:8: error: this statement may fall through [-Werror=implicit-fallthrough=]
  667 |     if (!cmd_pos)
      |        ^
src/svf/svf.c:669:4: note: here
  669 |    default:
      |    ^~~~~~~
cc1: all warnings being treated as errors

解决方案 1: 通过源码分析可以看出,这块的报错只是因为在switch case语句中一个case没有写break,编译器识别到可能会跳到下一个case语句中,因此在这里直接忽略该错误继续编译即可。

imaginemiracle@:openocd$ make -j8 CFLAGS='-Wno-implicit-fallthrough'
<4.2> 报错 2: src/target/arm_disassembler.c:1499:30: error: bitwise comparison always evaluates to false [-Werror=tautological-compare]
#错误2
src/target/arm_disassembler.c: In function ‘evaluate_misc_instr’:
src/target/arm_disassembler.c:1499:30: error: bitwise comparison always evaluates to false [-Werror=tautological-compare]
 1499 |   if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) {
      |                              ^~
src/target/arm_disassembler.c:1521:29: error: bitwise comparison always evaluates to false [-Werror=tautological-compare]
 1521 |   if ((opcode & 0x00600000) == 0x00300000) {
      |                             ^~
src/target/arm_disassembler.c:1542:30: error: bitwise comparison always evaluates to false [-Werror=tautological-compare]
 1542 |   if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) {
      |                              ^~

解决方案 2: 按照道理说这种写法是没什么问题的,但还是会报错,因此将报错的三个位置进行修改,修改后的代码如下。

imaginemiracle@:openocd$ vim src/target/arm_disassembler.c +1499
//File src/target/arm_disassembler.c +1499:In function 'evaluate_misc_instr'
        /* SMLAW < y> */
//============================Alter by me==============================
        if (!(((opcode & 0x00600000) - 0x00100000)) && (x == 0)) {
//============================ End Alter ==============================
            uint8_t Rd, Rm, Rs, Rn;
            instruction->type = ARM_SMLAWy;
            Rd = (opcode & 0xf0000) >> 16;
            Rm = (opcode & 0xf);
            Rs = (opcode & 0xf00) >> 8;
            Rn = (opcode & 0xf000) >> 12;

            snprintf(instruction->text,
                    128,
                    "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
                    address,
                    opcode,
                    (y) ? "T" : "B",
                    COND(opcode),
                    Rd,
                    Rm,
                    Rs,
                    Rn);
        }

        /* SMUL < x><y> */
//============================Alter by me==============================                
        if (!((opcode & 0x00600000) - 0x00300000)) {
//============================ End Alter ==============================        
            uint8_t Rd, Rm, Rs;
            instruction->type = ARM_SMULxy;
            Rd = (opcode & 0xf0000) >> 16;
            Rm = (opcode & 0xf);
            Rs = (opcode & 0xf00) >> 8;

            snprintf(instruction->text,
                    128,
                    "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
                    address,
                    opcode,
                    (x) ? "T" : "B",
                    (y) ? "T" : "B",
                    COND(opcode),
                    Rd,
                    Rm,
                    Rs);                                                                                                                                                                                                                                                                  
        }

        /* SMULW < y> */
//============================Alter by me==============================        
        if (!(((opcode & 0x00600000) - 0x00100000)) && (x == 1)) {
//============================ End Alter ==============================        
            uint8_t Rd, Rm, Rs;
            instruction->type = ARM_SMULWy;
            Rd = (opcode & 0xf0000) >> 16;
            Rm = (opcode & 0xf);
            Rs = (opcode & 0xf00) >> 8;

            snprintf(instruction->text,
                    128,
                    "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
                    address,
                    opcode,
                    (y) ? "T" : "B",
                    COND(opcode),
                    Rd,
                    Rm,
                    Rs);
        }
<4.3> 报错 3: src/target/nds32_cmd.c:824:21: error: ‘sprintf’ writing a terminating nul past the end of the destination [-Werror=format-overflow=]
#错误3
src/target/nds32_cmd.c: In function ‘jim_nds32_bulk_read’:
src/target/nds32_cmd.c:824:21: error: ‘sprintf’ writing a terminating nul past the end of the destination [-Werror=format-overflow=]
  824 |   sprintf(data_str, "0x%08" PRIx32 " ", data[i]);
      |                     ^~~~~~~
src/target/nds32_cmd.c:824:38: note: format string is defined here
  824 |   sprintf(data_str, "0x%08" PRIx32 " ", data[i]);
      |                                      ^
src/target/nds32_cmd.c:824:3: note: ‘sprintf’ output 12 bytes into a destination of size 11
  824 |   sprintf(data_str, "0x%08" PRIx32 " ", data[i]);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

解决方案 3: 从错误类型format-overflow,格式溢出,一看就是不重要的错误,直接忽略就好继续编译。

imaginemiracle@:openocd$ make -j8 CFLAGS='-Wno-implicit-fallthrough -Wno-format-overflow'
<4.4> 报错 4: /usr/include/x86_64-linux-gnu/sys/sysctl.h:21:2: error: #warning "The <sys/sysctl.h> header is deprecated and will be removed." [-Werror=cpp]
#错误4
In file included from src/helper/options.c:38:
/usr/include/x86_64-linux-gnu/sys/sysctl.h:21:2: error: #warning "The <sys/sysctl.h> header is deprecated and will be removed." [-Werror=cpp]
   21 | #warning "The <sys/sysctl.h> header is deprecated and will be removed."
      |  ^~~~~~~
cc1: all warnings being treated as errors

解决方案 4: 可以看出这里是使用了Linux已经移除的头文件<sys/sysctl.h>报错的,因此进入报错文件,做以下修改。

imaginemiracle@:openocd$ vim src/helper/options.c +38
//File src/helper/options.c +38
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "configuration.h"
#include "log.h"
#include "command.h"

#include <getopt.h>

#include <limits.h>
#include <stdlib.h>
#if IS_DARWIN
#include <libproc.h>
#endif
//===================Alter by me===================
#ifdef HAVE_SYS_SYSCTL_H
//#include <sys/sysctl.h>
#endif
#if IS_WIN32 && !IS_CYGWIN
#include <windows.h>
#endif
//=================== End  Alter ===================
static int help_flag, version_flag;
<4.5> 报错 5: `./src/helper/log.h:130:2: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
#错误5
  130 |  log_printf_lf(LOG_LVL_ERROR, __FILE__, __LINE__, __func__, expr)
      |  ^~~~~~~~~~~~~
src/flash/nor/jtagspi.c:262:11: note: ‘status’ was declared here
  262 |  uint32_t status;
      |           ^~~~~~
src/flash/nor/jtagspi.c: In function ‘jtagspi_wait’:
src/flash/nor/jtagspi.c:249:15: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  249 |   if ((status & SPIFLASH_BSY_BIT) == 0) {
      |       ~~~~~~~~^~~~~~~~~~~~~~~~~~~`
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I./src -I./src -I./src/helper -DPKGDATADIR=\"/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/riscv-openocd/install_openocd/share/openocd\" -DBINDIR=\"/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/riscv-openocd/install_openocd/bin\" -I./jimtcl -I./jimtcl -Wall -Wstrict-prototypes -Wformat-security -Wshadow -Wextra -Wno-unused-parameter -Wbad-function-cast -Wcast-align -Wredundant-decls -Werror -g -O2 -MT src/flash/nor/jtagspi.lo -MD -MP -MF src/flash/nor/.deps/jtagspi.Tpo -c src/flash/nor/jtagspi.c -o src/flash/nor/jtagspi.o
In file included from ./src/flash/common.h:21,
                 from src/flash/nor/core.h:25,
                 from src/flash/nor/imp.h:22,
                 from src/flash/nor/jtagspi.c:22:
src/flash/nor/jtagspi.c: In function ‘jtagspi_write_enable’:
./src/helper/log.h:130:2: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  130 |  log_printf_lf(LOG_LVL_ERROR, __FILE__, __LINE__, __func__, expr)
      |  ^~~~~~~~~~~~~
src/flash/nor/jtagspi.c:262:11: note: ‘status’ was declared here
  262 |  uint32_t status;
      |           ^~~~~~
src/flash/nor/jtagspi.c: In function ‘jtagspi_wait’:
src/flash/nor/jtagspi.c:249:15: error: ‘status’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  249 |   if ((status & SPIFLASH_BSY_BIT) == 0) {
      |       ~~~~~~~~^~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[2]: *** [Makefile:3340: src/flash/nor/jtagspi.lo] Error 1
make[2]: Leaving directory '/media/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/riscv-openocd/openocd'
make[1]: *** [Makefile:4272: all-recursive] Error 1
make[1]: Leaving directory '/media/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/riscv-openocd/openocd'
make: *** [Makefile:1996: all] Error 2

解决方案 5: 报错文件为src/flash/nor/jtagspi.c,从报错信息里可以看到是检测到使用未初始化变量导致的,因此,在对应文件中将status变量初始化即可。下面是修改后的文件,只需要初始化status即可。

# File::src/flash/nor/jtagspi.c
240 static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
241 {
242 /**************Alter by wxn****************/
243     uint32_t status = 0;
244 /****************End Alter*****************/
245     int64_t t0 = timeval_ms();
246     int64_t dt;
247 
248     do {
249         dt = timeval_ms() - t0;
250         jtagspi_read_status(bank, &status);
251         if ((status & SPIFLASH_BSY_BIT) == 0) {
252             LOG_DEBUG("waited %" PRId64 " ms", dt);
253             return ERROR_OK;
254         }
255         alive_sleep(1);
256     } while (dt <= timeout_ms);
257     
258     LOG_ERROR("timeout, device still busy");
259     return ERROR_FAIL;
260 }
261 
262 static int jtagspi_write_enable(struct flash_bank *bank)
263 {
264 /**************Alter by wxn****************/
265     uint32_t status = 0;
266 /****************End Alter*****************/
267 
268     jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
269     jtagspi_read_status(bank, &status);
270     if ((status & SPIFLASH_WE_BIT) == 0) {
271         LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
272         return ERROR_FAIL;
273     }
274     return ERROR_OK;
275 }
<4.6> 报错 6: `./src/helper/binarybuffer.h:94:19: error: ‘out’ may be used uninitialized in this function [-Werror=maybe-uninitialized]

94 | buffer[i / 8] &= ~(1 << (i % 8));`

#错误6
In file included from ./src/jtag/jtag.h:25,
                 from src/target/riscv/riscv-011.c:18:
src/target/riscv/riscv-011.c: In function ‘dbus_scan’:
./src/helper/binarybuffer.h:94:19: error: ‘out’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
   94 |     buffer[i / 8] &= ~(1 << (i % 8));
      |                   ^~
cc1: all warnings being treated as errors
make[2]: *** [Makefile:3340: src/target/riscv/riscv-011.lo] Error 1
make[2]: Leaving directory '/media/imaginemiracle/Disk_D/Download/Ubuntu_Download/syntacore/openocd'
make[1]: *** [Makefile:4272: all-recursive] Error 1
make[1]: Leaving directory '/media/imaginemiracle/Disk_D/Download/Ubuntu_Download/syntacore/openocd'
make: *** [Makefile:1996: all] Error 2

解决方案 6: 报错文件为src/helper/binarybuffer.h,从报错信息中可以看到依然是由使用未初始化变量引起的错误,不过这里的未初始化和之前的不太一样,需要这样修改,如下。

File::src/helper/binarybuffer.h
 69 static inline void buf_set_u64(uint8_t *_buffer,
 70     unsigned first, unsigned num, uint64_t value)
 71 {   
 72     uint8_t *buffer = _buffer;
 73     
 74     if ((num == 32) && (first == 0)) {
 75         buffer[3] = (value >> 24) & 0xff;
 76         buffer[2] = (value >> 16) & 0xff;
 77         buffer[1] = (value >> 8) & 0xff;
 78         buffer[0] = (value >> 0) & 0xff;
 79     } else if ((num == 64) && (first == 0)) {
 80         buffer[7] = (value >> 56) & 0xff;
 81         buffer[6] = (value >> 48) & 0xff;
 82         buffer[5] = (value >> 40) & 0xff;
 83         buffer[4] = (value >> 32) & 0xff;
 84         buffer[3] = (value >> 24) & 0xff;
 85         buffer[2] = (value >> 16) & 0xff;
 86         buffer[1] = (value >> 8) & 0xff;
 87         buffer[0] = (value >> 0) & 0xff;
 88     } else {
 89         for (unsigned i = first; i < (first + num); i++) {
 90             if (((value >> (i - first)) & 1) == 1) {
 91 /******************Alter by wxn***********************/
 92                 buffer[i / 8] = 0x01;
 93 /********************End Alter************************/
 94                 buffer[i / 8] |= 1 << (i % 8);
 95             }
 96             else {
 97 /******************Alter by wxn***********************/
 98                 buffer[i / 8] = 0x02;
 99 /********************End Alter************************/
100                 buffer[i / 8] &= ~(1 << (i % 8));
101             }
102         }
103     }
104 }
<4.7> 报错 7: src/flash/nor/numicro.c:1244:17: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation]
src/flash/nor/numicro.c:1244:17: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation]
 1244 |                 if (retval != ERROR_OK)
      |                 ^~
In file included from ./src/flash/common.h:21,
                 from src/flash/nor/core.h:25,
                 from src/flash/nor/imp.h:22,
                 from src/flash/nor/numicro.c:32:
./src/helper/log.h:116:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
  116 |         do { \
      |         ^~
src/flash/nor/numicro.c:1246:25: note: in expansion of macro ‘LOG_DEBUG’
 1246 |                         LOG_DEBUG("status: 0x%" PRIx32 "", status);
      |                         ^~~~~~~~~
src/flash/nor/numicro.c: In function ‘numicro_erase’:
src/flash/nor/numicro.c:1512:25: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation]
 1512 |                         if (retval != ERROR_OK)
      |

解决方案 7: 从报错信息来看,是想说这个 if 语句边界不明确,因为有 break 的存在,需要为 if 语句明确的加上大括号,表示 if 的作用范围。

 for (;;) {
                                retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
                                if (retval != ERROR_OK) {
                                        return retval;
                                }
                                LOG_DEBUG("status: 0x%" PRIx32 "", status);
                                if (status == 0) {
                                        break;
                                }
<4.8> 报错 8: src/target/arm920t.c:255:9: error: ‘arm9tdmi_write_core_regs’ accessing 64 bytes in a region of size 8 [-Werror=stringop-overflow=]
src/target/arm920t.c:255:9: error: ‘arm9tdmi_write_core_regs’ accessing 64 bytes in a region of size 8 [-Werror=stringop-overflow=]
  255 |         arm9tdmi_write_core_regs(target, 0x2, regs);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/target/arm920t.c:255:9: note: referencing argument 3 of type ‘uint32_t *’ {aka ‘unsigned int *’}

解决方案 8: 这个问题也可以算作是高版本编译器对代码检查的严格导致的,修改 src/target/arm9tdmi.hsrc/target/arm9tdmi.c 两个文件中的 void arm9tdmi_write_core_regsvoid arm9tdmi_read_core_regs 两个函数。

// File: src/target/arm9tdmi.h
//-----------------------Alter by wxn------------------------
//void arm9tdmi_read_core_regs(struct target *target,
//              uint32_t mask, uint32_t *core_regs[16]);
//void arm9tdmi_write_core_regs(struct target *target,
//              uint32_t mask, uint32_t core_regs[16]);

void arm9tdmi_read_core_regs(struct target *target,
                uint32_t mask, uint32_t **core_regs);
void arm9tdmi_write_core_regs(struct target *target,
                uint32_t mask, uint32_t *core_regs);
//----------------------End of Alter-------------------------

同时将 c 文件中对应的两个函数实现的参数也修改为一样的即可。

4、OpenOCD的使用

4.1、OpenOCD的配置

安装成功后则会在配置的安装目录里生成如下文件,这里的openocd就是需要用到的可执行程序将它拷贝到需要执行的目录,或者直接在当前目录使用也可以。([注]: 若未配置安装路径,默认安装到“./src目录”中)

imaginemiracle@:openocd$ cd install_IM/
imaginemiracle@:install_IM$ ls
bin  share
imaginemiracle@:install_IM$ ls bin/
openocd
imaginemiracle@:openocd$ cp install_IM/bin/openocd ./

使用openocd+JTAG需要用到两个配置文件,分别是JTAG的配置文件和目标平台的配置文件。一般JTAG厂商都会提供购买到的JTAGopenocd配置文件,这里就可以直接使用。

<1> JTAG设备配置文件

前文提到笔者所使用的JTAG型号为Olimex-ARM-USB-TINY-H,其配置文件如下:

# File olimex-arm-usb-tiny-h.cfg
#
# Olimex ARM-USB-TINY-H
#
# http://www.olimex.com/dev/arm-usb-tiny-h.html
#

interface ftdi
#interface jlink
ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H"
ftdi_vid_pid 0x15ba 0x002a

ftdi_layout_init 0x0808 0x0a1b
ftdi_layout_signal nSRST -oe 0x0200
ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi_layout_signal LED -data 0x0800

当电脑链接上JTAG后,还需要安装JTAG的驱动,若“lsusb”可以查看到JTAG设备,则说明驱动安装成功。

imaginemiracle@:openocd$ lsusb
Bus 002 Device 002: ID 0424:5744 Microchip Technology, Inc. (formerly SMSC) Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 003: ID 0424:2744 Microchip Technology, Inc. (formerly SMSC) Hub
Bus 001 Device 007: ID 413c:2113 Dell Computer Corp. Dell KB216 Wired Keyboard
Bus 001 Device 006: ID 413c:301a Dell Computer Corp. Dell MS116 USB Optical Mouse
Bus 001 Device 008: ID 15ba:002a Olimex Ltd. ARM-USB-TINY-H JTAG interface
Bus 001 Device 002: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

这里的ID后面的值分别为USB设备的VIDPID,这里的值应该与JTAG配置文件中的vid_pid相同才可。

<2> 目标平台配置文件

OpenOCD的配置文件使用的是tcl语言,这里的目标平台配置文件是笔者仿照其它配置文件修改的。

# File riscv64_IM.cfg
proc init_targets {} {
	adapter_khz 1000
	reset_config trst_and_srst
	set _CHIPNAME riscv
	jtag newtap $_CHIPNAME cpu -irlen 5

	set _TARGETNAME $_CHIPNAME.cpu
	target create $_TARGETNAME riscv -endian little -chain-position $_TARGETNAME -coreid 0
	# $_TARGETNAME configure -rtos riscv
	# $_TARGETNAME configure -work-area-phys 0x3ff0000 -work-area-size 0x10000 -work-area-backup 1
	# $_TARGETNAME riscv expose_csrs 3008-3015,4033-4034
}

proc sw_reset_halt {} {
    reset halt
}

4.2、OpenOCD链接JTAG

有了JTAG和目标平台的两个配置文件后,就可以启动OpenOCD连接本地JTAG设备了,启动命令如下:

imaginemiracle@:riscv-openocd$ sudo ./src/openocd -s ./tcl -f ./tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f ./tcl/target/riscv64_IM.cfg
[sudo] password for imaginemiracle: 
Open On-Chip Debugger 0.10.0+dev-01145-gb7bd3f8d4 (2021-01-12-17:54)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
sw_reset_halt
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
0
Info : clock speed 1000 kHz
Info : TAP riscv.cpu has invalid IDCODE (0xfffffffe)
Info : datacount=2 progbufsize=16
Info : Disabling abstract command reads from CSRs.
Info : Examined RISC-V core; found 4 harts
Info :  hart 0: XLEN=64, misa=0x800000000014112d
Info :  hart 1: currently disabled
Info :  hart 2: currently disabled
Info :  hart 3: currently disabled
Info : Listening on port 3333 for gdb connections

连接到本地:

imaginemiracle@:riscv-openocd$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> 

如上进入openocd的命令行则说明OpenOCD+JTAG的整个软件环境搭建完成。

4.3、OpenOCD的一些简单命令

OpenOCD常用命令

halt	-暂停CPU
reset	-复位目标板
resume 	-恢复运行
resume 0x123456   -从0x123456地址恢复运行
reg <register>    -打印register寄存器的值

load_image <File Name> <Addr>		    -烧写二进制文件到指定地址
例: load_image image.bin 0x4000000  	-烧写image.bin到0x4000000

dump_image <File Name> <Addr> <Size>    -将内存从地址Addr开始的Size字节数据读出,保存到文件File Name中

verify_image <File Name> <Addr> [bin|ihex|elf] 	-将文件File Name与内存Addr开始的数据进行比较,格式可选,bin、ihex、elf

step [Addr]		-不加地址:从当前位置单步执行; 加地址:从Addr处单步执行
poll		    -查询目标板当前状态
bp <Addr> <Length> [hw] 	-在Addr地址设置断点,指令长度为Length,hw代表硬件断点
rbp <Addr>		 -删除Addr处的断点

mdw <Addr> [Count]	 -显示从物理地址Addr开始的Count(缺省则默认为1)个字(4Bytes)
mdh <Addr> [Count]	 -显示从物理地址Addr开始的Count(缺省则默认为1)个半字(2Bytes)
mdb <Addr> [Count]	 -显示从物理地址Addr开始的Count(缺省则默认为1)个字节(1Byte)
mww <Addr> <Value>   -向物理地址Addr写入Value,大小:一个字(4Bytes)
mwh <Addr> <Value>   -向物理地址Addr写入Value,大小:一个半字(2Bytes)
mwb <Addr> <Value>   -向物理地址Addr写入Value,大小:一个字节(1Bytes)

觉得这篇文章对你有帮助的话,就留下一个赞吧^ v ^*
请尊重作者,转载还请注明出处!感谢配合~
[作者]: Imagine Miracle
[版权]: 本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
[本文链接]: https://blog.csdn.net/qq_36393978/article/details/112509307

 类似资料: