You can subscribe to this list here.
| 2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(75) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2009 |
Jan
(70) |
Feb
(20) |
Mar
(52) |
Apr
(149) |
May
(387) |
Jun
(466) |
Jul
(133) |
Aug
(87) |
Sep
(122) |
Oct
(140) |
Nov
(185) |
Dec
(105) |
| 2010 |
Jan
(85) |
Feb
(45) |
Mar
(75) |
Apr
(17) |
May
(41) |
Jun
(52) |
Jul
(33) |
Aug
(29) |
Sep
(36) |
Oct
(15) |
Nov
(26) |
Dec
(34) |
| 2011 |
Jan
(26) |
Feb
(25) |
Mar
(26) |
Apr
(29) |
May
(20) |
Jun
(27) |
Jul
(15) |
Aug
(32) |
Sep
(13) |
Oct
(64) |
Nov
(60) |
Dec
(10) |
| 2012 |
Jan
(64) |
Feb
(63) |
Mar
(39) |
Apr
(43) |
May
(54) |
Jun
(11) |
Jul
(30) |
Aug
(45) |
Sep
(11) |
Oct
(70) |
Nov
(24) |
Dec
(23) |
| 2013 |
Jan
(17) |
Feb
(8) |
Mar
(35) |
Apr
(40) |
May
(20) |
Jun
(24) |
Jul
(36) |
Aug
(25) |
Sep
(42) |
Oct
(40) |
Nov
(9) |
Dec
(21) |
| 2014 |
Jan
(29) |
Feb
(24) |
Mar
(60) |
Apr
(22) |
May
(22) |
Jun
(46) |
Jul
(11) |
Aug
(23) |
Sep
(26) |
Oct
(10) |
Nov
(14) |
Dec
(2) |
| 2015 |
Jan
(28) |
Feb
(47) |
Mar
(33) |
Apr
(58) |
May
(5) |
Jun
(1) |
Jul
|
Aug
(8) |
Sep
(12) |
Oct
(25) |
Nov
(58) |
Dec
(21) |
| 2016 |
Jan
(12) |
Feb
(40) |
Mar
(2) |
Apr
(1) |
May
(67) |
Jun
(2) |
Jul
(5) |
Aug
(36) |
Sep
|
Oct
(24) |
Nov
(17) |
Dec
(50) |
| 2017 |
Jan
(14) |
Feb
(16) |
Mar
(2) |
Apr
(35) |
May
(14) |
Jun
(16) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
(19) |
Nov
|
Dec
(16) |
| 2018 |
Jan
(55) |
Feb
(11) |
Mar
(34) |
Apr
(14) |
May
(4) |
Jun
(20) |
Jul
(39) |
Aug
(16) |
Sep
(17) |
Oct
(16) |
Nov
(20) |
Dec
(30) |
| 2019 |
Jan
(29) |
Feb
(24) |
Mar
(37) |
Apr
(26) |
May
(19) |
Jun
(21) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(12) |
Nov
(12) |
Dec
(12) |
| 2020 |
Jan
(47) |
Feb
(36) |
Mar
(54) |
Apr
(44) |
May
(37) |
Jun
(19) |
Jul
(32) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(32) |
Dec
(11) |
| 2021 |
Jan
(14) |
Feb
(5) |
Mar
(40) |
Apr
(32) |
May
(42) |
Jun
(31) |
Jul
(29) |
Aug
(47) |
Sep
(38) |
Oct
(17) |
Nov
(74) |
Dec
(33) |
| 2022 |
Jan
(11) |
Feb
(15) |
Mar
(40) |
Apr
(21) |
May
(39) |
Jun
(44) |
Jul
(19) |
Aug
(46) |
Sep
(79) |
Oct
(35) |
Nov
(21) |
Dec
(15) |
| 2023 |
Jan
(56) |
Feb
(13) |
Mar
(43) |
Apr
(28) |
May
(60) |
Jun
(15) |
Jul
(29) |
Aug
(28) |
Sep
(32) |
Oct
(21) |
Nov
(42) |
Dec
(39) |
| 2024 |
Jan
(35) |
Feb
(17) |
Mar
(28) |
Apr
(7) |
May
(14) |
Jun
(35) |
Jul
(30) |
Aug
(35) |
Sep
(30) |
Oct
(28) |
Nov
(38) |
Dec
(18) |
| 2025 |
Jan
(21) |
Feb
(28) |
Mar
(36) |
Apr
(35) |
May
(34) |
Jun
(58) |
Jul
(9) |
Aug
(54) |
Sep
(47) |
Oct
(15) |
Nov
(47) |
Dec
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-10 13:35:26
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 5f6b25aa91eb81903aed128ee304ffc69e0492f3 (commit)
from 2bd40b0bf930459f0fc3dbcbde3ac2f40ff56e4e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5f6b25aa91eb81903aed128ee304ffc69e0492f3
Author: Peter Lawrence <maj...@gm...>
Date: Wed Nov 15 09:58:24 2023 -0600
tcl/target/at91sama5d2.cfg: allow choice of SWD instead of JTAG
The target supports both SWD and JTAG, but the existing cfg file
only supports JTAG. Using the standard [using_jtag] mechanism,
the user would now have a choice.
Change-Id: Ic6adb68090422812d591f6bf5b945ac10f323c74
Signed-off-by: Peter Lawrence <maj...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8020
Reviewed-by: Jörg Wunsch <op...@ur...>
Reviewed-by: Paul Fertser <fer...@gm...>
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/tcl/target/at91sama5d2.cfg b/tcl/target/at91sama5d2.cfg
index 65e5217e1..30ddc92a9 100644
--- a/tcl/target/at91sama5d2.cfg
+++ b/tcl/target/at91sama5d2.cfg
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
+# SAMA5D2 devices support both JTAG and SWD transports.
+#
# The JTAG connection is disabled at reset, and during the ROM Code execution.
# It is re-enabled when the ROM code jumps in the boot file copied from an
# external Flash memory into the internalSRAM, or when the ROM code launches
@@ -12,14 +14,28 @@
# - if enabled, boundary Scan mode is activated. JTAG ID Code value is 0x05B3F03F.
# - if disabled, ICE mode is activated. Debug Port JTAG IDCODE value is 0x5BA00477
#
+
+source [find target/swj-dp.tcl]
+
+#jtag scan chain
+if { [info exists CPUTAPID] } {
+ set _CPUTAPID $CPUTAPID
+} else {
+ if { [using_jtag] } {
+ set _CPUTAPID 0x5ba00477
+ } else {
+ # SWD IDCODE (single drop, arm)
+ set _CPUTAPID 0x5ba02477
+ }
+}
+
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME at91sama5d2
}
-jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x0f \
- -expected-id 0x5ba00477
+swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
# Cortex-A5 target
set _TARGETNAME $_CHIPNAME.cpu_a5
-----------------------------------------------------------------------
Summary of changes:
tcl/target/at91sama5d2.cfg | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-10 13:34:21
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 2bd40b0bf930459f0fc3dbcbde3ac2f40ff56e4e (commit)
from 0ce08ec858add3e26ba04536b87fad680561fe50 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 2bd40b0bf930459f0fc3dbcbde3ac2f40ff56e4e
Author: Karl Palsson <ka...@tw...>
Date: Wed Nov 22 09:57:06 2023 +0000
target: Increase maximum profile sample count to 1000000
Change-Id: I38276dd1af011ce5781b0264b7cbb08c31a0a2ad
Signed-off-by: Paul Reimer <pa...@za...>
Signed-off-by: Karl Palsson <ka...@tw...>
Reviewed-on: https://review.openocd.org/c/openocd/+/6099
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index db7315fe4..6c6519d62 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9492,7 +9492,7 @@ TCP/IP port 9090.
@deffn {Command} {profile} seconds filename [start end]
Profiling samples the CPU's program counter as quickly as possible,
which is useful for non-intrusive stochastic profiling.
-Saves up to 10000 samples in @file{filename} using ``gmon.out''
+Saves up to 1000000 samples in @file{filename} using ``gmon.out''
format. Optional @option{start} and @option{end} parameters allow to
limit the address range.
@end deffn
diff --git a/src/target/target.c b/src/target/target.c
index 2703f7b00..d7283324f 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -4298,7 +4298,7 @@ COMMAND_HANDLER(handle_profile_command)
if ((CMD_ARGC != 2) && (CMD_ARGC != 4))
return ERROR_COMMAND_SYNTAX_ERROR;
- const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000;
+ const uint32_t MAX_PROFILE_SAMPLE_NUM = 1000000;
uint32_t offset;
uint32_t num_of_samples;
int retval = ERROR_OK;
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 2 +-
src/target/target.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-10 13:33:36
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 0ce08ec858add3e26ba04536b87fad680561fe50 (commit)
from 4003762177b1aec2ab27eaa6946b47f13c457bbc (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0ce08ec858add3e26ba04536b87fad680561fe50
Author: Kirill Radkin <kir...@sy...>
Date: Tue Oct 31 18:24:35 2023 +0300
target: Add some info messages about examination process.
These messages helps to clarify current status of examination process
Change-Id: I5d93903c4680deed2c1bf707d8f7ef0b48ffdc9a
Signed-off-by: Kirill Radkin <kir...@sy...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8013
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/target.c b/src/target/target.c
index f847894d6..2703f7b00 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -675,10 +675,14 @@ static int default_check_reset(struct target *target)
* Keep in sync */
int target_examine_one(struct target *target)
{
+ LOG_TARGET_DEBUG(target, "Examination started");
+
target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
int retval = target->type->examine(target);
if (retval != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Examination failed");
+ LOG_TARGET_DEBUG(target, "examine() returned error code %d", retval);
target_reset_examined(target);
target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_FAIL);
return retval;
@@ -687,6 +691,7 @@ int target_examine_one(struct target *target)
target_set_examined(target);
target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
+ LOG_TARGET_INFO(target, "Examination succeed");
return ERROR_OK;
}
-----------------------------------------------------------------------
Summary of changes:
src/target/target.c | 5 +++++
1 file changed, 5 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-10 13:32:27
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 4003762177b1aec2ab27eaa6946b47f13c457bbc (commit)
from d06d8ea3e4d0057dd13a6dac792b1ad7c246aebb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4003762177b1aec2ab27eaa6946b47f13c457bbc
Author: Erhan Kurubas <erh...@es...>
Date: Mon Jul 10 23:47:06 2023 +0200
target/espressif: add algorithm support to xtensa chips
Also includes esp_xtensa flasher stub jumper binary.
Signed-off-by: Erhan Kurubas <erh...@es...>
Change-Id: I054ce31033ca6a87afe9b5325b545338a7d8fe8f
Reviewed-on: https://review.openocd.org/c/openocd/+/7772
Tested-by: jenkins
Reviewed-by: Ian Thompson <ia...@ca...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/contrib/loaders/trampoline/espressif/xtensa/Makefile b/contrib/loaders/trampoline/espressif/xtensa/Makefile
new file mode 100644
index 000000000..bd1f63044
--- /dev/null
+++ b/contrib/loaders/trampoline/espressif/xtensa/Makefile
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Espressif Xtensa Makefile to compile flasher stub wrapper
+# Copyright (C) 2023 Espressif Systems Ltd.
+
+# Prefix for Espressif xtensa cross compilers (can include a directory path)
+CROSS ?= xtensa-esp32-elf-
+
+APP_ARCH := xtensa
+APP_CHIP_PATH := $(shell pwd)
+SRCS := $(APP_CHIP_PATH)/esp_xtensa_stub_tramp_win.S
+
+BIN2C = ../../../../../src/helper/bin2char.sh
+BUILD_DIR = build
+
+APP = esp_xtensa_stub_tramp_win
+APP_OBJ = $(BUILD_DIR)/$(APP).o
+APP_BIN = $(BUILD_DIR)/$(APP).bin
+APP_CODE = $(APP).inc
+
+.PHONY: all clean
+
+all: $(BUILD_DIR) $(APP_OBJ) $(APP_CODE)
+
+$(BUILD_DIR):
+ $(Q) mkdir $@
+
+$(APP_OBJ): $(SRCS)
+ @echo " CC $^ -> $@"
+ $(Q) $(CROSS)gcc -c $(CFLAGS) -o $@ $^
+
+$(APP_CODE): $(APP_OBJ)
+ @echo " CC $^ -> $@"
+ $(Q) $(CROSS)objcopy -O binary -j.text $^ $(APP_BIN)
+ $(Q) $(BIN2C) < $(APP_BIN) > $@
+
+clean:
+ $(Q) rm -rf $(BUILD_DIR)
diff --git a/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S
new file mode 100644
index 000000000..e0c827d9f
--- /dev/null
+++ b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Xtensa flasher stub wrapper *
+ * Copyright (C) 2017 Espressif Systems Ltd. *
+ ***************************************************************************/
+
+/*
+ * Expects :
+ * a0 = zero
+ * a1 = stack_base + stack_size - 16, 16 bytes aligned
+ * a8 = address of the function to call
+ * Params :
+ * a2 = command arg0, result (out)
+ * a3 = command arg1
+ * a4 = command arg2
+ * a5 = command arg3
+ * a6 = command arg4
+ * Maximum 5 user args
+ */
+ .text
+
+ .align 4
+_stub_enter:
+ /* initialize initial stack frame for callx8 */
+ addi a9, sp, 32 /* point 16 past extra save area */
+ s32e a9, sp, -12 /* access to extra save area */
+ /* prepare args */
+ mov a10, a2
+ mov a11, a3
+ mov a12, a4
+ mov a13, a5
+ mov a14, a6
+ /* call stub */
+ callx8 a8
+ /* prepare return value */
+ mov a2, a10
+ break 0,0
+
+_idle_loop:
+ j _idle_loop
diff --git a/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc
new file mode 100644
index 000000000..1657223e1
--- /dev/null
+++ b/contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc
@@ -0,0 +1,3 @@
+/* Autogenerated with ../../../../../src/helper/bin2char.sh */
+0x92,0xc1,0x20,0x90,0xd1,0x49,0xad,0x02,0xbd,0x03,0xcd,0x04,0xdd,0x05,0x60,0xe6,
+0x20,0xe0,0x08,0x00,0x2d,0x0a,0x00,0x40,0x00,0x06,0xff,0xff,
diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am
index 1fbd926d9..cf82ee995 100644
--- a/src/target/espressif/Makefile.am
+++ b/src/target/espressif/Makefile.am
@@ -10,6 +10,8 @@ noinst_LTLIBRARIES += %D%/libespressif.la
%D%/esp_xtensa_semihosting.h \
%D%/esp_xtensa_apptrace.c \
%D%/esp_xtensa_apptrace.h \
+ %D%/esp_xtensa_algorithm.c \
+ %D%/esp_xtensa_algorithm.h \
%D%/esp32_apptrace.c \
%D%/esp32_apptrace.h \
%D%/esp32.c \
diff --git a/src/target/espressif/esp.c b/src/target/espressif/esp.c
index 9583d6493..600f6d7e9 100644
--- a/src/target/espressif/esp.c
+++ b/src/target/espressif/esp.c
@@ -14,6 +14,16 @@
#include "target/target.h"
#include "esp.h"
+int esp_common_init(struct esp_common *esp, const struct esp_algorithm_hw *algo_hw)
+{
+ if (!esp)
+ return ERROR_FAIL;
+
+ esp->algo_hw = algo_hw;
+
+ return ERROR_OK;
+}
+
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs)
{
uint32_t table_size, table_start_id, desc_entry_id, gcov_entry_id;
diff --git a/src/target/espressif/esp.h b/src/target/espressif/esp.h
index 3ba2b8bcf..6e0a2d2d3 100644
--- a/src/target/espressif/esp.h
+++ b/src/target/espressif/esp.h
@@ -77,9 +77,11 @@ struct esp_dbg_stubs {
};
struct esp_common {
+ const struct esp_algorithm_hw *algo_hw;
struct esp_dbg_stubs dbg_stubs;
};
+int esp_common_init(struct esp_common *esp, const struct esp_algorithm_hw *algo_hw);
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs);
#endif /* OPENOCD_TARGET_ESP_H */
diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c
index b510f287c..324aa3993 100644
--- a/src/target/espressif/esp32.c
+++ b/src/target/espressif/esp32.c
@@ -484,6 +484,10 @@ struct target_type esp32_target = {
.get_gdb_arch = xtensa_get_gdb_arch,
.get_gdb_reg_list = xtensa_get_gdb_reg_list,
+ .run_algorithm = xtensa_run_algorithm,
+ .start_algorithm = xtensa_start_algorithm,
+ .wait_algorithm = xtensa_wait_algorithm,
+
.add_breakpoint = esp_xtensa_breakpoint_add,
.remove_breakpoint = esp_xtensa_breakpoint_remove,
diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c
index dadc130c1..2abde479e 100644
--- a/src/target/espressif/esp32s2.c
+++ b/src/target/espressif/esp32s2.c
@@ -521,6 +521,10 @@ struct target_type esp32s2_target = {
.get_gdb_arch = xtensa_get_gdb_arch,
.get_gdb_reg_list = xtensa_get_gdb_reg_list,
+ .run_algorithm = xtensa_run_algorithm,
+ .start_algorithm = xtensa_start_algorithm,
+ .wait_algorithm = xtensa_wait_algorithm,
+
.add_breakpoint = esp_xtensa_breakpoint_add,
.remove_breakpoint = esp_xtensa_breakpoint_remove,
diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c
index 5036956ee..22e1630e1 100644
--- a/src/target/espressif/esp32s3.c
+++ b/src/target/espressif/esp32s3.c
@@ -405,6 +405,10 @@ struct target_type esp32s3_target = {
.get_gdb_arch = xtensa_get_gdb_arch,
.get_gdb_reg_list = xtensa_get_gdb_reg_list,
+ .run_algorithm = xtensa_run_algorithm,
+ .start_algorithm = xtensa_start_algorithm,
+ .wait_algorithm = xtensa_wait_algorithm,
+
.add_breakpoint = esp_xtensa_breakpoint_add,
.remove_breakpoint = esp_xtensa_breakpoint_remove,
diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c
index 0bd2cdd9d..11895d23b 100644
--- a/src/target/espressif/esp_xtensa.c
+++ b/src/target/espressif/esp_xtensa.c
@@ -12,10 +12,12 @@
#include <stdbool.h>
#include <stdint.h>
#include <target/smp.h>
-#include "esp_xtensa_apptrace.h"
#include <target/register.h>
+#include "esp.h"
#include "esp_xtensa.h"
+#include "esp_xtensa_apptrace.h"
#include "esp_semihosting.h"
+#include "esp_xtensa_algorithm.h"
#define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_) \
do { \
@@ -68,6 +70,10 @@ int esp_xtensa_init_arch_info(struct target *target,
int ret = xtensa_init_arch_info(target, &esp_xtensa->xtensa, dm_cfg);
if (ret != ERROR_OK)
return ret;
+ ret = esp_common_init(&esp_xtensa->esp, &xtensa_algo_hw);
+ if (ret != ERROR_OK)
+ return ret;
+
esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops;
esp_xtensa->apptrace.hw = &esp_xtensa_apptrace_hw;
return ERROR_OK;
diff --git a/src/target/espressif/esp_xtensa_algorithm.c b/src/target/espressif/esp_xtensa_algorithm.c
new file mode 100644
index 000000000..68005cbf2
--- /dev/null
+++ b/src/target/espressif/esp_xtensa_algorithm.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Module to run arbitrary code on Xtensa using OpenOCD *
+ * Copyright (C) 2019 Espressif Systems Ltd. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <target/xtensa/xtensa.h>
+#include "esp_xtensa_algorithm.h"
+
+static int esp_xtensa_algo_init(struct target *target, struct esp_algorithm_run_data *run,
+ uint32_t num_args, va_list ap);
+static int esp_xtensa_algo_cleanup(struct target *target, struct esp_algorithm_run_data *run);
+static const uint8_t *esp_xtensa_stub_tramp_get(struct target *target, size_t *size);
+
+const struct esp_algorithm_hw xtensa_algo_hw = {
+ .algo_init = esp_xtensa_algo_init,
+ .algo_cleanup = esp_xtensa_algo_cleanup,
+ .stub_tramp_get = esp_xtensa_stub_tramp_get,
+};
+
+/* Generated from contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S */
+static const uint8_t esp_xtensa_stub_tramp_win[] = {
+#include "../../../contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc"
+};
+
+static const uint8_t *esp_xtensa_stub_tramp_get(struct target *target, size_t *size)
+{
+ struct xtensa *xtensa = target_to_xtensa(target);
+
+ if (!xtensa->core_config->windowed) {
+ LOG_ERROR("Running stubs is not supported for cores without windowed registers option!");
+ return NULL;
+ }
+ *size = sizeof(esp_xtensa_stub_tramp_win);
+ return esp_xtensa_stub_tramp_win;
+}
+
+static int esp_xtensa_algo_regs_init_start(struct target *target, struct esp_algorithm_run_data *run)
+{
+ uint32_t stack_addr = run->stub.stack_addr;
+
+ LOG_TARGET_DEBUG(target, "Check stack addr 0x%x", stack_addr);
+ if (stack_addr & 0xFUL) {
+ stack_addr &= ~0xFUL;
+ LOG_TARGET_DEBUG(target, "Adjust stack addr to 0x%x", stack_addr);
+ }
+ stack_addr -= 16;
+ struct reg_param *params = run->reg_args.params;
+ init_reg_param(¶ms[0], "a0", 32, PARAM_OUT); /*TODO: move to tramp */
+ init_reg_param(¶ms[1], "a1", 32, PARAM_OUT);
+ init_reg_param(¶ms[2], "a8", 32, PARAM_OUT);
+ init_reg_param(¶ms[3], "windowbase", 32, PARAM_OUT); /*TODO: move to tramp */
+ init_reg_param(¶ms[4], "windowstart", 32, PARAM_OUT); /*TODO: move to tramp */
+ init_reg_param(¶ms[5], "ps", 32, PARAM_OUT);
+ buf_set_u32(params[0].value, 0, 32, 0); /* a0 TODO: move to tramp */
+ buf_set_u32(params[1].value, 0, 32, stack_addr); /* a1 */
+ buf_set_u32(params[2].value, 0, 32, run->stub.entry); /* a8 */
+ buf_set_u32(params[3].value, 0, 32, 0x0); /* initial window base TODO: move to tramp */
+ buf_set_u32(params[4].value, 0, 32, 0x1); /* initial window start TODO: move to tramp */
+ buf_set_u32(params[5].value, 0, 32, 0x60025); /* enable WOE, UM and debug interrupts level (6) */
+ return ERROR_OK;
+}
+
+static int esp_xtensa_algo_init(struct target *target, struct esp_algorithm_run_data *run,
+ uint32_t num_args, va_list ap)
+{
+ enum xtensa_mode core_mode = XT_MODE_ANY;
+ static const char *const arg_regs[] = { "a2", "a3", "a4", "a5", "a6" };
+
+ if (!run)
+ return ERROR_FAIL;
+
+ if (num_args > ARRAY_SIZE(arg_regs)) {
+ LOG_ERROR("Too many algo user args %u! Max %zu args are supported.", num_args, ARRAY_SIZE(arg_regs));
+ return ERROR_FAIL;
+ }
+
+ struct xtensa_algorithm *ainfo = calloc(1, sizeof(struct xtensa_algorithm));
+ if (!ainfo) {
+ LOG_ERROR("Unable to allocate memory");
+ return ERROR_FAIL;
+ }
+
+ if (run->arch_info) {
+ struct xtensa_algorithm *xtensa_algo = run->arch_info;
+ core_mode = xtensa_algo->core_mode;
+ }
+
+ run->reg_args.first_user_param = ESP_XTENSA_STUB_ARGS_FUNC_START;
+ run->reg_args.count = run->reg_args.first_user_param + num_args;
+ if (num_args == 0)
+ run->reg_args.count++; /* a2 reg is used as the 1st arg and return code */
+ LOG_DEBUG("reg params count %d (%d/%d).",
+ run->reg_args.count,
+ run->reg_args.first_user_param,
+ num_args);
+ run->reg_args.params = calloc(run->reg_args.count, sizeof(struct reg_param));
+ if (!run->reg_args.params) {
+ free(ainfo);
+ LOG_ERROR("Unable to allocate memory");
+ return ERROR_FAIL;
+ }
+
+ esp_xtensa_algo_regs_init_start(target, run);
+
+ init_reg_param(&run->reg_args.params[run->reg_args.first_user_param + 0], "a2", 32, PARAM_IN_OUT);
+
+ if (num_args > 0) {
+ uint32_t arg = va_arg(ap, uint32_t);
+ esp_algorithm_user_arg_set_uint(run, 0, arg);
+ LOG_DEBUG("Set arg[0] = %d (%s)", arg, run->reg_args.params[run->reg_args.first_user_param + 0].reg_name);
+ } else {
+ esp_algorithm_user_arg_set_uint(run, 0, 0);
+ }
+
+ for (unsigned int i = 1; i < num_args; i++) {
+ uint32_t arg = va_arg(ap, uint32_t);
+ init_reg_param(&run->reg_args.params[run->reg_args.first_user_param + i], (char *)arg_regs[i], 32, PARAM_OUT);
+ esp_algorithm_user_arg_set_uint(run, i, arg);
+ LOG_DEBUG("Set arg[%d] = %d (%s)", i, arg, run->reg_args.params[run->reg_args.first_user_param + i].reg_name);
+ }
+
+ ainfo->core_mode = core_mode;
+ run->stub.ainfo = ainfo;
+ return ERROR_OK;
+}
+
+static int esp_xtensa_algo_cleanup(struct target *target, struct esp_algorithm_run_data *run)
+{
+ free(run->stub.ainfo);
+ for (uint32_t i = 0; i < run->reg_args.count; i++)
+ destroy_reg_param(&run->reg_args.params[i]);
+ free(run->reg_args.params);
+ return ERROR_OK;
+}
diff --git a/src/target/espressif/esp_xtensa_algorithm.h b/src/target/espressif/esp_xtensa_algorithm.h
new file mode 100644
index 000000000..36fa1a331
--- /dev/null
+++ b/src/target/espressif/esp_xtensa_algorithm.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Module to run arbitrary code on Xtensa using OpenOCD *
+ * Copyright (C) 2019 Espressif Systems Ltd. *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_ESP_XTENSA_ALGO_H
+#define OPENOCD_TARGET_ESP_XTENSA_ALGO_H
+
+#include <target/xtensa/xtensa.h>
+#include <target/espressif/esp_algorithm.h>
+
+/** Index of the first user-defined algo arg. @see algorithm_stub */
+#define ESP_XTENSA_STUB_ARGS_FUNC_START 6
+
+extern const struct esp_algorithm_hw xtensa_algo_hw;
+
+#endif /* OPENOCD_TARGET_XTENSA_ALGO_H */
-----------------------------------------------------------------------
Summary of changes:
.../espressif/xtensa/Makefile} | 26 ++--
.../espressif/xtensa/esp_xtensa_stub_tramp_win.S | 41 ++++++
.../espressif/xtensa/esp_xtensa_stub_tramp_win.inc | 3 +
src/target/espressif/Makefile.am | 2 +
src/target/espressif/esp.c | 10 ++
src/target/espressif/esp.h | 2 +
src/target/espressif/esp32.c | 4 +
src/target/espressif/esp32s2.c | 4 +
src/target/espressif/esp32s3.c | 4 +
src/target/espressif/esp_xtensa.c | 8 +-
src/target/espressif/esp_xtensa_algorithm.c | 140 +++++++++++++++++++++
src/target/espressif/esp_xtensa_algorithm.h | 19 +++
12 files changed, 248 insertions(+), 15 deletions(-)
copy contrib/loaders/{reset/espressif/common.mk => trampoline/espressif/xtensa/Makefile} (53%)
create mode 100644 contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S
create mode 100644 contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc
create mode 100644 src/target/espressif/esp_xtensa_algorithm.c
create mode 100644 src/target/espressif/esp_xtensa_algorithm.h
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-10 13:29:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via d06d8ea3e4d0057dd13a6dac792b1ad7c246aebb (commit)
from d3ffcc784dac76ffb5d5d29ca73cb56f38154c1a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d06d8ea3e4d0057dd13a6dac792b1ad7c246aebb
Author: Erhan Kurubas <erh...@es...>
Date: Mon Jul 10 23:56:56 2023 +0200
target/xtensa: add algorithm support
Add arch level functions to execute code on the target
Signed-off-by: Erhan Kurubas <erh...@es...>
Change-Id: I089095de6fcb9906ad8c84232fa52a77db5e6185
Reviewed-on: https://review.openocd.org/c/openocd/+/7771
Tested-by: jenkins
Reviewed-by: Ian Thompson <ia...@ca...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
index 85dce0614..d2ca32c1d 100644
--- a/src/target/xtensa/xtensa.c
+++ b/src/target/xtensa/xtensa.c
@@ -16,6 +16,7 @@
#include <helper/time_support.h>
#include <helper/align.h>
#include <target/register.h>
+#include <target/algorithm.h>
#include "xtensa_chip.h"
#include "xtensa.h"
@@ -2635,6 +2636,214 @@ int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoin
return ERROR_OK;
}
+int xtensa_start_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t entry_point, target_addr_t exit_point,
+ void *arch_info)
+{
+ struct xtensa *xtensa = target_to_xtensa(target);
+ struct xtensa_algorithm *algorithm_info = arch_info;
+ int retval = ERROR_OK;
+ bool usr_ps = false;
+
+ /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint
+ * at the exit point */
+
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("Target not halted!");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ for (unsigned int i = 0; i < xtensa->core_cache->num_regs; i++) {
+ struct reg *reg = &xtensa->core_cache->reg_list[i];
+ buf_cpy(reg->value, xtensa->algo_context_backup[i], reg->size);
+ }
+ /* save debug reason, it will be changed */
+ algorithm_info->ctx_debug_reason = target->debug_reason;
+ /* write mem params */
+ for (int i = 0; i < num_mem_params; i++) {
+ if (mem_params[i].direction != PARAM_IN) {
+ retval = target_write_buffer(target, mem_params[i].address,
+ mem_params[i].size,
+ mem_params[i].value);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ }
+ /* write reg params */
+ for (int i = 0; i < num_reg_params; i++) {
+ if (reg_params[i].size > 32) {
+ LOG_ERROR("BUG: not supported register size (%d)", reg_params[i].size);
+ return ERROR_FAIL;
+ }
+ struct reg *reg = register_get_by_name(xtensa->core_cache, reg_params[i].reg_name, 0);
+ if (!reg) {
+ LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
+ return ERROR_FAIL;
+ }
+ if (reg->size != reg_params[i].size) {
+ LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
+ return ERROR_FAIL;
+ }
+ if (memcmp(reg_params[i].reg_name, "ps", 3)) {
+ usr_ps = true;
+ } else {
+ unsigned int reg_id = xtensa->eps_dbglevel_idx;
+ assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!");
+ reg = &xtensa->core_cache->reg_list[reg_id];
+ }
+ xtensa_reg_set_value(reg, buf_get_u32(reg_params[i].value, 0, reg->size));
+ reg->valid = 1;
+ }
+ /* ignore custom core mode if custom PS value is specified */
+ if (!usr_ps) {
+ unsigned int eps_reg_idx = xtensa->eps_dbglevel_idx;
+ xtensa_reg_val_t ps = xtensa_reg_get(target, eps_reg_idx);
+ enum xtensa_mode core_mode = XT_PS_RING_GET(ps);
+ if (algorithm_info->core_mode != XT_MODE_ANY && algorithm_info->core_mode != core_mode) {
+ LOG_DEBUG("setting core_mode: 0x%x", algorithm_info->core_mode);
+ xtensa_reg_val_t new_ps = (ps & ~XT_PS_RING_MSK) | XT_PS_RING(algorithm_info->core_mode);
+ /* save previous core mode */
+ /* TODO: core_mode is not restored for now. Can be added to the end of wait_algorithm */
+ algorithm_info->core_mode = core_mode;
+ xtensa_reg_set(target, eps_reg_idx, new_ps);
+ xtensa->core_cache->reg_list[eps_reg_idx].valid = 1;
+ }
+ }
+
+ return xtensa_resume(target, 0, entry_point, 1, 1);
+}
+
+/** Waits for an algorithm in the target. */
+int xtensa_wait_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t exit_point, unsigned int timeout_ms,
+ void *arch_info)
+{
+ struct xtensa *xtensa = target_to_xtensa(target);
+ struct xtensa_algorithm *algorithm_info = arch_info;
+ int retval = ERROR_OK;
+ xtensa_reg_val_t pc;
+
+ /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint
+ * at the exit point */
+
+ retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
+ /* If the target fails to halt due to the breakpoint, force a halt */
+ if (retval != ERROR_OK || target->state != TARGET_HALTED) {
+ retval = target_halt(target);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = target_wait_state(target, TARGET_HALTED, 500);
+ if (retval != ERROR_OK)
+ return retval;
+ LOG_TARGET_ERROR(target, "not halted %d, pc 0x%" PRIx32 ", ps 0x%" PRIx32, retval,
+ xtensa_reg_get(target, XT_REG_IDX_PC),
+ xtensa_reg_get(target, xtensa->eps_dbglevel_idx));
+ return ERROR_TARGET_TIMEOUT;
+ }
+ pc = xtensa_reg_get(target, XT_REG_IDX_PC);
+ if (exit_point && pc != exit_point) {
+ LOG_ERROR("failed algorithm halted at 0x%" PRIx32 ", expected " TARGET_ADDR_FMT, pc, exit_point);
+ return ERROR_TARGET_TIMEOUT;
+ }
+ /* Copy core register values to reg_params[] */
+ for (int i = 0; i < num_reg_params; i++) {
+ if (reg_params[i].direction != PARAM_OUT) {
+ struct reg *reg = register_get_by_name(xtensa->core_cache, reg_params[i].reg_name, 0);
+ if (!reg) {
+ LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
+ return ERROR_FAIL;
+ }
+ if (reg->size != reg_params[i].size) {
+ LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
+ return ERROR_FAIL;
+ }
+ buf_set_u32(reg_params[i].value, 0, 32, xtensa_reg_get_value(reg));
+ }
+ }
+ /* Read memory values to mem_params */
+ LOG_DEBUG("Read mem params");
+ for (int i = 0; i < num_mem_params; i++) {
+ LOG_DEBUG("Check mem param @ " TARGET_ADDR_FMT, mem_params[i].address);
+ if (mem_params[i].direction != PARAM_OUT) {
+ LOG_DEBUG("Read mem param @ " TARGET_ADDR_FMT, mem_params[i].address);
+ retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ }
+
+ /* avoid gdb keep_alive warning */
+ keep_alive();
+
+ for (int i = xtensa->core_cache->num_regs - 1; i >= 0; i--) {
+ struct reg *reg = &xtensa->core_cache->reg_list[i];
+ if (i == XT_REG_IDX_PS) {
+ continue; /* restore mapped reg number of PS depends on NDEBUGLEVEL */
+ } else if (i == XT_REG_IDX_DEBUGCAUSE) {
+ /*FIXME: restoring DEBUGCAUSE causes exception when executing corresponding
+ * instruction in DIR */
+ LOG_DEBUG("Skip restoring register %s: 0x%8.8" PRIx32 " -> 0x%8.8" PRIx32,
+ xtensa->core_cache->reg_list[i].name,
+ buf_get_u32(reg->value, 0, 32),
+ buf_get_u32(xtensa->algo_context_backup[i], 0, 32));
+ buf_cpy(xtensa->algo_context_backup[i], reg->value, reg->size);
+ xtensa->core_cache->reg_list[i].dirty = 0;
+ xtensa->core_cache->reg_list[i].valid = 0;
+ } else if (memcmp(xtensa->algo_context_backup[i], reg->value, reg->size / 8)) {
+ if (reg->size <= 32) {
+ LOG_DEBUG("restoring register %s: 0x%8.8" PRIx32 " -> 0x%8.8" PRIx32,
+ xtensa->core_cache->reg_list[i].name,
+ buf_get_u32(reg->value, 0, reg->size),
+ buf_get_u32(xtensa->algo_context_backup[i], 0, reg->size));
+ } else if (reg->size <= 64) {
+ LOG_DEBUG("restoring register %s: 0x%8.8" PRIx64 " -> 0x%8.8" PRIx64,
+ xtensa->core_cache->reg_list[i].name,
+ buf_get_u64(reg->value, 0, reg->size),
+ buf_get_u64(xtensa->algo_context_backup[i], 0, reg->size));
+ } else {
+ LOG_DEBUG("restoring register %s %u-bits", xtensa->core_cache->reg_list[i].name, reg->size);
+ }
+ buf_cpy(xtensa->algo_context_backup[i], reg->value, reg->size);
+ xtensa->core_cache->reg_list[i].dirty = 1;
+ xtensa->core_cache->reg_list[i].valid = 1;
+ }
+ }
+ target->debug_reason = algorithm_info->ctx_debug_reason;
+
+ retval = xtensa_write_dirty_registers(target);
+ if (retval != ERROR_OK)
+ LOG_ERROR("Failed to write dirty regs (%d)!", retval);
+
+ return retval;
+}
+
+int xtensa_run_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t entry_point, target_addr_t exit_point,
+ unsigned int timeout_ms, void *arch_info)
+{
+ int retval = xtensa_start_algorithm(target,
+ num_mem_params, mem_params,
+ num_reg_params, reg_params,
+ entry_point, exit_point,
+ arch_info);
+
+ if (retval == ERROR_OK) {
+ retval = xtensa_wait_algorithm(target,
+ num_mem_params, mem_params,
+ num_reg_params, reg_params,
+ exit_point, timeout_ms,
+ arch_info);
+ }
+
+ return retval;
+}
+
static int xtensa_build_reg_cache(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h
index 4216ae24f..3b37122d6 100644
--- a/src/target/xtensa/xtensa.h
+++ b/src/target/xtensa/xtensa.h
@@ -222,6 +222,16 @@ struct xtensa_sw_breakpoint {
uint8_t insn_sz; /* 2 or 3 bytes */
};
+/**
+ * Xtensa algorithm data.
+ */
+struct xtensa_algorithm {
+ /** User can set this to specify which core mode algorithm should be run in. */
+ enum xtensa_mode core_mode;
+ /** Used internally to backup and restore debug_reason. */
+ enum target_debug_reason ctx_debug_reason;
+};
+
#define XTENSA_COMMON_MAGIC 0x54E4E555U
/**
@@ -395,6 +405,21 @@ int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint);
int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint);
+int xtensa_start_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t entry_point, target_addr_t exit_point,
+ void *arch_info);
+int xtensa_wait_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t exit_point, unsigned int timeout_ms,
+ void *arch_info);
+int xtensa_run_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t entry_point, target_addr_t exit_point,
+ unsigned int timeout_ms, void *arch_info);
void xtensa_set_permissive_mode(struct target *target, bool state);
const char *xtensa_get_gdb_arch(struct target *target);
int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p);
-----------------------------------------------------------------------
Summary of changes:
src/target/xtensa/xtensa.c | 209 +++++++++++++++++++++++++++++++++++++++++++++
src/target/xtensa/xtensa.h | 25 ++++++
2 files changed, 234 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-10 13:27:58
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via d3ffcc784dac76ffb5d5d29ca73cb56f38154c1a (commit)
from ba16fdc1c645bda82adb5a06b4403e7501e150c4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d3ffcc784dac76ffb5d5d29ca73cb56f38154c1a
Author: Erhan Kurubas <erh...@es...>
Date: Mon Jul 3 11:02:13 2023 +0200
target/espressif: add algorithm support to execute code on target
This functionality can be useful for;
1-ESP flashing code to load flasher stub on target and
write/read/erase flash.
2-ESP GCOV command uses some of these functions to run
onboard routines to dump coverage info.
This is high level api for the Espressif xtensa and riscv targets
Signed-off-by: Erhan Kurubas <erh...@es...>
Change-Id: I5e618b960bb6566ee618d4ba261f51af97a7cb0e
Reviewed-on: https://review.openocd.org/c/openocd/+/7759
Reviewed-by: Tomas Vanek <va...@fb...>
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am
index 776818ff4..1fbd926d9 100644
--- a/src/target/espressif/Makefile.am
+++ b/src/target/espressif/Makefile.am
@@ -21,4 +21,6 @@ noinst_LTLIBRARIES += %D%/libespressif.la
%D%/esp32_sysview.h \
%D%/segger_sysview.h \
%D%/esp_semihosting.c \
- %D%/esp_semihosting.h
+ %D%/esp_semihosting.h \
+ %D%/esp_algorithm.c \
+ %D%/esp_algorithm.h
diff --git a/src/target/espressif/esp_algorithm.c b/src/target/espressif/esp_algorithm.c
new file mode 100644
index 000000000..79f610b92
--- /dev/null
+++ b/src/target/espressif/esp_algorithm.c
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Espressif chips common algorithm API for OpenOCD *
+ * Copyright (C) 2022 Espressif Systems Ltd. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/align.h>
+#include <target/algorithm.h>
+#include <target/target.h>
+#include "esp_algorithm.h"
+
+#define DEFAULT_ALGORITHM_TIMEOUT_MS 40000 /* ms */
+
+static int esp_algorithm_read_stub_logs(struct target *target, struct esp_algorithm_stub *stub)
+{
+ if (!stub || stub->log_buff_addr == 0 || stub->log_buff_size == 0)
+ return ERROR_FAIL;
+
+ uint32_t len = 0;
+ int retval = target_read_u32(target, stub->log_buff_addr, &len);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* sanity check. log_buff_size = sizeof(len) + sizeof(log_buff) */
+ if (len == 0 || len > stub->log_buff_size - 4)
+ return ERROR_FAIL;
+
+ uint8_t *log_buff = calloc(1, len);
+ if (!log_buff) {
+ LOG_ERROR("Failed to allocate memory for the stub log!");
+ return ERROR_FAIL;
+ }
+ retval = target_read_memory(target, stub->log_buff_addr + 4, 1, len, log_buff);
+ if (retval == ERROR_OK)
+ LOG_OUTPUT("%*.*s", len, len, log_buff);
+ free(log_buff);
+ return retval;
+}
+
+static int esp_algorithm_run_image(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap)
+{
+ struct working_area **mem_handles = NULL;
+
+ if (!run || !run->hw)
+ return ERROR_FAIL;
+
+ int retval = run->hw->algo_init(target, run, num_args, ap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* allocate memory arguments and fill respective reg params */
+ if (run->mem_args.count > 0) {
+ mem_handles = calloc(run->mem_args.count, sizeof(*mem_handles));
+ if (!mem_handles) {
+ LOG_ERROR("Failed to alloc target mem handles!");
+ retval = ERROR_FAIL;
+ goto _cleanup;
+ }
+ /* alloc memory args target buffers */
+ for (uint32_t i = 0; i < run->mem_args.count; i++) {
+ /* small hack: if we need to update some reg param this field holds
+ * appropriate user argument number, */
+ /* otherwise should hold UINT_MAX */
+ uint32_t usr_param_num = run->mem_args.params[i].address;
+ static struct working_area *area;
+ retval = target_alloc_working_area(target, run->mem_args.params[i].size, &area);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to alloc target buffer!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _cleanup;
+ }
+ mem_handles[i] = area;
+ run->mem_args.params[i].address = area->address;
+ if (usr_param_num != UINT_MAX) /* if we need update some register param with mem param value */
+ esp_algorithm_user_arg_set_uint(run, usr_param_num, run->mem_args.params[i].address);
+ }
+ }
+
+ if (run->usr_func_init) {
+ retval = run->usr_func_init(target, run, run->usr_func_arg);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to prepare algorithm host side args stub (%d)!", retval);
+ goto _cleanup;
+ }
+ }
+
+ LOG_DEBUG("Algorithm start @ " TARGET_ADDR_FMT ", stack %d bytes @ " TARGET_ADDR_FMT,
+ run->stub.tramp_mapped_addr, run->stack_size, run->stub.stack_addr);
+ retval = target_start_algorithm(target,
+ run->mem_args.count, run->mem_args.params,
+ run->reg_args.count, run->reg_args.params,
+ run->stub.tramp_mapped_addr, 0,
+ run->stub.ainfo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to start algorithm (%d)!", retval);
+ goto _cleanup;
+ }
+
+ if (run->usr_func) {
+ /* give target algorithm stub time to init itself, then user func can communicate to it safely */
+ alive_sleep(100);
+ retval = run->usr_func(target, run->usr_func_arg);
+ if (retval != ERROR_OK)
+ LOG_ERROR("Failed to exec algorithm user func (%d)!", retval);
+ }
+ uint32_t timeout_ms = 0; /* do not wait if 'usr_func' returned error */
+ if (retval == ERROR_OK)
+ timeout_ms = run->timeout_ms ? run->timeout_ms : DEFAULT_ALGORITHM_TIMEOUT_MS;
+ LOG_DEBUG("Wait algorithm completion");
+ retval = target_wait_algorithm(target,
+ run->mem_args.count, run->mem_args.params,
+ run->reg_args.count, run->reg_args.params,
+ 0, timeout_ms,
+ run->stub.ainfo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to wait algorithm (%d)!", retval);
+ /* target has been forced to stop in target_wait_algorithm() */
+ }
+ esp_algorithm_read_stub_logs(target, &run->stub);
+
+ if (run->usr_func_done)
+ run->usr_func_done(target, run, run->usr_func_arg);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Algorithm run failed (%d)!", retval);
+ } else {
+ run->ret_code = esp_algorithm_user_arg_get_uint(run, 0);
+ LOG_DEBUG("Got algorithm RC 0x%" PRIx32, run->ret_code);
+ }
+
+_cleanup:
+ /* free memory arguments */
+ if (mem_handles) {
+ for (uint32_t i = 0; i < run->mem_args.count; i++) {
+ if (mem_handles[i])
+ target_free_working_area(target, mem_handles[i]);
+ }
+ free(mem_handles);
+ }
+ run->hw->algo_cleanup(target, run);
+
+ return retval;
+}
+
+static int esp_algorithm_run_debug_stub(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap)
+{
+ if (!run || !run->hw)
+ return ERROR_FAIL;
+
+ int retval = run->hw->algo_init(target, run, num_args, ap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("Algorithm start @ " TARGET_ADDR_FMT ", stack %d bytes @ " TARGET_ADDR_FMT,
+ run->stub.tramp_mapped_addr, run->stack_size, run->stub.stack_addr);
+ retval = target_start_algorithm(target,
+ run->mem_args.count, run->mem_args.params,
+ run->reg_args.count, run->reg_args.params,
+ run->stub.tramp_mapped_addr, 0,
+ run->stub.ainfo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to start algorithm (%d)!", retval);
+ goto _cleanup;
+ }
+
+ uint32_t timeout_ms = 0; /* do not wait if 'usr_func' returned error */
+ if (retval == ERROR_OK)
+ timeout_ms = run->timeout_ms ? run->timeout_ms : DEFAULT_ALGORITHM_TIMEOUT_MS;
+ LOG_DEBUG("Wait algorithm completion");
+ retval = target_wait_algorithm(target,
+ run->mem_args.count, run->mem_args.params,
+ run->reg_args.count, run->reg_args.params,
+ 0, timeout_ms,
+ run->stub.ainfo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to wait algorithm (%d)!", retval);
+ /* target has been forced to stop in target_wait_algorithm() */
+ }
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Algorithm run failed (%d)!", retval);
+ } else {
+ run->ret_code = esp_algorithm_user_arg_get_uint(run, 0);
+ LOG_DEBUG("Got algorithm RC 0x%" PRIx32, run->ret_code);
+ }
+
+_cleanup:
+ run->hw->algo_cleanup(target, run);
+
+ return retval;
+}
+
+static void reverse_binary(const uint8_t *src, uint8_t *dest, size_t length)
+{
+ size_t remaining = length % 4;
+ size_t offset = 0;
+ size_t aligned_len = ALIGN_UP(length, 4);
+
+ if (remaining > 0) {
+ /* Put extra bytes to the beginning with padding */
+ memset(dest + remaining, 0xFF, 4 - remaining);
+ for (size_t i = 0; i < remaining; i++)
+ dest[i] = src[length - remaining + i];
+ length -= remaining; /* reverse the others */
+ offset = 4;
+ }
+
+ for (size_t i = offset; i < aligned_len; i += 4) {
+ dest[i + 0] = src[length - i + offset - 4];
+ dest[i + 1] = src[length - i + offset - 3];
+ dest[i + 2] = src[length - i + offset - 2];
+ dest[i + 3] = src[length - i + offset - 1];
+ }
+}
+
+static int load_section_from_image(struct target *target,
+ struct esp_algorithm_run_data *run,
+ int section_num,
+ bool reverse)
+{
+ if (!run)
+ return ERROR_FAIL;
+
+ struct imagesection *section = &run->image.image.sections[section_num];
+ uint32_t sec_wr = 0;
+ uint8_t buf[1024];
+
+ assert(sizeof(buf) % 4 == 0);
+
+ while (sec_wr < section->size) {
+ uint32_t nb = section->size - sec_wr > sizeof(buf) ? sizeof(buf) : section->size - sec_wr;
+ size_t size_read = 0;
+ int retval = image_read_section(&run->image.image, section_num, sec_wr, nb, buf, &size_read);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read stub section (%d)!", retval);
+ return retval;
+ }
+
+ if (reverse) {
+ size_t aligned_len = ALIGN_UP(size_read, 4);
+ uint8_t reversed_buf[aligned_len];
+
+ /* Send original size to allow padding */
+ reverse_binary(buf, reversed_buf, size_read);
+
+ /*
+ The address range accessed via the instruction bus is in reverse order (word-wise) compared to access
+ via the data bus. That is to say, address
+ 0x3FFE_0000 and 0x400B_FFFC access the same word
+ 0x3FFE_0004 and 0x400B_FFF8 access the same word
+ 0x3FFE_0008 and 0x400B_FFF4 access the same word
+ ...
+ The data bus and instruction bus of the CPU are still both little-endian,
+ so the byte order of individual words is not reversed between address spaces.
+ For example, address
+ 0x3FFE_0000 accesses the least significant byte in the word accessed by 0x400B_FFFC.
+ 0x3FFE_0001 accesses the second least significant byte in the word accessed by 0x400B_FFFC.
+ 0x3FFE_0002 accesses the second most significant byte in the word accessed by 0x400B_FFFC.
+ For more details, please refer to ESP32 TRM, Internal SRAM1 section.
+ */
+ retval = target_write_buffer(target, run->image.dram_org - sec_wr - aligned_len, aligned_len, reversed_buf);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write stub section!");
+ return retval;
+ }
+ } else {
+ retval = target_write_buffer(target, section->base_address + sec_wr, size_read, buf);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write stub section!");
+ return retval;
+ }
+ }
+
+ sec_wr += size_read;
+ }
+
+ return ERROR_OK;
+}
+
+/*
+ * Configuration:
+ * ----------------------------
+ * The linker scripts defines the memory layout for the stub code.
+ * The OpenOCD script specifies the workarea address and it's size
+ * Sections defined in the linker are organized to share the same addresses with the workarea.
+ * code and data sections are located in Internal SRAM1 and OpenOCD fills these sections using the data bus.
+ */
+int esp_algorithm_load_func_image(struct target *target, struct esp_algorithm_run_data *run)
+{
+ int retval;
+ size_t tramp_sz = 0;
+ const uint8_t *tramp = NULL;
+ struct duration algo_time;
+ bool alloc_code_working_area = true;
+
+ if (!run || !run->hw)
+ return ERROR_FAIL;
+
+ if (duration_start(&algo_time) != 0) {
+ LOG_ERROR("Failed to start algo time measurement!");
+ return ERROR_FAIL;
+ }
+
+ if (run->hw->stub_tramp_get) {
+ tramp = run->hw->stub_tramp_get(target, &tramp_sz);
+ if (!tramp)
+ return ERROR_FAIL;
+ }
+
+ LOG_DEBUG("stub: base 0x%x, start 0x%" PRIx32 ", %d sections",
+ run->image.image.base_address_set ? (unsigned int)run->image.image.base_address : 0,
+ run->image.image.start_address,
+ run->image.image.num_sections);
+ run->stub.entry = run->image.image.start_address;
+
+ /* [code + trampoline] + <padding> + [data] */
+
+ /* ESP32 has reversed memory region. It will use the last part of DRAM, the others will use the first part.
+ * To avoid complexity for the backup/restore process, we will allocate a workarea for all IRAM region from
+ * the beginning. In that case no need to have a padding area.
+ */
+ if (run->image.reverse) {
+ if (target_alloc_working_area(target, run->image.iram_len, &run->stub.code) != ERROR_OK) {
+ LOG_ERROR("no working area available, can't alloc space for stub code!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _on_error;
+ }
+ alloc_code_working_area = false;
+ }
+
+ uint32_t code_size = 0;
+
+ /* Load code section */
+ for (unsigned int i = 0; i < run->image.image.num_sections; i++) {
+ struct imagesection *section = &run->image.image.sections[i];
+
+ if (section->size == 0)
+ continue;
+
+ if (section->flags & ESP_IMAGE_ELF_PHF_EXEC) {
+ LOG_DEBUG("addr " TARGET_ADDR_FMT ", sz %d, flags %" PRIx64,
+ section->base_address, section->size, section->flags);
+
+ if (alloc_code_working_area) {
+ retval = target_alloc_working_area(target, section->size, &run->stub.code);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("no working area available, can't alloc space for stub code!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _on_error;
+ }
+ }
+
+ if (section->base_address == 0) {
+ section->base_address = run->stub.code->address;
+ /* sanity check, stub is compiled to be run from working area */
+ } else if (run->stub.code->address != section->base_address) {
+ LOG_ERROR("working area " TARGET_ADDR_FMT " and stub code section " TARGET_ADDR_FMT
+ " address mismatch!",
+ section->base_address,
+ run->stub.code->address);
+ retval = ERROR_FAIL;
+ goto _on_error;
+ }
+
+ retval = load_section_from_image(target, run, i, run->image.reverse);
+ if (retval != ERROR_OK)
+ goto _on_error;
+
+ code_size += ALIGN_UP(section->size, 4);
+ break; /* Stub has one executable text section */
+ }
+ }
+
+ /* If exists, load trampoline to the code area */
+ if (tramp) {
+ if (run->stub.tramp_addr == 0) {
+ if (alloc_code_working_area) {
+ /* alloc trampoline in code working area */
+ if (target_alloc_working_area(target, tramp_sz, &run->stub.tramp) != ERROR_OK) {
+ LOG_ERROR("no working area available, can't alloc space for stub jumper!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _on_error;
+ }
+ run->stub.tramp_addr = run->stub.tramp->address;
+ }
+ }
+
+ size_t al_tramp_size = ALIGN_UP(tramp_sz, 4);
+
+ if (run->image.reverse) {
+ target_addr_t reversed_tramp_addr = run->image.dram_org - code_size;
+ uint8_t reversed_tramp[al_tramp_size];
+
+ /* Send original size to allow padding */
+ reverse_binary(tramp, reversed_tramp, tramp_sz);
+ run->stub.tramp_addr = reversed_tramp_addr - al_tramp_size;
+ LOG_DEBUG("Write reversed tramp to addr " TARGET_ADDR_FMT ", sz %zu", run->stub.tramp_addr, al_tramp_size);
+ retval = target_write_buffer(target, run->stub.tramp_addr, al_tramp_size, reversed_tramp);
+ } else {
+ LOG_DEBUG("Write tramp to addr " TARGET_ADDR_FMT ", sz %zu", run->stub.tramp_addr, tramp_sz);
+ retval = target_write_buffer(target, run->stub.tramp_addr, tramp_sz, tramp);
+ }
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write stub jumper!");
+ goto _on_error;
+ }
+
+ run->stub.tramp_mapped_addr = run->image.iram_org + code_size;
+ code_size += al_tramp_size;
+ LOG_DEBUG("Tramp mapped to addr " TARGET_ADDR_FMT, run->stub.tramp_mapped_addr);
+ }
+
+ /* allocate dummy space until the data address */
+ if (alloc_code_working_area) {
+ /* we dont need to restore padding area. */
+ uint32_t backup_working_area_prev = target->backup_working_area;
+ target->backup_working_area = 0;
+ if (target_alloc_working_area(target, run->image.iram_len - code_size, &run->stub.padding) != ERROR_OK) {
+ LOG_ERROR("no working area available, can't alloc space for stub code!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _on_error;
+ }
+ target->backup_working_area = backup_working_area_prev;
+ }
+
+ /* Load the data section */
+ for (unsigned int i = 0; i < run->image.image.num_sections; i++) {
+ struct imagesection *section = &run->image.image.sections[i];
+
+ if (section->size == 0)
+ continue;
+
+ if (!(section->flags & ESP_IMAGE_ELF_PHF_EXEC)) {
+ LOG_DEBUG("addr " TARGET_ADDR_FMT ", sz %d, flags %" PRIx64, section->base_address, section->size,
+ section->flags);
+ /* target_alloc_working_area() aligns the whole working area size to 4-byte boundary.
+ We alloc one area for both DATA and BSS, so align each of them ourselves. */
+ uint32_t data_sec_sz = ALIGN_UP(section->size, 4);
+ LOG_DEBUG("DATA sec size %" PRIu32 " -> %" PRIu32, section->size, data_sec_sz);
+ uint32_t bss_sec_sz = ALIGN_UP(run->image.bss_size, 4);
+ LOG_DEBUG("BSS sec size %" PRIu32 " -> %" PRIu32, run->image.bss_size, bss_sec_sz);
+ if (target_alloc_working_area(target, data_sec_sz + bss_sec_sz, &run->stub.data) != ERROR_OK) {
+ LOG_ERROR("no working area available, can't alloc space for stub data!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _on_error;
+ }
+ if (section->base_address == 0) {
+ section->base_address = run->stub.data->address;
+ /* sanity check, stub is compiled to be run from working area */
+ } else if (run->stub.data->address != section->base_address) {
+ LOG_ERROR("working area " TARGET_ADDR_FMT
+ " and stub data section " TARGET_ADDR_FMT
+ " address mismatch!",
+ section->base_address,
+ run->stub.data->address);
+ retval = ERROR_FAIL;
+ goto _on_error;
+ }
+
+ retval = load_section_from_image(target, run, i, false);
+ if (retval != ERROR_OK)
+ goto _on_error;
+ }
+ }
+
+ /* stack */
+ if (run->stub.stack_addr == 0 && run->stack_size > 0) {
+ /* allocate stack in data working area */
+ if (target_alloc_working_area(target, run->stack_size, &run->stub.stack) != ERROR_OK) {
+ LOG_ERROR("no working area available, can't alloc stub stack!");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto _on_error;
+ }
+ run->stub.stack_addr = run->stub.stack->address + run->stack_size;
+ }
+
+ if (duration_measure(&algo_time) != 0) {
+ LOG_ERROR("Failed to stop algo run measurement!");
+ retval = ERROR_FAIL;
+ goto _on_error;
+ }
+ LOG_DEBUG("Stub loaded in %g ms", duration_elapsed(&algo_time) * 1000);
+ return ERROR_OK;
+
+_on_error:
+ esp_algorithm_unload_func_image(target, run);
+ return retval;
+}
+
+int esp_algorithm_unload_func_image(struct target *target, struct esp_algorithm_run_data *run)
+{
+ if (!run)
+ return ERROR_FAIL;
+
+ target_free_all_working_areas(target);
+
+ run->stub.tramp = NULL;
+ run->stub.stack = NULL;
+ run->stub.code = NULL;
+ run->stub.data = NULL;
+ run->stub.padding = NULL;
+
+ return ERROR_OK;
+}
+
+int esp_algorithm_exec_func_image_va(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap)
+{
+ if (!run || !run->image.image.start_address_set || run->image.image.start_address == 0)
+ return ERROR_FAIL;
+
+ return esp_algorithm_run_image(target, run, num_args, ap);
+}
+
+int esp_algorithm_load_onboard_func(struct target *target, target_addr_t func_addr, struct esp_algorithm_run_data *run)
+{
+ int res;
+ const uint8_t *tramp = NULL;
+ size_t tramp_sz = 0;
+ struct duration algo_time;
+
+ if (!run || !run->hw)
+ return ERROR_FAIL;
+
+ if (duration_start(&algo_time) != 0) {
+ LOG_ERROR("Failed to start algo time measurement!");
+ return ERROR_FAIL;
+ }
+
+ if (run->hw->stub_tramp_get) {
+ tramp = run->hw->stub_tramp_get(target, &tramp_sz);
+ if (!tramp)
+ return ERROR_FAIL;
+ }
+
+ if (tramp_sz > run->on_board.code_buf_size) {
+ LOG_ERROR("Stub tramp size %zu bytes exceeds target buf size %d bytes!",
+ tramp_sz, run->on_board.code_buf_size);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ if (run->stack_size > run->on_board.min_stack_size) {
+ LOG_ERROR("Algorithm stack size not fit into the allocated target stack!");
+ return ERROR_FAIL;
+ }
+
+ run->stub.stack_addr = run->on_board.min_stack_addr + run->stack_size;
+ run->stub.tramp_addr = run->on_board.code_buf_addr;
+ run->stub.tramp_mapped_addr = run->stub.tramp_addr;
+ run->stub.entry = func_addr;
+
+ if (tramp) {
+ res = target_write_buffer(target, run->stub.tramp_addr, tramp_sz, tramp);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to write stub jumper!");
+ esp_algorithm_unload_onboard_func(target, run);
+ return res;
+ }
+ }
+
+ if (duration_measure(&algo_time) != 0) {
+ LOG_ERROR("Failed to stop algo run measurement!");
+ return ERROR_FAIL;
+ }
+ LOG_DEBUG("Stub loaded in %g ms", duration_elapsed(&algo_time) * 1000);
+
+ return ERROR_OK;
+}
+
+int esp_algorithm_unload_onboard_func(struct target *target, struct esp_algorithm_run_data *run)
+{
+ return ERROR_OK;
+}
+
+int esp_algorithm_exec_onboard_func_va(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap)
+{
+ return esp_algorithm_run_debug_stub(target, run, num_args, ap);
+}
diff --git a/src/target/espressif/esp_algorithm.h b/src/target/espressif/esp_algorithm.h
new file mode 100644
index 000000000..11d275777
--- /dev/null
+++ b/src/target/espressif/esp_algorithm.h
@@ -0,0 +1,420 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Espressif chips common algorithm API for OpenOCD *
+ * Copyright (C) 2022 Espressif Systems Ltd. *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_ESP_ALGORITHM_H
+#define OPENOCD_TARGET_ESP_ALGORITHM_H
+
+#include "helper/log.h"
+#include "helper/binarybuffer.h"
+#include <helper/time_support.h>
+#include <target/algorithm.h>
+#include <target/image.h>
+
+/**
+ * API defined below allows executing pieces of code on target without breaking the execution of the running program.
+ * This functionality can be useful for various debugging and maintenance procedures.
+ * @note ESP flashing code to load flasher stub on target and write/read/erase flash.
+ * Also ESP GCOV command uses some of these functions to run onboard routines to dump coverage info.
+ * Stub entry function can take up to 5 arguments and should be of the following form:
+ *
+ * int stub_entry([uint32_t a1 [, uint32_t a2 [, uint32_t a3 [, uint32_t a4 [, uint32_t a5]]]]]);
+ *
+ * The general scheme of stub code execution is shown below.
+ *
+ * ------- ----------- (initial frame) ----
+ * | | -------(registers, stub entry, stub args)------> |trampoline | ---(stub args)---> | |
+ * | | | | | |
+ * |OpenOCD| <----------(stub-specific communications)---------------------------------------> |stub|
+ * | | | | | |
+ * | | <---------(target halted event, ret code)------- |tramp break| <---(ret code)---- | |
+ * ------- ----------- ----
+ *
+ * Procedure of executing stub on target includes:
+ * 1) User prepares struct esp_algorithm_run_data and calls one of algorithm_run_xxx() functions.
+ * 2) Routine allocates all necessary stub code and data sections.
+ * 3) If a user specifies an initializer func esp_algorithm_usr_func_init_t it is called just before the stub starts.
+ * 4) If user specifies stub communication func esp_algorithm_usr_func_t (@see esp_flash_write/read in ESP flash driver)
+ * it is called just after the stub starts. When communication with stub is finished this function must return.
+ * 5) OpenOCD waits for the stub to finish (hit exit breakpoint).
+ * 6) If the user specified arguments cleanup func esp_algorithm_usr_func_done_t,
+ * it is called just after the stub finishes.
+ *
+ * There are two options to run code on target under OpenOCD control:
+ * - Run externally compiled stub code.
+ * - Run onboard pre-compiled code. @note For ESP chips debug stubs must be enabled in target code @see ESP IDF docs.
+ * The main difference between the execution of external stub code and target built-in functions is that
+ * in the latter case working areas can not be used to allocate target memory for code and data because they can overlap
+ * with code and data involved in onboard function execution. For example, if memory allocated in the working area
+ * for the stub stack will overlap with some on-board data used by the stub the stack will get overwritten.
+ * The same stands for allocations in target code space.
+ *
+ * External Code Execution
+ * -----------------------
+ * To run external code on the target user should use esp_algorithm_run_func_image().
+ * In this case all necessary memory (code/data) is allocated in working areas that have fixed configuration
+ * defined in target TCL file. Stub code is actually a standalone program, so all its segments must have known
+ * addresses due to position-dependent code nature. So stub must be linked in such a way that its code segment
+ * starts at the beginning of the working area for code space defined in TCL. The same restriction must be applied
+ * to stub's data segment and base addresses of working area for data space. @see ESP stub flasher LD scripts.
+ * Also in order to simplify memory allocation BSS section must follow the DATA section in the stub image.
+ * The size of the BSS section must be specified in the bss_size field of struct algorithm_image.
+ * Sample stub memory map is shown below.
+ * ___________________________________________
+ * | data space working area start |
+ * | |
+ * | <stub .data segment> |
+ * |___________________________________________|
+ * | stub .bss start |
+ * | |
+ * | <stub .bss segment of size 'bss_size'> |
+ * |___________________________________________|
+ * | stub stack base |
+ * | |
+ * | <stub stack> |
+ * |___________________________________________|
+ * | |
+ * | <stub mem arg1> |
+ * |___________________________________________|
+ * | |
+ * | <stub mem arg2> |
+ * |___________________________________________|
+ * ___________________________________________
+ * | code space working area start |
+ * | |
+ * | <stub .text segment> |
+ * |___________________________________________|
+ * | |
+ * | <stub trampoline with exit breakpoint> |
+ * |___________________________________________|
+ *
+ * For example on how to execute external code with memory arguments @see esp_algo_flash_blank_check in
+ * ESP flash driver.
+ *
+ * On-Board Code Execution
+ * -----------------------
+ * To run on-board code on the target user should use esp_algorithm_run_onboard_func().
+ * On-board code execution process does not need to allocate target memory for stub code and data,
+ * Because the stub is pre-compiled to the code running on the target.
+ * But it still needs memory for stub trampoline, stack, and memory arguments.
+ * Working areas can not be used due to possible memory layout conflicts with on-board stub code and data.
+ * Debug stubs functionality provided by ESP IDF allows OpenOCD to overcome the above problem.
+ * It provides a special descriptor which provides info necessary to safely allocate memory on target.
+ * @see struct esp_dbg_stubs_desc.
+ * That info is also used to locate memory for stub trampoline code.
+ * User can execute target function at any address, but @see ESP IDF debug stubs also provide a way to pass to the host
+ * an entry address of pre-defined registered stub functions.
+ * For example of an on-board code execution @see esp32_cmd_gcov() in ESP32 apptrace module.
+*/
+
+/**
+ * Algorithm image data.
+ * Helper struct to work with algorithms consisting of code and data segments.
+ */
+struct esp_algorithm_image {
+ /** Image. */
+ struct image image;
+ /** BSS section size. */
+ uint32_t bss_size;
+ /** IRAM start address in the linker script */
+ uint32_t iram_org;
+ /** Total reserved IRAM size */
+ uint32_t iram_len;
+ /** DRAM start address in the linker script */
+ uint32_t dram_org;
+ /** Total reserved DRAM size */
+ uint32_t dram_len;
+ /** IRAM DRAM address range reversed or not */
+ bool reverse;
+};
+
+#define ESP_IMAGE_ELF_PHF_EXEC 0x1
+
+/**
+ * Algorithm stub data.
+ */
+struct esp_algorithm_stub {
+ /** Entry addr. */
+ target_addr_t entry;
+ /** Working area for code segment. */
+ struct working_area *code;
+ /** Working area for data segment. */
+ struct working_area *data;
+ /** Working area for trampoline. */
+ struct working_area *tramp;
+ /** Working area for padding between code and data area. */
+ struct working_area *padding;
+ /** Address of the target buffer for stub trampoline. If zero tramp->address will be used. */
+ target_addr_t tramp_addr;
+ /** Tramp code area will be filled from dbus.
+ * We need to map it to the ibus to be able to initialize PC register to start algorithm execution from.
+ */
+ target_addr_t tramp_mapped_addr;
+ /** Working area for stack. */
+ struct working_area *stack;
+ /** Address of the target buffer for stack. If zero tramp->address will be used. */
+ target_addr_t stack_addr;
+ /** Address of the log buffer */
+ target_addr_t log_buff_addr;
+ /** Size of the log buffer */
+ uint32_t log_buff_size;
+ /** Algorithm's arch-specific info. */
+ void *ainfo;
+};
+
+/**
+ * Algorithm stub in-memory arguments.
+ */
+struct esp_algorithm_mem_args {
+ /** Memory params. */
+ struct mem_param *params;
+ /** Number of memory params. */
+ uint32_t count;
+};
+
+/**
+ * Algorithm stub register arguments.
+ */
+struct esp_algorithm_reg_args {
+ /** Algorithm register params. User args start from user_first_reg_param */
+ struct reg_param *params;
+ /** Number of register params. */
+ uint32_t count;
+ /** The first several reg_params can be used by stub itself (e.g. for trampoline).
+ * This is the index of the first reg_param available for user to pass args to algorithm stub. */
+ uint32_t first_user_param;
+};
+
+struct esp_algorithm_run_data;
+
+/**
+ * @brief Algorithm run function.
+ *
+ * @param target Pointer to target.
+ * @param run Pointer to algo run data.
+ * @param arg Function specific argument.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX.
+ */
+typedef int (*esp_algorithm_func_t)(struct target *target, struct esp_algorithm_run_data *run, void *arg);
+
+/**
+ * @brief Host part of algorithm.
+ * This function will be called while stub is running on target.
+ * It can be used for communication with stub.
+ *
+ * @param target Pointer to target.
+ * @param usr_arg Function specific argument.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX.
+ */
+typedef int (*esp_algorithm_usr_func_t)(struct target *target, void *usr_arg);
+
+/**
+ * @brief Algorithm's arguments setup function.
+ * This function will be called just before stub start.
+ * It must return when all operations with running stub are completed.
+ * It can be used to prepare stub memory parameters.
+ *
+ * @param target Pointer to target.
+ * @param run Pointer to algo run data.
+ * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX.
+ */
+typedef int (*esp_algorithm_usr_func_init_t)(struct target *target,
+ struct esp_algorithm_run_data *run,
+ void *usr_arg);
+
+/**
+ * @brief Algorithm's arguments cleanup function.
+ * This function will be called just after stub exit.
+ * It can be used to cleanup stub memory parameters.
+ *
+ * @param target Pointer to target.
+ * @param run Pointer to algo run data.
+ * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX.
+ */
+typedef void (*esp_algorithm_usr_func_done_t)(struct target *target,
+ struct esp_algorithm_run_data *run,
+ void *usr_arg);
+
+struct esp_algorithm_hw {
+ int (*algo_init)(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, va_list ap);
+ int (*algo_cleanup)(struct target *target, struct esp_algorithm_run_data *run);
+ const uint8_t *(*stub_tramp_get)(struct target *target, size_t *size);
+};
+
+/**
+ * Algorithm run data.
+ */
+struct esp_algorithm_run_data {
+ /** Algorithm completion timeout in ms. If 0, default value will be used */
+ uint32_t timeout_ms;
+ /** Algorithm stack size. */
+ uint32_t stack_size;
+ /** Algorithm register arguments. */
+ struct esp_algorithm_reg_args reg_args;
+ /** Algorithm memory arguments. */
+ struct esp_algorithm_mem_args mem_args;
+ /** Algorithm arch-specific info. For Xtensa this should point to struct xtensa_algorithm. */
+ void *arch_info;
+ /** Algorithm return code. */
+ int32_t ret_code;
+ /** Stub. */
+ struct esp_algorithm_stub stub;
+ union {
+ struct {
+ /** Size of the pre-alocated on-board buffer for stub's code. */
+ uint32_t code_buf_size;
+ /** Address of pre-compiled target buffer for stub trampoline. */
+ target_addr_t code_buf_addr;
+ /** Size of the pre-alocated on-board buffer for stub's stack. */
+ uint32_t min_stack_size;
+ /** Pre-compiled target buffer's addr for stack. */
+ target_addr_t min_stack_addr;
+ } on_board;
+ struct esp_algorithm_image image;
+ };
+ /** Host side algorithm function argument. */
+ void *usr_func_arg;
+ /** Host side algorithm function. */
+ esp_algorithm_usr_func_t usr_func;
+ /** Host side algorithm function setup routine. */
+ esp_algorithm_usr_func_init_t usr_func_init;
+ /** Host side algorithm function cleanup routine. */
+ esp_algorithm_usr_func_done_t usr_func_done;
+ /** Algorithm run function: see algorithm_run_xxx for example. */
+ esp_algorithm_func_t algo_func;
+ /** HW specific API */
+ const struct esp_algorithm_hw *hw;
+};
+
+int esp_algorithm_load_func_image(struct target *target, struct esp_algorithm_run_data *run);
+int esp_algorithm_unload_func_image(struct target *target, struct esp_algorithm_run_data *run);
+
+int esp_algorithm_exec_func_image_va(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap);
+
+/**
+ * @brief Loads and runs stub from specified image.
+ * This function should be used to run external stub code on target.
+ *
+ * @param target Pointer to target.
+ * @param run Pointer to algo run data.
+ * @param num_args Number of stub arguments that follow.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX. Stub return code is in run->ret_code.
+ */
+static inline int esp_algorithm_run_func_image_va(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap)
+{
+ int ret = esp_algorithm_load_func_image(target, run);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = esp_algorithm_exec_func_image_va(target, run, num_args, ap);
+ int rc = esp_algorithm_unload_func_image(target, run);
+ return ret != ERROR_OK ? ret : rc;
+}
+
+static inline int esp_algorithm_run_func_image(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ ...)
+{
+ va_list ap;
+ va_start(ap, num_args);
+ int retval = esp_algorithm_run_func_image_va(target, run, num_args, ap);
+ va_end(ap);
+ return retval;
+}
+
+int esp_algorithm_load_onboard_func(struct target *target,
+ target_addr_t func_addr,
+ struct esp_algorithm_run_data *run);
+int esp_algorithm_unload_onboard_func(struct target *target, struct esp_algorithm_run_data *run);
+int esp_algorithm_exec_onboard_func_va(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t num_args,
+ va_list ap);
+
+/**
+ * @brief Runs pre-compiled on-board function.
+ * This function should be used to run on-board stub code.
+ *
+ * @param target Pointer to target.
+ * @param run Pointer to algo run data.
+ * @param func_entry Address of the function to run.
+ * @param num_args Number of function arguments that follow.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX. Stub return code is in run->ret_code.
+ */
+static inline int esp_algorithm_run_onboard_func_va(struct target *target,
+ struct esp_algorithm_run_data *run,
+ target_addr_t func_addr,
+ uint32_t num_args,
+ va_list ap)
+{
+ int ret = esp_algorithm_load_onboard_func(target, func_addr, run);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = esp_algorithm_exec_onboard_func_va(target, run, num_args, ap);
+ if (ret != ERROR_OK)
+ return ret;
+ return esp_algorithm_unload_onboard_func(target, run);
+}
+
+static inline int esp_algorithm_run_onboard_func(struct target *target,
+ struct esp_algorithm_run_data *run,
+ target_addr_t func_addr,
+ uint32_t num_args,
+ ...)
+{
+ va_list ap;
+ va_start(ap, num_args);
+ int retval = esp_algorithm_run_onboard_func_va(target, run, func_addr, num_args, ap);
+ va_end(ap);
+ return retval;
+}
+
+/**
+ * @brief Set the value of an argument passed via registers to the stub main function.
+ */
+static inline void esp_algorithm_user_arg_set_uint(struct esp_algorithm_run_data *run,
+ int arg_num,
+ uint64_t val)
+{
+ struct reg_param *param = &run->reg_args.params[run->reg_args.first_user_param + arg_num];
+
+ assert(param->size <= 64);
+
+ if (param->size <= 32)
+ buf_set_u32(param->value, 0, param->size, val);
+ else
+ buf_set_u64(param->value, 0, param->size, val);
+}
+
+/**
+ * @brief Get the value of an argument passed via registers from the stub main function.
+ */
+static inline uint64_t esp_algorithm_user_arg_get_uint(struct esp_algorithm_run_data *run, int arg_num)
+{
+ struct reg_param *param = &run->reg_args.params[run->reg_args.first_user_param + arg_num];
+
+ assert(param->size <= 64);
+
+ if (param->size <= 32)
+ return buf_get_u32(param->value, 0, param->size);
+ return buf_get_u64(param->value, 0, param->size);
+}
+
+#endif /* OPENOCD_TARGET_ESP_ALGORITHM_H */
diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c
index bc4d8a21a..f883b1ce7 100644
--- a/src/target/espressif/esp_xtensa_smp.c
+++ b/src/target/espressif/esp_xtensa_smp.c
@@ -16,6 +16,7 @@
#include <target/semihosting_common.h>
#include "esp_xtensa_smp.h"
#include "esp_xtensa_semihosting.h"
+#include "esp_algorithm.h"
/*
Multiprocessor stuff common:
@@ -495,6 +496,83 @@ int esp_xtensa_smp_watchpoint_remove(struct target *target, struct watchpoint *w
return ERROR_OK;
}
+int esp_xtensa_smp_run_func_image(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, ...)
+{
+ struct target *run_target = target;
+ struct target_list *head;
+ va_list ap;
+ uint32_t smp_break = 0;
+ int res;
+
+ if (target->smp) {
+ /* find first HALTED and examined core */
+ foreach_smp_target(head, target->smp_targets) {
+ run_target = head->target;
+ if (target_was_examined(run_target) && run_target->state == TARGET_HALTED)
+ break;
+ }
+ if (!head) {
+ LOG_ERROR("Failed to find HALTED core!");
+ return ERROR_FAIL;
+ }
+
+ res = esp_xtensa_smp_smpbreak_disable(run_target, &smp_break);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ va_start(ap, num_args);
+ int algo_res = esp_algorithm_run_func_image_va(run_target, run, num_args, ap);
+ va_end(ap);
+
+ if (target->smp) {
+ res = esp_xtensa_smp_smpbreak_restore(run_target, smp_break);
+ if (res != ERROR_OK)
+ return res;
+ }
+ return algo_res;
+}
+
+int esp_xtensa_smp_run_onboard_func(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t func_addr,
+ uint32_t num_args,
+ ...)
+{
+ struct target *run_target = target;
+ struct target_list *head;
+ va_list ap;
+ uint32_t smp_break = 0;
+ int res;
+
+ if (target->smp) {
+ /* find first HALTED and examined core */
+ foreach_smp_target(head, target->smp_targets) {
+ run_target = head->target;
+ if (target_was_examined(run_target) && run_target->state == TARGET_HALTED)
+ break;
+ }
+ if (!head) {
+ LOG_ERROR("Failed to find HALTED core!");
+ return ERROR_FAIL;
+ }
+ res = esp_xtensa_smp_smpbreak_disable(run_target, &smp_break);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ va_start(ap, num_args);
+ int algo_res = esp_algorithm_run_onboard_func_va(run_target, run, func_addr, num_args, ap);
+ va_end(ap);
+
+ if (target->smp) {
+ res = esp_xtensa_smp_smpbreak_restore(run_target, smp_break);
+ if (res != ERROR_OK)
+ return res;
+ }
+ return algo_res;
+}
+
int esp_xtensa_smp_init_arch_info(struct target *target,
struct esp_xtensa_smp_common *esp_xtensa_smp,
struct xtensa_debug_module_config *dm_cfg,
diff --git a/src/target/espressif/esp_xtensa_smp.h b/src/target/espressif/esp_xtensa_smp.h
index 4e4f3b332..39afd8af1 100644
--- a/src/target/espressif/esp_xtensa_smp.h
+++ b/src/target/espressif/esp_xtensa_smp.h
@@ -9,6 +9,7 @@
#define OPENOCD_TARGET_XTENSA_ESP_SMP_H
#include "esp_xtensa.h"
+#include "esp_algorithm.h"
struct esp_xtensa_smp_chip_ops {
int (*poll)(struct target *target);
@@ -47,7 +48,12 @@ int esp_xtensa_smp_init_arch_info(struct target *target,
struct xtensa_debug_module_config *dm_cfg,
const struct esp_xtensa_smp_chip_ops *chip_ops,
const struct esp_semihost_ops *semihost_ops);
-
+int esp_xtensa_smp_run_func_image(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, ...);
+int esp_xtensa_smp_run_onboard_func(struct target *target,
+ struct esp_algorithm_run_data *run,
+ uint32_t func_addr,
+ uint32_t num_args,
+ ...);
extern const struct command_registration esp_xtensa_smp_command_handlers[];
extern const struct command_registration esp_xtensa_smp_xtensa_command_handlers[];
extern const struct command_registration esp_xtensa_smp_esp_command_handlers[];
-----------------------------------------------------------------------
Summary of changes:
src/target/espressif/Makefile.am | 4 +-
src/target/espressif/esp_algorithm.c | 595 ++++++++++++++++++++++++++++++++++
src/target/espressif/esp_algorithm.h | 420 ++++++++++++++++++++++++
src/target/espressif/esp_xtensa_smp.c | 78 +++++
src/target/espressif/esp_xtensa_smp.h | 8 +-
5 files changed, 1103 insertions(+), 2 deletions(-)
create mode 100644 src/target/espressif/esp_algorithm.c
create mode 100644 src/target/espressif/esp_algorithm.h
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-06 14:01:28
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via ba16fdc1c645bda82adb5a06b4403e7501e150c4 (commit)
from 66391d28373fef090999b253b193d19dbdc11217 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ba16fdc1c645bda82adb5a06b4403e7501e150c4
Author: Tomas Vanek <va...@fb...>
Date: Tue Nov 7 14:45:45 2023 +0100
drivers/cmsis_dap: use quirk workarounds optionally
Introduce 'cmsis-dap quirk' command to enable and
disable quirk mode.
If enabled, disconnect and connect before a switch
sequence and do not use multiple packets pipelining.
Change-Id: I6576f7de9f6c98a25c3cf9eec9a456a23610d00d
Signed-off-by: Tomas Vanek <va...@fb...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7966
Tested-by: jenkins
diff --git a/doc/openocd.texi b/doc/openocd.texi
index de990c538..db7315fe4 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -2569,6 +2569,18 @@ In most cases need not to be specified and interfaces are searched by
interface string or for user class interface.
@end deffn
+@deffn {Command} {cmsis-dap quirk} [@option{enable}|@option{disable}]
+Enables or disables the following workarounds of known CMSIS-DAP adapter
+quirks:
+@itemize @minus
+@item disconnect and re-connect before sending a switch sequence
+@item packets pipelining is suppressed, only one packet at a time is
+submitted to the adapter
+@end itemize
+The quirk workarounds are disabled by default.
+The command without a parameter displays current setting.
+@end deffn
+
@deffn {Command} {cmsis-dap info}
Display various device information, like hardware version, firmware version, current bus status.
@end deffn
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index 5d060bdad..caacc9b91 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -861,9 +861,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
goto skip;
}
- dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % dap->packet_count;
+ unsigned int packet_count = dap->quirk_mode ? 1 : dap->packet_count;
+ dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % packet_count;
dap->pending_fifo_block_count++;
- if (dap->pending_fifo_block_count > dap->packet_count)
+ if (dap->pending_fifo_block_count > packet_count)
LOG_ERROR("internal: too much pending writes %u", dap->pending_fifo_block_count);
return;
@@ -984,7 +985,8 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo
skip:
block->transfer_count = 0;
- dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count;
+ if (!dap->quirk_mode && dap->packet_count > 1)
+ dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count;
dap->pending_fifo_block_count--;
}
@@ -1079,7 +1081,8 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
/* Not enough room in the queue. Run the queue. */
cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
- if (cmsis_dap_handle->pending_fifo_block_count >= cmsis_dap_handle->packet_count)
+ unsigned int packet_count = cmsis_dap_handle->quirk_mode ? 1 : cmsis_dap_handle->packet_count;
+ if (cmsis_dap_handle->pending_fifo_block_count >= packet_count)
cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING);
}
@@ -1222,7 +1225,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
if (swd_mode)
queued_retval = cmsis_dap_swd_run_queue();
- if (seq != LINE_RESET &&
+ if (cmsis_dap_handle->quirk_mode && seq != LINE_RESET &&
(output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST))
== (SWJ_PIN_SRST | SWJ_PIN_TRST)) {
/* Following workaround deasserts reset on most adapters.
@@ -2220,6 +2223,19 @@ COMMAND_HANDLER(cmsis_dap_handle_backend_command)
return ERROR_OK;
}
+COMMAND_HANDLER(cmsis_dap_handle_quirk_command)
+{
+ if (CMD_ARGC > 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (CMD_ARGC == 1)
+ COMMAND_PARSE_ENABLE(CMD_ARGV[0], cmsis_dap_handle->quirk_mode);
+
+ command_print(CMD, "CMSIS-DAP quirk workarounds %s",
+ cmsis_dap_handle->quirk_mode ? "enabled" : "disabled");
+ return ERROR_OK;
+}
+
static const struct command_registration cmsis_dap_subcommand_handlers[] = {
{
.name = "info",
@@ -2249,6 +2265,13 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = {
.help = "set the communication backend to use (USB bulk or HID).",
.usage = "(auto | usb_bulk | hid)",
},
+ {
+ .name = "quirk",
+ .handler = &cmsis_dap_handle_quirk_command,
+ .mode = COMMAND_ANY,
+ .help = "allow expensive workarounds of known adapter quirks.",
+ .usage = "[enable | disable]",
+ },
#if BUILD_CMSIS_DAP_USB
{
.name = "usb",
diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
index 817636f34..e47697d1f 100644
--- a/src/jtag/drivers/cmsis_dap.h
+++ b/src/jtag/drivers/cmsis_dap.h
@@ -52,6 +52,7 @@ struct cmsis_dap {
unsigned int pending_fifo_block_count;
uint16_t caps;
+ bool quirk_mode; /* enable expensive workarounds */
uint32_t swo_buf_sz;
bool trace_enabled;
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 12 ++++++++++++
src/jtag/drivers/cmsis_dap.c | 33 ++++++++++++++++++++++++++++-----
src/jtag/drivers/cmsis_dap.h | 1 +
3 files changed, 41 insertions(+), 5 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-06 14:01:06
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 66391d28373fef090999b253b193d19dbdc11217 (commit)
from fd75e9e542700e40f11d79532d19e311cf437de1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 66391d28373fef090999b253b193d19dbdc11217
Author: Tomas Vanek <va...@fb...>
Date: Sun Nov 20 21:01:17 2022 +0100
jtag/drivers/cmsis_dap: implement canceling of pending USB requests
Use it whenever an out-of-sync response is detected to clean
USB bulk transfer state.
USB hidapi does not offer any means to cancel a pending request,
therefore cmsis_dap_hid_cancel_all() does nothing.
Signed-off-by: Tomas Vanek <va...@fb...>
Change-Id: Ie36fa760c1643ae10be0e87fc633068965a72242
Reviewed-on: https://review.openocd.org/c/openocd/+/7366
Tested-by: jenkins
Reviewed-by: zapb <de...@za...>
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index bc86eb46a..5d060bdad 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -365,6 +365,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
LOG_ERROR("CMSIS-DAP command mismatch. Sent 0x%" PRIx8
" received 0x%" PRIx8, current_cmd, resp[0]);
+ dap->backend->cancel_all(dap);
cmsis_dap_flush_read(dap);
return ERROR_FAIL;
}
@@ -758,7 +759,6 @@ static int cmsis_dap_cmd_dap_swo_data(
return ERROR_OK;
}
-
static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap)
{
for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++)
@@ -769,6 +769,13 @@ static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap)
dap->pending_fifo_block_count = 0;
}
+static void cmsis_dap_swd_cancel_transfers(struct cmsis_dap *dap)
+{
+ dap->backend->cancel_all(dap);
+ cmsis_dap_flush_read(dap);
+ cmsis_dap_swd_discard_all_pending(dap);
+}
+
static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
{
uint8_t *command = dap->command;
@@ -913,8 +920,9 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo
if (resp[0] != block->command) {
LOG_ERROR("CMSIS-DAP command mismatch. Expected 0x%x received 0x%" PRIx8,
block->command, resp[0]);
+ cmsis_dap_swd_cancel_transfers(dap);
queued_retval = ERROR_FAIL;
- goto skip;
+ return;
}
unsigned int transfer_count;
@@ -940,9 +948,13 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo
goto skip;
}
- if (block->transfer_count != transfer_count)
+ if (block->transfer_count != transfer_count) {
LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d",
block->transfer_count, transfer_count);
+ cmsis_dap_swd_cancel_transfers(dap);
+ queued_retval = ERROR_FAIL;
+ return;
+ }
LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u, %s mode",
transfer_count, dap->pending_fifo_get_idx,
diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
index 187aeb54d..817636f34 100644
--- a/src/jtag/drivers/cmsis_dap.h
+++ b/src/jtag/drivers/cmsis_dap.h
@@ -66,6 +66,7 @@ struct cmsis_dap_backend {
int (*write)(struct cmsis_dap *dap, int len, int timeout_ms);
int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz);
void (*packet_buffer_free)(struct cmsis_dap *dap);
+ void (*cancel_all)(struct cmsis_dap *dap);
};
extern const struct cmsis_dap_backend cmsis_dap_hid_backend;
diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c
index aaab5804d..17e490f05 100644
--- a/src/jtag/drivers/cmsis_dap_usb_bulk.c
+++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c
@@ -634,6 +634,19 @@ static void cmsis_dap_usb_free(struct cmsis_dap *dap)
dap->response = NULL;
}
+static void cmsis_dap_usb_cancel_all(struct cmsis_dap *dap)
+{
+ for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+ if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING)
+ libusb_cancel_transfer(dap->bdata->command_transfers[i].transfer);
+ if (dap->bdata->response_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING)
+ libusb_cancel_transfer(dap->bdata->response_transfers[i].transfer);
+
+ dap->bdata->command_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE;
+ dap->bdata->response_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE;
+ }
+}
+
COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
{
if (CMD_ARGC == 1)
@@ -663,4 +676,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = {
.write = cmsis_dap_usb_write,
.packet_buffer_alloc = cmsis_dap_usb_alloc,
.packet_buffer_free = cmsis_dap_usb_free,
+ .cancel_all = cmsis_dap_usb_cancel_all,
};
diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c
index 6338886c8..1decc7156 100644
--- a/src/jtag/drivers/cmsis_dap_usb_hid.c
+++ b/src/jtag/drivers/cmsis_dap_usb_hid.c
@@ -236,6 +236,10 @@ static void cmsis_dap_hid_free(struct cmsis_dap *dap)
dap->packet_buffer = NULL;
}
+static void cmsis_dap_hid_cancel_all(struct cmsis_dap *dap)
+{
+}
+
const struct cmsis_dap_backend cmsis_dap_hid_backend = {
.name = "hid",
.open = cmsis_dap_hid_open,
@@ -244,4 +248,5 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = {
.write = cmsis_dap_hid_write,
.packet_buffer_alloc = cmsis_dap_hid_alloc,
.packet_buffer_free = cmsis_dap_hid_free,
+ .cancel_all = cmsis_dap_hid_cancel_all,
};
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/cmsis_dap.c | 18 +++++++++++++++---
src/jtag/drivers/cmsis_dap.h | 1 +
src/jtag/drivers/cmsis_dap_usb_bulk.c | 14 ++++++++++++++
src/jtag/drivers/cmsis_dap_usb_hid.c | 5 +++++
4 files changed, 35 insertions(+), 3 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-06 14:00:45
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via fd75e9e542700e40f11d79532d19e311cf437de1 (commit)
from 0f70c6c325785517f35bbbb9316801bef7a79d8b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit fd75e9e542700e40f11d79532d19e311cf437de1
Author: Tomas Vanek <va...@fb...>
Date: Sat Nov 19 07:26:37 2022 +0100
jtag/drivers/cmsis_dap_bulk: use asynchronous libusb transfer
The synchronous libusb_bulk_transfer() always waits
for the transfer to complete. Therefore it does not allow issuing
multiple USB requests as used on HID backend.
Switch to asynchrounous libusb_submit_transfer().
With this patch a good USB FS based CMSIS-DAPv2 adapter
almost doubles the throughput:
adapter speed: 20000 kHz
poll off
> load_image /run/user/1000/ram256k.bin 0x20000000
262144 bytes written at address 0x20000000
downloaded 262144 bytes in 0.428576s (597.327 KiB/s)
> dump_image /dev/null 0x20000000 0x40000
dumped 262144 bytes in 0.572875s (446.869 KiB/s)
Signed-off-by: Tomas Vanek <va...@fb...>
Change-Id: Ic6168ea4eca4f6bd1d8ad541a07a8d70427cc509
Reviewed-on: https://review.openocd.org/c/openocd/+/7365
Reviewed-by: zapb <de...@za...>
Tested-by: jenkins
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index 03832431d..bc86eb46a 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -225,6 +225,12 @@ struct pending_scan_result {
unsigned int buffer_offset;
};
+/* Read mode */
+enum cmsis_dap_blocking {
+ CMSIS_DAP_NON_BLOCKING,
+ CMSIS_DAP_BLOCKING
+};
+
/* Each block in FIFO can contain up to pending_queue_len transfers */
static unsigned int pending_queue_len;
static unsigned int tfer_max_command_size;
@@ -315,7 +321,7 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap)
* USB close/open so we need to flush up to 64 old packets
* to be sure all buffers are empty */
for (i = 0; i < 64; i++) {
- int retval = dap->backend->read(dap, 10);
+ int retval = dap->backend->read(dap, 10, NULL);
if (retval == ERROR_TIMEOUT_REACHED)
break;
}
@@ -326,10 +332,13 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap)
/* Send a message and receive the reply */
static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
{
+ if (dap->write_count + dap->read_count) {
+ LOG_ERROR("internal: queue not empty before xfer");
+ }
if (dap->pending_fifo_block_count) {
LOG_ERROR("pending %u blocks, flushing", dap->pending_fifo_block_count);
while (dap->pending_fifo_block_count) {
- dap->backend->read(dap, 10);
+ dap->backend->read(dap, 10, NULL);
dap->pending_fifo_block_count--;
}
dap->pending_fifo_put_idx = 0;
@@ -342,7 +351,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
return retval;
/* get reply */
- retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS);
+ retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, NULL);
if (retval < 0)
return retval;
@@ -750,6 +759,16 @@ static int cmsis_dap_cmd_dap_swo_data(
}
+static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap)
+{
+ for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++)
+ dap->pending_fifo[i].transfer_count = 0;
+
+ dap->pending_fifo_put_idx = 0;
+ dap->pending_fifo_get_idx = 0;
+ dap->pending_fifo_block_count = 0;
+}
+
static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
{
uint8_t *command = dap->command;
@@ -770,8 +789,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
goto skip;
}
- if (block->transfer_count == 0)
+ if (block->transfer_count == 0) {
+ LOG_ERROR("internal: write an empty queue?!");
goto skip;
+ }
bool block_cmd = !cmsis_dap_handle->swd_cmds_differ
&& block->transfer_count >= CMD_DAP_TFER_BLOCK_MIN_OPS;
@@ -831,14 +852,12 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
if (retval < 0) {
queued_retval = retval;
goto skip;
- } else {
- queued_retval = ERROR_OK;
}
dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % dap->packet_count;
dap->pending_fifo_block_count++;
if (dap->pending_fifo_block_count > dap->packet_count)
- LOG_ERROR("too much pending writes %u", dap->pending_fifo_block_count);
+ LOG_ERROR("internal: too much pending writes %u", dap->pending_fifo_block_count);
return;
@@ -846,21 +865,47 @@ skip:
block->transfer_count = 0;
}
-static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blocking blocking)
{
+ int retval;
struct pending_request_block *block = &dap->pending_fifo[dap->pending_fifo_get_idx];
- if (dap->pending_fifo_block_count == 0)
- LOG_ERROR("no pending write");
+ if (dap->pending_fifo_block_count == 0) {
+ LOG_ERROR("internal: no pending write when reading?!");
+ return;
+ }
+
+ if (queued_retval != ERROR_OK) {
+ /* keep reading blocks until the pipeline is empty */
+ retval = dap->backend->read(dap, 10, NULL);
+ if (retval == ERROR_TIMEOUT_REACHED || retval == 0) {
+ /* timeout means that we flushed the pipeline,
+ * we can safely discard remaining pending requests */
+ cmsis_dap_swd_discard_all_pending(dap);
+ return;
+ }
+ goto skip;
+ }
/* get reply */
- int retval = dap->backend->read(dap, timeout_ms);
- if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < LIBUSB_TIMEOUT_MS)
+ struct timeval tv = {
+ .tv_sec = 0,
+ .tv_usec = 0
+ };
+ retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking ? NULL : &tv);
+ bool timeout = (retval == ERROR_TIMEOUT_REACHED || retval == 0);
+ if (timeout && blocking == CMSIS_DAP_NON_BLOCKING)
return;
if (retval <= 0) {
- LOG_DEBUG("error reading data");
+ LOG_DEBUG("error reading adapter response");
queued_retval = ERROR_FAIL;
+ if (timeout) {
+ /* timeout means that we flushed the pipeline,
+ * we can safely discard remaining pending requests */
+ cmsis_dap_swd_discard_all_pending(dap);
+ return;
+ }
goto skip;
}
@@ -899,8 +944,9 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d",
block->transfer_count, transfer_count);
- LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u timeout %i",
- transfer_count, dap->pending_fifo_get_idx, timeout_ms);
+ LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u, %s mode",
+ transfer_count, dap->pending_fifo_get_idx,
+ blocking ? "blocking" : "nonblocking");
for (unsigned int i = 0; i < transfer_count; i++) {
struct pending_transfer_result *transfer = &(block->transfers[i]);
@@ -932,13 +978,15 @@ skip:
static int cmsis_dap_swd_run_queue(void)
{
- if (cmsis_dap_handle->pending_fifo_block_count)
- cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+ if (cmsis_dap_handle->write_count + cmsis_dap_handle->read_count) {
+ if (cmsis_dap_handle->pending_fifo_block_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_NON_BLOCKING);
- cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
+ cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
+ }
while (cmsis_dap_handle->pending_fifo_block_count)
- cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
+ cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING);
cmsis_dap_handle->pending_fifo_put_idx = 0;
cmsis_dap_handle->pending_fifo_get_idx = 0;
@@ -979,10 +1027,16 @@ static unsigned int cmsis_dap_tfer_resp_size(unsigned int write_count,
static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
{
+ /* TARGETSEL register write cannot be queued */
+ if (swd_cmd(false, false, DP_TARGETSEL) == cmd) {
+ queued_retval = cmsis_dap_swd_run_queue();
+
+ cmsis_dap_metacmd_targetsel(data);
+ return;
+ }
+
/* Compute sizes of the DAP Transfer command and the expected response
* for all queued and this operation */
- bool targetsel_cmd = swd_cmd(false, false, DP_TARGETSEL) == cmd;
-
unsigned int write_count = cmsis_dap_handle->write_count;
unsigned int read_count = cmsis_dap_handle->read_count;
bool block_cmd;
@@ -1003,20 +1057,18 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
block_cmd);
unsigned int max_transfer_count = block_cmd ? 65535 : 255;
- /* Does the DAP Transfer command and the expected response fit into one packet?
- * Run the queue also before a targetsel - it cannot be queued */
+ /* Does the DAP Transfer command and also its expected response fit into one packet? */
if (cmd_size > tfer_max_command_size
|| resp_size > tfer_max_response_size
- || targetsel_cmd
|| write_count + read_count > max_transfer_count) {
if (cmsis_dap_handle->pending_fifo_block_count)
- cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+ cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_NON_BLOCKING);
/* Not enough room in the queue. Run the queue. */
cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
if (cmsis_dap_handle->pending_fifo_block_count >= cmsis_dap_handle->packet_count)
- cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
+ cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING);
}
assert(cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx].transfer_count < pending_queue_len);
@@ -1024,11 +1076,6 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
if (queued_retval != ERROR_OK)
return;
- if (targetsel_cmd) {
- cmsis_dap_metacmd_targetsel(data);
- return;
- }
-
struct pending_request_block *block = &cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx];
struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]);
transfer->data = data;
@@ -1160,6 +1207,9 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
unsigned int s_len;
int retval;
+ if (swd_mode)
+ queued_retval = cmsis_dap_swd_run_queue();
+
if (seq != LINE_RESET &&
(output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST))
== (SWJ_PIN_SRST | SWJ_PIN_TRST)) {
@@ -1296,7 +1346,7 @@ static int cmsis_dap_init(void)
if (data[0] == 2) { /* short */
uint16_t pkt_sz = data[1] + (data[2] << 8);
if (pkt_sz != cmsis_dap_handle->packet_size) {
- free(cmsis_dap_handle->packet_buffer);
+ cmsis_dap_handle->backend->packet_buffer_free(cmsis_dap_handle);
retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz);
if (retval != ERROR_OK)
goto init_err;
diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
index a8554de80..187aeb54d 100644
--- a/src/jtag/drivers/cmsis_dap.h
+++ b/src/jtag/drivers/cmsis_dap.h
@@ -61,9 +61,11 @@ struct cmsis_dap_backend {
const char *name;
int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial);
void (*close)(struct cmsis_dap *dap);
- int (*read)(struct cmsis_dap *dap, int timeout_ms);
+ int (*read)(struct cmsis_dap *dap, int transfer_timeout_ms,
+ struct timeval *wait_timeout);
int (*write)(struct cmsis_dap *dap, int len, int timeout_ms);
int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz);
+ void (*packet_buffer_free)(struct cmsis_dap *dap);
};
extern const struct cmsis_dap_backend cmsis_dap_hid_backend;
diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c
index 6599c414c..aaab5804d 100644
--- a/src/jtag/drivers/cmsis_dap_usb_bulk.c
+++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c
@@ -28,8 +28,29 @@
#include <libusb.h>
#include <helper/log.h>
#include <helper/replacements.h>
+#include <jtag/jtag.h> /* ERROR_JTAG_DEVICE_ERROR only */
#include "cmsis_dap.h"
+#include "libusb_helper.h"
+
+#if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000105) \
+ || defined(_WIN32) || defined(__CYGWIN__)
+ #define libusb_dev_mem_alloc(dev, sz) malloc(sz)
+ #define libusb_dev_mem_free(dev, buffer, sz) free(buffer)
+#endif
+
+enum {
+ CMSIS_DAP_TRANSFER_PENDING = 0, /* must be 0, used in libusb_handle_events_completed */
+ CMSIS_DAP_TRANSFER_IDLE,
+ CMSIS_DAP_TRANSFER_COMPLETED
+};
+
+struct cmsis_dap_bulk_transfer {
+ struct libusb_transfer *transfer;
+ uint8_t *buffer;
+ int status; /* either CMSIS_DAP_TRANSFER_ enum or error code */
+ int transferred;
+};
struct cmsis_dap_backend_data {
struct libusb_context *usb_ctx;
@@ -37,12 +58,16 @@ struct cmsis_dap_backend_data {
unsigned int ep_out;
unsigned int ep_in;
int interface;
+
+ struct cmsis_dap_bulk_transfer command_transfers[MAX_PENDING_REQUESTS];
+ struct cmsis_dap_bulk_transfer response_transfers[MAX_PENDING_REQUESTS];
};
static int cmsis_dap_usb_interface = -1;
static void cmsis_dap_usb_close(struct cmsis_dap *dap);
static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
+static void cmsis_dap_usb_free(struct cmsis_dap *dap);
static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
{
@@ -358,6 +383,24 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
dap->bdata->ep_in = ep_in;
dap->bdata->interface = interface_num;
+ for (unsigned int idx = 0; idx < MAX_PENDING_REQUESTS; idx++) {
+ dap->bdata->command_transfers[idx].status = CMSIS_DAP_TRANSFER_IDLE;
+ dap->bdata->command_transfers[idx].transfer = libusb_alloc_transfer(0);
+ if (!dap->bdata->command_transfers[idx].transfer) {
+ LOG_ERROR("unable to allocate USB transfer");
+ cmsis_dap_usb_close(dap);
+ return ERROR_FAIL;
+ }
+
+ dap->bdata->response_transfers[idx].status = CMSIS_DAP_TRANSFER_IDLE;
+ dap->bdata->response_transfers[idx].transfer = libusb_alloc_transfer(0);
+ if (!dap->bdata->response_transfers[idx].transfer) {
+ LOG_ERROR("unable to allocate USB transfer");
+ cmsis_dap_usb_close(dap);
+ return ERROR_FAIL;
+ }
+ }
+
err = cmsis_dap_usb_alloc(dap, packet_size);
if (err != ERROR_OK)
cmsis_dap_usb_close(dap);
@@ -376,65 +419,178 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
static void cmsis_dap_usb_close(struct cmsis_dap *dap)
{
+ for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+ libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+ libusb_free_transfer(dap->bdata->response_transfers[i].transfer);
+ }
+ cmsis_dap_usb_free(dap);
libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface);
libusb_close(dap->bdata->dev_handle);
libusb_exit(dap->bdata->usb_ctx);
free(dap->bdata);
dap->bdata = NULL;
- free(dap->packet_buffer);
- dap->packet_buffer = NULL;
}
-static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms)
+static void LIBUSB_CALL cmsis_dap_usb_callback(struct libusb_transfer *transfer)
+{
+ struct cmsis_dap_bulk_transfer *tr;
+
+ tr = (struct cmsis_dap_bulk_transfer *)transfer->user_data;
+ if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
+ tr->status = CMSIS_DAP_TRANSFER_COMPLETED;
+ tr->transferred = transfer->actual_length;
+ } else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
+ tr->status = ERROR_TIMEOUT_REACHED;
+ } else {
+ tr->status = ERROR_JTAG_DEVICE_ERROR;
+ }
+}
+
+static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms,
+ struct timeval *wait_timeout)
{
int transferred = 0;
int err;
+ struct cmsis_dap_bulk_transfer *tr;
+ tr = &dap->bdata->response_transfers[dap->pending_fifo_get_idx];
+
+ if (tr->status == CMSIS_DAP_TRANSFER_IDLE) {
+ libusb_fill_bulk_transfer(tr->transfer,
+ dap->bdata->dev_handle, dap->bdata->ep_in,
+ tr->buffer, dap->packet_size,
+ &cmsis_dap_usb_callback, tr,
+ transfer_timeout_ms);
+ LOG_DEBUG_IO("submit read @ %u", dap->pending_fifo_get_idx);
+ tr->status = CMSIS_DAP_TRANSFER_PENDING;
+ err = libusb_submit_transfer(tr->transfer);
+ if (err) {
+ tr->status = CMSIS_DAP_TRANSFER_IDLE;
+ LOG_ERROR("error submitting USB read: %s", libusb_strerror(err));
+ return ERROR_FAIL;
+ }
+ }
- err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_in,
- dap->packet_buffer, dap->packet_size, &transferred, timeout_ms);
- if (err) {
- if (err == LIBUSB_ERROR_TIMEOUT) {
- return ERROR_TIMEOUT_REACHED;
- } else {
- LOG_ERROR("error reading data: %s", libusb_strerror(err));
+ struct timeval tv = {
+ .tv_sec = transfer_timeout_ms / 1000,
+ .tv_usec = transfer_timeout_ms % 1000 * 1000
+ };
+
+ while (tr->status == CMSIS_DAP_TRANSFER_PENDING) {
+ err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx,
+ wait_timeout ? wait_timeout : &tv,
+ &tr->status);
+ if (err) {
+ LOG_ERROR("error handling USB events: %s", libusb_strerror(err));
return ERROR_FAIL;
}
+ if (wait_timeout)
+ break;
}
- memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred);
+ if (tr->status < 0 || tr->status == CMSIS_DAP_TRANSFER_COMPLETED) {
+ /* Check related command request for an error */
+ struct cmsis_dap_bulk_transfer *tr_cmd;
+ tr_cmd = &dap->bdata->command_transfers[dap->pending_fifo_get_idx];
+ if (tr_cmd->status < 0) {
+ err = tr_cmd->status;
+ tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE;
+ if (err != ERROR_TIMEOUT_REACHED)
+ LOG_ERROR("error writing USB data");
+ else
+ LOG_DEBUG("command write USB timeout @ %u", dap->pending_fifo_get_idx);
+
+ return err;
+ }
+ if (tr_cmd->status == CMSIS_DAP_TRANSFER_COMPLETED)
+ tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE;
+ }
+
+ if (tr->status < 0) {
+ err = tr->status;
+ tr->status = CMSIS_DAP_TRANSFER_IDLE;
+ if (err != ERROR_TIMEOUT_REACHED)
+ LOG_ERROR("error reading USB data");
+ else
+ LOG_DEBUG("USB timeout @ %u", dap->pending_fifo_get_idx);
+
+ return err;
+ }
+
+ if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) {
+ transferred = tr->transferred;
+ LOG_DEBUG_IO("completed read @ %u, transferred %i",
+ dap->pending_fifo_get_idx, transferred);
+ memcpy(dap->packet_buffer, tr->buffer, transferred);
+ memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred);
+ tr->status = CMSIS_DAP_TRANSFER_IDLE;
+ }
return transferred;
}
static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
{
- int transferred = 0;
int err;
+ struct cmsis_dap_bulk_transfer *tr;
+ tr = &dap->bdata->command_transfers[dap->pending_fifo_put_idx];
+
+ if (tr->status == CMSIS_DAP_TRANSFER_PENDING) {
+ LOG_ERROR("busy command USB transfer at %u", dap->pending_fifo_put_idx);
+ struct timeval tv = {
+ .tv_sec = timeout_ms / 1000,
+ .tv_usec = timeout_ms % 1000 * 1000
+ };
+ libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, &tr->status);
+ }
+ if (tr->status < 0) {
+ if (tr->status != ERROR_TIMEOUT_REACHED)
+ LOG_ERROR("error writing USB data, late detect");
+ else
+ LOG_DEBUG("USB write timeout @ %u, late detect", dap->pending_fifo_get_idx);
+ tr->status = CMSIS_DAP_TRANSFER_IDLE;
+ }
+ if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) {
+ LOG_ERROR("USB write: late transfer competed");
+ tr->status = CMSIS_DAP_TRANSFER_IDLE;
+ }
+ if (tr->status != CMSIS_DAP_TRANSFER_IDLE) {
+ libusb_cancel_transfer(tr->transfer);
+ /* TODO: switch to less verbose errors and wait for USB working again */
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+
+ memcpy(tr->buffer, dap->packet_buffer, txlen);
+
+ libusb_fill_bulk_transfer(tr->transfer,
+ dap->bdata->dev_handle, dap->bdata->ep_out,
+ tr->buffer, txlen,
+ &cmsis_dap_usb_callback, tr,
+ timeout_ms);
- /* skip the first byte that is only used by the HID backend */
- err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out,
- dap->packet_buffer, txlen, &transferred, timeout_ms);
+ LOG_DEBUG_IO("submit write @ %u", dap->pending_fifo_put_idx);
+ tr->status = CMSIS_DAP_TRANSFER_PENDING;
+ err = libusb_submit_transfer(tr->transfer);
if (err) {
- if (err == LIBUSB_ERROR_TIMEOUT) {
- return ERROR_TIMEOUT_REACHED;
- } else {
- LOG_ERROR("error writing data: %s", libusb_strerror(err));
- return ERROR_FAIL;
- }
+ if (err == LIBUSB_ERROR_BUSY)
+ libusb_cancel_transfer(tr->transfer);
+ else
+ tr->status = CMSIS_DAP_TRANSFER_IDLE;
+
+ LOG_ERROR("error submitting USB write: %s", libusb_strerror(err));
+ return ERROR_FAIL;
}
- return transferred;
+ return ERROR_OK;
}
static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
{
- uint8_t *buf = malloc(pkt_sz);
- if (!buf) {
+ dap->packet_buffer = malloc(pkt_sz);
+ if (!dap->packet_buffer) {
LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
return ERROR_FAIL;
}
- dap->packet_buffer = buf;
dap->packet_size = pkt_sz;
dap->packet_buffer_size = pkt_sz;
/* Prevent sending zero size USB packets */
@@ -443,9 +599,41 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
dap->command = dap->packet_buffer;
dap->response = dap->packet_buffer;
+ for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+ dap->bdata->command_transfers[i].buffer =
+ libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz);
+ if (!dap->bdata->command_transfers[i].buffer) {
+ LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
+ return ERROR_FAIL;
+ }
+ dap->bdata->response_transfers[i].buffer =
+ libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz);
+ if (!dap->bdata->response_transfers[i].buffer) {
+ LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
+ return ERROR_FAIL;
+ }
+ }
+
return ERROR_OK;
}
+static void cmsis_dap_usb_free(struct cmsis_dap *dap)
+{
+ for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+ libusb_dev_mem_free(dap->bdata->dev_handle,
+ dap->bdata->command_transfers[i].buffer, dap->packet_size);
+ dap->bdata->command_transfers[i].buffer = NULL;
+ libusb_dev_mem_free(dap->bdata->dev_handle,
+ dap->bdata->response_transfers[i].buffer, dap->packet_size);
+ dap->bdata->response_transfers[i].buffer = NULL;
+ }
+
+ free(dap->packet_buffer);
+ dap->packet_buffer = NULL;
+ dap->command = NULL;
+ dap->response = NULL;
+}
+
COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
{
if (CMD_ARGC == 1)
@@ -474,4 +662,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = {
.read = cmsis_dap_usb_read,
.write = cmsis_dap_usb_write,
.packet_buffer_alloc = cmsis_dap_usb_alloc,
+ .packet_buffer_free = cmsis_dap_usb_free,
};
diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c
index 52dfd7616..6338886c8 100644
--- a/src/jtag/drivers/cmsis_dap_usb_hid.c
+++ b/src/jtag/drivers/cmsis_dap_usb_hid.c
@@ -36,6 +36,7 @@ struct cmsis_dap_backend_data {
static void cmsis_dap_hid_close(struct cmsis_dap *dap);
static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
+static void cmsis_dap_hid_free(struct cmsis_dap *dap);
static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
{
@@ -165,14 +166,21 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap)
hid_exit();
free(dap->bdata);
dap->bdata = NULL;
- free(dap->packet_buffer);
- dap->packet_buffer = NULL;
+ cmsis_dap_hid_free(dap);
}
-static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
+static int cmsis_dap_hid_read(struct cmsis_dap *dap, int transfer_timeout_ms,
+ struct timeval *wait_timeout)
{
- int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, timeout_ms);
-
+ int timeout_ms;
+ if (wait_timeout)
+ timeout_ms = wait_timeout->tv_usec / 1000 + wait_timeout->tv_sec * 1000;
+ else
+ timeout_ms = transfer_timeout_ms;
+
+ int retval = hid_read_timeout(dap->bdata->dev_handle,
+ dap->packet_buffer, dap->packet_buffer_size,
+ timeout_ms);
if (retval == 0) {
return ERROR_TIMEOUT_REACHED;
} else if (retval == -1) {
@@ -222,6 +230,12 @@ static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
return ERROR_OK;
}
+static void cmsis_dap_hid_free(struct cmsis_dap *dap)
+{
+ free(dap->packet_buffer);
+ dap->packet_buffer = NULL;
+}
+
const struct cmsis_dap_backend cmsis_dap_hid_backend = {
.name = "hid",
.open = cmsis_dap_hid_open,
@@ -229,4 +243,5 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = {
.read = cmsis_dap_hid_read,
.write = cmsis_dap_hid_write,
.packet_buffer_alloc = cmsis_dap_hid_alloc,
+ .packet_buffer_free = cmsis_dap_hid_free,
};
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/cmsis_dap.c | 114 +++++++++++-----
src/jtag/drivers/cmsis_dap.h | 4 +-
src/jtag/drivers/cmsis_dap_usb_bulk.c | 239 ++++++++++++++++++++++++++++++----
src/jtag/drivers/cmsis_dap_usb_hid.c | 25 +++-
4 files changed, 319 insertions(+), 63 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-03 06:23:29
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 0f70c6c325785517f35bbbb9316801bef7a79d8b (commit)
from 119a5338623d77bbdbc37b6ecb5e93df3368af30 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0f70c6c325785517f35bbbb9316801bef7a79d8b
Author: Manuel Wick <ma...@ma...>
Date: Sat Jan 30 22:46:50 2021 +0100
remote_bitbang: Add SWD support
This adds new command characters to make SWD work with the new split
jtag and swd operations of bitbang.
The command characters are as follows:
O - SWDIO drive 1
o - SWDIO drive 0
c - SWDIO read request
d - SWD write 0 0
e - SWD write 0 1
f - SWD write 1 0
g - SWD write 1 1
Documentation has been updated accordingly. The new commands will be
used by an adapted version of the jtag-openocd applet of the "Glasgow
Debug Tool" (https://github.com/glasgowEmbedded/Glasgow). It has been
tested against an stm32f103 and an at91samd21 target.
contrib/remote/bitbang/remote_bitbang_sysfsgpio.c has also been adapted
to support SWD via the new command set. Some limited testing has been
done using a Raspberry Pi 2 with an stm32f103 and an at91samd21 target
attached.
Change-Id: I8e998a2cb36905142cb16e534483094cd99e8fa7
Signed-off-by: Manuel Wick <ma...@ma...>
Signed-off-by: David Ryskalczyk <dav...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/6044
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/configure.ac b/configure.ac
index a2442d40b..c9cf0214e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -382,7 +382,7 @@ AC_ARG_ENABLE([internal-libjaylink],
[use_internal_libjaylink=$enableval], [use_internal_libjaylink=no])
AC_ARG_ENABLE([remote-bitbang],
- AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]),
+ AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang driver]),
[build_remote_bitbang=$enableval], [build_remote_bitbang=no])
AS_CASE(["${host_cpu}"],
@@ -598,9 +598,9 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [
AS_IF([test "x$build_remote_bitbang" = "xyes"], [
build_bitbang=yes
- AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang JTAG driver.])
+ AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang driver.])
], [
- AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang JTAG driver.])
+ AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang driver.])
])
AS_IF([test "x$build_sysfsgpio" = "xyes"], [
diff --git a/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c b/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c
index 9294837e3..1588eb9a3 100644
--- a/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c
+++ b/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c
@@ -1,30 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
+ * Copyright (C) 2021 by Manuel Wick <ma...@ma...> *
* Copyright (C) 2013 Paul Fertser <fer...@gm...> *
* Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
***************************************************************************/
/*
- This is a test application to be used as a remote bitbang server for
- the OpenOCD remote_bitbang interface driver.
-
- To compile run:
- gcc -Wall -ansi -pedantic -std=c99 -o remote_bitbang_sysfsgpio remote_bitbang_sysfsgpio.c
-
-
- Usage example:
-
- On Raspberry Pi run:
- socat TCP6-LISTEN:7777,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10"
-
- On host run:
- openocd -c "interface remote_bitbang; remote_bitbang host raspberrypi; remote_bitbang port 7777" \
- -f target/stm32f1x.cfg
-
- Or if you want to test UNIX sockets, run both on Raspberry Pi:
- socat UNIX-LISTEN:/tmp/remotebitbang-socket,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10"
- openocd -c "interface remote_bitbang; remote_bitbang host /tmp/remotebitbang-socket" -f target/stm32f1x.cfg
+ * This is a test application to be used as a remote bitbang server for
+ * the OpenOCD remote_bitbang interface driver.
+ *
+ * To compile run:
+ * gcc -Wall -ansi -pedantic -std=c99 -o remote_bitbang_sysfsgpio remote_bitbang_sysfsgpio.c
+ *
+ *
+ * Usage example:
+ *
+ * On Raspberry Pi run:
+ * socat TCP6-LISTEN:7777,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10"
+ *
+ * On host run:
+ * openocd -c "adapter driver remote_bitbang; remote_bitbang host raspberrypi; remote_bitbang port 7777" \
+ * -f target/stm32f1x.cfg
+ *
+ * Or if you want to test UNIX sockets, run both on Raspberry Pi:
+ * socat UNIX-LISTEN:/tmp/remotebitbang-socket,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10"
+ * openocd -c "adapter driver remote_bitbang; remote_bitbang host /tmp/remotebitbang-socket" -f target/stm32f1x.cfg
*/
#include <sys/types.h>
@@ -97,11 +98,14 @@ static void unexport_sysfs_gpio(int gpio)
* If the gpio is an output, it is initialized according to init_high,
* otherwise it is ignored.
*
+ * When open_rw is set, the file descriptor will be open as read and write,
+ * e.g. for SWDIO (TMS) that is used as input and output.
+ *
* If the gpio is already exported we just show a warning and continue; if
* openocd happened to crash (or was killed by user) then the gpios will not
* have been cleaned up.
*/
-static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
+static int setup_sysfs_gpio(int gpio, int is_output, int init_high, int open_rw)
{
char buf[40];
char gpiostr[4];
@@ -132,7 +136,9 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
- if (is_output)
+ if (open_rw)
+ ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
+ else if (is_output)
ret = open(buf, O_WRONLY | O_NONBLOCK | O_SYNC);
else
ret = open(buf, O_RDONLY | O_NONBLOCK | O_SYNC);
@@ -143,6 +149,37 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
return ret;
}
+/*
+ * Change direction for gpio.
+ */
+static int change_dir_sysfs_gpio(int gpio, int is_output, int init_high)
+{
+ char buf[40];
+ int ret;
+
+ if (!is_gpio_valid(gpio))
+ return ERROR_OK;
+
+ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
+ ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
+ if (ret < 0) {
+ LOG_ERROR("Couldn't set direction for gpio %d", gpio);
+ perror("sysfsgpio: ");
+ unexport_sysfs_gpio(gpio);
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
+
+/* gpio numbers for each gpio. Negative values are invalid */
+static int tck_gpio = -1;
+static int tms_gpio = -1;
+static int tdi_gpio = -1;
+static int tdo_gpio = -1;
+static int trst_gpio = -1;
+static int srst_gpio = -1;
+
/*
* file descriptors for /sys/class/gpio/gpioXX/value
* Set up during init.
@@ -154,6 +191,15 @@ static int tdo_fd = -1;
static int trst_fd = -1;
static int srst_fd = -1;
+/*
+ * GPIO state of /sys/class/gpio/gpioXX/value
+ */
+static int last_tck = -1;
+static int last_tms = -1;
+static int last_tms_drive = -1;
+static int last_tdi = -1;
+static int last_initialized = -1;
+
/*
* Bitbang interface read of TDO
*
@@ -179,26 +225,22 @@ static int sysfsgpio_read(void)
/*
* Bitbang interface write of TCK, TMS, TDI
*
- * Seeing as this is the only function where the outputs are changed,
- * we can cache the old value to avoid needlessly writing it.
+ * Output states are changed here and in sysfsgpio_write_swd,
+ * which are not used simultaneously, so we can cache the old
+ * value to avoid needlessly writing it.
*/
static void sysfsgpio_write(int tck, int tms, int tdi)
{
const char one[] = "1";
const char zero[] = "0";
- static int last_tck;
- static int last_tms;
- static int last_tdi;
-
- static int first_time;
size_t bytes_written;
- if (!first_time) {
+ if (!last_initialized) {
last_tck = !tck;
last_tms = !tms;
last_tdi = !tdi;
- first_time = 1;
+ last_initialized = 1;
}
if (tdi != last_tdi) {
@@ -251,13 +293,81 @@ static void sysfsgpio_reset(int trst, int srst)
}
}
-/* gpio numbers for each gpio. Negative values are invalid */
-static int tck_gpio = -1;
-static int tms_gpio = -1;
-static int tdi_gpio = -1;
-static int tdo_gpio = -1;
-static int trst_gpio = -1;
-static int srst_gpio = -1;
+/*
+ * Bitbang interface set direction of SWDIO (TMS)
+ */
+static void sysfsgpio_swdio_drive(int is_output)
+{
+ int ret;
+
+ if (is_output != 0 && last_tms == -1)
+ last_tms = 0;
+
+ ret = change_dir_sysfs_gpio(tms_gpio, (is_output != 0) ? 1 : 0, last_tms);
+ if (ret != ERROR_OK)
+ LOG_WARNING("Failed to change SWDIO (TMS) direction to output");
+ else
+ last_tms_drive = (is_output != 0) ? 1 : 0;
+}
+
+/*
+ * Bitbang interface read of SWDIO (TMS)
+ *
+ * The sysfs value will read back either '0' or '1'. The trick here is to call
+ * lseek to bypass buffering in the sysfs kernel driver.
+ */
+static int sysfsgpio_swdio_read(void)
+{
+ char buf[1];
+
+ /* important to seek to signal sysfs of new read */
+ lseek(tms_fd, 0, SEEK_SET);
+ int ret = read(tms_fd, &buf, sizeof(buf));
+
+ if (ret < 0) {
+ LOG_WARNING("reading swdio (tms) failed");
+ return 0;
+ }
+
+ return buf[0];
+}
+
+/*
+ * Bitbang interface write of SWCLK (TCK) and SWDIO (TMS)
+ *
+ * Output states are changed here and in sysfsgpio_write, which
+ * are not used simultaneously, so we can cache the old value
+ * to avoid needlessly writing it.
+ */
+static void sysfsgpio_swd_write(int swclk, int swdio)
+{
+ static const char one[] = "1";
+ static const char zero[] = "0";
+
+ size_t bytes_written;
+
+ if (!last_initialized) {
+ last_tck = !swclk;
+ last_tms = !swdio;
+ last_initialized = 1;
+ }
+
+ if (last_tms_drive == 1 && swdio != last_tms) {
+ bytes_written = write(tms_fd, swdio ? &one : &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing swdio (tms) failed");
+ }
+
+ /* write clk last */
+ if (swclk != last_tck) {
+ bytes_written = write(tck_fd, swclk ? &one : &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing swclk (tck) failed");
+ }
+
+ last_tms = swdio;
+ last_tck = swclk;
+}
/* helper func to close and cleanup files only if they were valid/ used */
static void cleanup_fd(int fd, int gpio)
@@ -293,13 +403,21 @@ static void process_remote_protocol(void)
char d = c - 'r';
sysfsgpio_reset(!!(d & 2),
(d & 1));
- } else if (c >= '0' && c <= '0' + 7) {/* Write */
+ } else if (c >= '0' && c <= '0' + 7) { /* Write */
char d = c - '0';
sysfsgpio_write(!!(d & 4),
!!(d & 2),
(d & 1));
} else if (c == 'R')
putchar(sysfsgpio_read());
+ else if (c == 'c') /* SWDIO read */
+ putchar(sysfsgpio_swdio_read());
+ else if (c == 'o' || c == 'O') /* SWDIO drive */
+ sysfsgpio_swdio_drive(c == 'o' ? 0 : 1);
+ else if (c >= 'd' && c <= 'g') { /* SWD write */
+ char d = c - 'd';
+ sysfsgpio_swd_write((d & 2), (d & 1));
+ }
else
LOG_ERROR("Unknown command '%c' received", c);
}
@@ -307,7 +425,7 @@ static void process_remote_protocol(void)
int main(int argc, char *argv[])
{
- LOG_WARNING("SysfsGPIO remote_bitbang JTAG driver\n");
+ LOG_WARNING("SysfsGPIO remote_bitbang JTAG+SWD driver\n");
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "tck"))
@@ -349,36 +467,39 @@ int main(int argc, char *argv[])
* Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
* as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
*/
- tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0);
+ tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0, 0);
if (tck_fd < 0)
goto out_error;
- tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1);
+ tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1, 1);
if (tms_fd < 0)
goto out_error;
+ last_tms_drive = 0;
- tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0);
+ tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0, 0);
if (tdi_fd < 0)
goto out_error;
- tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0);
+ tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0, 0);
if (tdo_fd < 0)
goto out_error;
/* assume active low */
if (trst_gpio > 0) {
- trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1);
+ trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1, 0);
if (trst_fd < 0)
goto out_error;
}
/* assume active low */
if (srst_gpio > 0) {
- srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1);
+ srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1, 0);
if (srst_fd < 0)
goto out_error;
}
+ last_initialized = 0;
+
LOG_WARNING("SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
LOG_WARNING("SysfsGPIO num: srst = %d", srst_gpio);
diff --git a/doc/manual/jtag/drivers/remote_bitbang.txt b/doc/manual/jtag/drivers/remote_bitbang.txt
index f394d736a..7c8eee289 100644
--- a/doc/manual/jtag/drivers/remote_bitbang.txt
+++ b/doc/manual/jtag/drivers/remote_bitbang.txt
@@ -1,15 +1,19 @@
/** @remote_bitbangpage OpenOCD Developer's Guide
-The remote_bitbang JTAG driver is used to drive JTAG from a remote process. The
-remote_bitbang driver communicates via TCP or UNIX sockets with some remote
-process using an ASCII encoding of the bitbang interface. The remote process
-presumably then drives the JTAG however it pleases. The remote process should
-act as a server, listening for connections from the openocd remote_bitbang
-driver.
+The remote_bitbang JTAG+SWD driver is used to drive JTAG and/or SWD from a
+remote process. The remote_bitbang driver communicates via TCP or UNIX
+sockets with some remote process using an ASCII encoding of the bitbang
+interface. The remote process presumably then drives the JTAG/SWD however
+it pleases. The remote process should act as a server, listening for
+connections from the openocd remote_bitbang driver.
The remote bitbang driver is useful for debugging software running on
processors which are being simulated.
+There also is an implementation of the server-side protocol for the
+Glasgow Debug Tool (https://github.com/glasgowEmbedded/Glasgow) through
+the jtag-openocd applet.
+
The bitbang interface consists of the following functions.
blink on
@@ -24,11 +28,20 @@ write tck tms tdi
reset trst srst
Set the value of trst, srst.
+swdio_drive
+ Set the output enable of the bidirectional swdio (tms) pin
+
+swdio_read
+ Sample the value of swdio (tms).
+
+swd_write
+ Set the value of swclk (tck) and swdio (tms).
+
An additional function, quit, is added to the remote_bitbang interface to
indicate there will be no more requests and the connection with the remote
driver should be closed.
-These five functions are encoded in ASCII by assigning a single character to
+These eight functions are encoded in ASCII by assigning a single character to
each possible request. The assignments are:
B - Blink on
@@ -47,7 +60,14 @@ each possible request. The assignments are:
s - Reset 0 1
t - Reset 1 0
u - Reset 1 1
+ O - SWDIO drive 1
+ o - SWDIO drive 0
+ c - SWDIO read request
+ d - SWD write 0 0
+ e - SWD write 0 1
+ f - SWD write 1 0
+ g - SWD write 1 1
-The read response is encoded in ASCII as either digit 0 or 1.
+The read responses are encoded in ASCII as either digit 0 or 1.
*/
diff --git a/doc/openocd.texi b/doc/openocd.texi
index c14ee9cb6..de990c538 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -2810,9 +2810,9 @@ If not specified, default 0xFFFF is used.
@end deffn
@deffn {Interface Driver} {remote_bitbang}
-Drive JTAG from a remote process. This sets up a UNIX or TCP socket connection
-with a remote process and sends ASCII encoded bitbang requests to that process
-instead of directly driving JTAG.
+Drive JTAG and SWD from a remote process. This sets up a UNIX or TCP socket
+connection with a remote process and sends ASCII encoded bitbang requests to
+that process instead of directly driving JTAG and SWD.
The remote_bitbang driver is useful for debugging software running on
processors which are being simulated.
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index 36bcbe19c..261c30df2 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -3,6 +3,8 @@
/***************************************************************************
* Copyright (C) 2011 by Richard Uhler *
* ru...@mi... *
+ * *
+ * Copyright (C) 2021 by Manuel Wick <ma...@ma...> *
***************************************************************************/
#ifdef HAVE_CONFIG_H
@@ -220,11 +222,35 @@ static int remote_bitbang_blink(int on)
return remote_bitbang_queue(c, FLUSH_SEND_BUF);
}
+static void remote_bitbang_swdio_drive(bool is_output)
+{
+ char c = is_output ? 'O' : 'o';
+ if (remote_bitbang_queue(c, FLUSH_SEND_BUF) == ERROR_FAIL)
+ LOG_ERROR("Error setting direction for swdio");
+}
+
+static int remote_bitbang_swdio_read(void)
+{
+ if (remote_bitbang_queue('c', FLUSH_SEND_BUF) != ERROR_FAIL)
+ return remote_bitbang_read_sample();
+ else
+ return BB_ERROR;
+}
+
+static int remote_bitbang_swd_write(int swclk, int swdio)
+{
+ char c = 'd' + ((swclk ? 0x2 : 0x0) | (swdio ? 0x1 : 0x0));
+ return remote_bitbang_queue(c, NO_FLUSH);
+}
+
static struct bitbang_interface remote_bitbang_bitbang = {
.buf_size = sizeof(remote_bitbang_recv_buf) - 1,
.sample = &remote_bitbang_sample,
.read_sample = &remote_bitbang_read_sample,
.write = &remote_bitbang_write,
+ .swdio_read = &remote_bitbang_swdio_read,
+ .swdio_drive = &remote_bitbang_swdio_drive,
+ .swd_write = &remote_bitbang_swd_write,
.blink = &remote_bitbang_blink,
};
@@ -349,6 +375,8 @@ COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
return ERROR_COMMAND_SYNTAX_ERROR;
}
+static const char * const remote_bitbang_transports[] = { "jtag", "swd", NULL };
+
static const struct command_registration remote_bitbang_subcommand_handlers[] = {
{
.name = "port",
@@ -401,7 +429,7 @@ static struct jtag_interface remote_bitbang_interface = {
struct adapter_driver remote_bitbang_adapter_driver = {
.name = "remote_bitbang",
- .transports = jtag_only,
+ .transports = remote_bitbang_transports,
.commands = remote_bitbang_command_handlers,
.init = &remote_bitbang_init,
@@ -409,4 +437,5 @@ struct adapter_driver remote_bitbang_adapter_driver = {
.reset = &remote_bitbang_reset,
.jtag_ops = &remote_bitbang_interface,
+ .swd_ops = &bitbang_swd,
};
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 6 +-
contrib/remote_bitbang/remote_bitbang_sysfsgpio.c | 211 +++++++++++++++++-----
doc/manual/jtag/drivers/remote_bitbang.txt | 36 +++-
doc/openocd.texi | 6 +-
src/jtag/drivers/remote_bitbang.c | 31 +++-
5 files changed, 230 insertions(+), 60 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-01 22:24:23
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 119a5338623d77bbdbc37b6ecb5e93df3368af30 (commit)
from 73d62f3f0cd4cb3fb6975d4223bf44b35a0e1479 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 119a5338623d77bbdbc37b6ecb5e93df3368af30
Author: Marc Schink <de...@za...>
Date: Mon Nov 20 11:33:00 2023 +0100
target/target: Fix 'wp' command usage
While at it, fix the 'wp' command documentation.
Change-Id: I70f3110e8ce286051f8f810260f1857b2285e634
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8022
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
Reviewed-by: Jan Matyas <jan...@co...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index e8b207c52..c14ee9cb6 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9374,7 +9374,7 @@ Remove the breakpoint at @var{address} or all breakpoints.
Remove data watchpoint on @var{address} or all watchpoints.
@end deffn
-@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]]
+@deffn {Command} {wp} [address length [(@option{r}|@option{w}|@option{a}) [value [mask]]]]
With no parameters, lists all active watchpoints.
Else sets a data watchpoint on data from @var{address} for @var{length} bytes.
The watch point is an "access" watchpoint unless
diff --git a/src/target/target.c b/src/target/target.c
index 4a4c62613..f847894d6 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -7064,7 +7064,7 @@ static const struct command_registration target_exec_command_handlers[] = {
.handler = handle_wp_command,
.mode = COMMAND_EXEC,
.help = "list (no params) or create watchpoints",
- .usage = "[address length [('r'|'w'|'a') value [mask]]]",
+ .usage = "[address length [('r'|'w'|'a') [value [mask]]]]",
},
{
.name = "rwp",
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 2 +-
src/target/target.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-01 22:23:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 73d62f3f0cd4cb3fb6975d4223bf44b35a0e1479 (commit)
from 15038ab51a3c5811f7ff95c1f995c6e9dfe7d3d0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 73d62f3f0cd4cb3fb6975d4223bf44b35a0e1479
Author: Evgeniy Naydanov <evg...@sy...>
Date: Tue Oct 31 21:13:46 2023 +0300
target: clarify usage of `coreid`
By definition in `target/target.h`, `coreid` is not a unique identifier
of a target -- it can be the same for targets on different TAPs.
Change-Id: Ifce78da55fffe28dd8b6b06ecae7d8c4e305c0a2
Signed-off-by: Evgeniy Naydanov <evg...@sy...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7997
Tested-by: jenkins
Reviewed-by: Marek Vrbka <mar...@co...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c
index 98f4b3f04..66d4e0080 100644
--- a/src/target/armv8_cache.c
+++ b/src/target/armv8_cache.c
@@ -243,7 +243,7 @@ static int armv8_flush_all_data(struct target *target)
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr->state == TARGET_HALTED) {
- LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
+ LOG_TARGET_INFO(curr, "Wait flushing data l1.");
retval = _armv8_flush_all_data(curr);
}
}
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index ba3349d09..7fa0c4e8b 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -2989,29 +2989,29 @@ static int cortex_a_examine_first(struct target *target)
armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);
+ LOG_TARGET_DEBUG(target, "DBGPRSR 0x%" PRIx32, dbg_osreg);
if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) {
- LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid);
+ LOG_TARGET_ERROR(target, "powered down!");
target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
return ERROR_TARGET_INIT_FAILED;
}
if (dbg_osreg & PRSR_STICKY_RESET_STATUS)
- LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid);
+ LOG_TARGET_DEBUG(target, "was reset!");
/* Read DBGOSLSR and check if OSLK is implemented */
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg);
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg);
+ LOG_TARGET_DEBUG(target, "DBGOSLSR 0x%" PRIx32, dbg_osreg);
/* check if OS Lock is implemented */
if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) {
/* check if OS Lock is set */
if (dbg_osreg & OSLSR_OSLK) {
- LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid);
+ LOG_TARGET_DEBUG(target, "OSLock set! Trying to unlock");
retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_OSLAR,
@@ -3022,8 +3022,7 @@ static int cortex_a_examine_first(struct target *target)
/* if we fail to access the register or cannot reset the OSLK bit, bail out */
if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) {
- LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?",
- target->coreid);
+ LOG_TARGET_ERROR(target, "OSLock sticky, core not powered?");
target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */
return ERROR_TARGET_INIT_FAILED;
}
@@ -3036,13 +3035,11 @@ static int cortex_a_examine_first(struct target *target)
return retval;
if (dbg_idpfr1 & 0x000000f0) {
- LOG_DEBUG("target->coreid %" PRId32 " has security extensions",
- target->coreid);
+ LOG_TARGET_DEBUG(target, "has security extensions");
armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
}
if (dbg_idpfr1 & 0x0000f000) {
- LOG_DEBUG("target->coreid %" PRId32 " has virtualization extensions",
- target->coreid);
+ LOG_TARGET_DEBUG(target, "has virtualization extensions");
/*
* overwrite and simplify the checks.
* virtualization extensions require implementation of security extension
diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c
index 1d70be9e3..bc4d8a21a 100644
--- a/src/target/espressif/esp_xtensa_smp.c
+++ b/src/target/espressif/esp_xtensa_smp.c
@@ -746,7 +746,7 @@ COMMAND_HANDLER(esp_xtensa_smp_cmd_perfmon_dump)
struct target *curr;
foreach_smp_target(head, target->smp_targets) {
curr = head->target;
- LOG_INFO("CPU%d:", curr->coreid);
+ LOG_TARGET_INFO(curr, ":");
int ret = CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do,
target_to_xtensa(curr));
if (ret != ERROR_OK)
diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
index 0a06bb160..ad9808961 100644
--- a/src/target/mips_m4k.c
+++ b/src/target/mips_m4k.c
@@ -142,7 +142,7 @@ static int mips_m4k_halt_smp(struct target *target)
ret = mips_m4k_halt(curr);
if (ret != ERROR_OK) {
- LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid);
+ LOG_TARGET_ERROR(curr, "halt failed.");
retval = ret;
}
}
@@ -412,8 +412,8 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
handle_breakpoints, 0);
if (ret != ERROR_OK) {
- LOG_ERROR("target->coreid :%" PRId32 " failed to resume at address :0x%" PRIx32,
- curr->coreid, address);
+ LOG_TARGET_ERROR(curr, "failed to resume at address: 0x%" PRIx32,
+ address);
retval = ret;
}
}
diff --git a/src/target/smp.c b/src/target/smp.c
index effc63f52..50b19d01a 100644
--- a/src/target/smp.c
+++ b/src/target/smp.c
@@ -132,6 +132,9 @@ COMMAND_HANDLER(handle_smp_gdb_command)
{
struct target *target = get_current_target(CMD_CTX);
int retval = ERROR_OK;
+
+ LOG_WARNING(DEPRECATED_MSG);
+
if (!list_empty(target->smp_targets)) {
if (CMD_ARGC == 1) {
int coreid = 0;
diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
index e862fe165..85dce0614 100644
--- a/src/target/xtensa/xtensa.c
+++ b/src/target/xtensa/xtensa.c
@@ -822,7 +822,7 @@ int xtensa_examine(struct target *target)
struct xtensa *xtensa = target_to_xtensa(target);
unsigned int cmd = PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) | PWRCTL_COREWAKEUP(xtensa);
- LOG_DEBUG("coreid = %d", target->coreid);
+ LOG_TARGET_DEBUG(target, "");
if (xtensa->core_config->core_type == XT_UNDEF) {
LOG_ERROR("XTensa core not configured; is xtensa-core-openocd.cfg missing?");
-----------------------------------------------------------------------
Summary of changes:
src/target/armv8_cache.c | 2 +-
src/target/cortex_a.c | 19 ++++++++-----------
src/target/espressif/esp_xtensa_smp.c | 2 +-
src/target/mips_m4k.c | 6 +++---
src/target/smp.c | 3 +++
src/target/xtensa/xtensa.c | 2 +-
6 files changed, 17 insertions(+), 17 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-12-01 22:22:15
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 15038ab51a3c5811f7ff95c1f995c6e9dfe7d3d0 (commit)
from 7ac389cf47463cc35667659804d939015a4815e5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 15038ab51a3c5811f7ff95c1f995c6e9dfe7d3d0
Author: Walter Ji <wal...@os...>
Date: Fri Nov 17 11:27:09 2023 +0800
target/mips32: pracc write cp0 status register first
When user requested a change on cp0 status register,
it may contain changes on EXL/ERL bits, and changes on
these bits could lead to differnt behaviours on writing
to other cp0 registers.
Change-Id: Ic83039988c29c06ee134226b52de943c46d19da2
Signed-off-by: Walter Ji <wal...@os...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7914
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c
index 9f0d87cd9..db50ef928 100644
--- a/src/target/mips32_pracc.c
+++ b/src/target/mips32_pracc.c
@@ -842,12 +842,12 @@ int mips32_pracc_write_regs(struct mips32_common *mips32)
};
uint32_t cp0_write_data[] = {
+ /* status */
+ c0rs[0],
/* lo */
gprs[32],
/* hi */
gprs[33],
- /* status */
- c0rs[0],
/* badvaddr */
c0rs[1],
/* cause */
@@ -856,6 +856,9 @@ int mips32_pracc_write_regs(struct mips32_common *mips32)
c0rs[3],
};
+ /* Write CP0 Status Register first, changes on EXL or ERL bits
+ * may lead to different behaviour on writing to other CP0 registers.
+ */
for (size_t i = 0; i < ARRAY_SIZE(cp0_write_code); i++) {
/* load CP0 value in $1 */
pracc_add_li32(&ctx, 1, cp0_write_data[i], 0);
-----------------------------------------------------------------------
Summary of changes:
src/target/mips32_pracc.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-30 14:32:35
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 7ac389cf47463cc35667659804d939015a4815e5 (commit)
from 1b0b07baab2b23318ddc484a58d66214f0c2a0d2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 7ac389cf47463cc35667659804d939015a4815e5
Author: Thomas Hebb <tom...@gm...>
Date: Fri Apr 29 22:17:18 2022 -0700
tcl/target/gd32vf103: work around broken ndmreset
On this chip, the ndmreset bit in the RISC-V debug module doesn't
trigger a system reset like it should. To work around this, add a custom
"reset-assert" handler in its config file that resets the system by
writing to memory-mapped registers.
I've tested this workaround on a Sipeed Longan Nano dev board with a
GD32VF103CBT6 chip. It works correctly for both "reset run" and "reset
halt" (halting at pc=0 for the latter).
I originally submitted[1] this workaround to the riscv-openocd fork of
OpenOCD. That fork's maintainers accepted it, but have not upstreamed it
like they have several other of my changes.
[1] https://github.com/riscv/riscv-openocd/pull/538
Change-Id: I7482990755b300fcbe4963c9a599d599bc02684d
Signed-off-by: Thomas Hebb <tom...@gm...>
Signed-off-by: Tomas Vanek <va...@fb...>
Reviewed-on: https://review.openocd.org/c/openocd/+/6957
Tested-by: jenkins
Reviewed-by: zapb <de...@za...>
diff --git a/tcl/target/gd32vf103.cfg b/tcl/target/gd32vf103.cfg
index 068124334..54a74e8cc 100644
--- a/tcl/target/gd32vf103.cfg
+++ b/tcl/target/gd32vf103.cfg
@@ -28,6 +28,12 @@ jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+proc default_mem_access {} {
+ riscv set_mem_access progbuf
+}
+
+default_mem_access
+
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
set _FLASHNAME $_CHIPNAME.flash
@@ -40,3 +46,74 @@ $_TARGETNAME configure -event reset-init {
# DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP
mmw 0xE0042004 0x00000300 0
}
+
+# On this chip, ndmreset (the debug module bit that triggers a software reset)
+# doesn't work. So for JTAG connections without an SRST, we need to trigger a
+# reset manually. This is an undocumented reset sequence that's used by the
+# JTAG flashing script in the vendor-supplied GD32VF103 PlatformIO plugin:
+#
+# https://github.com/sipeed/platform-gd32v/commit/f9cbb44819bc05dd2010cc815c32be0486800cc2
+#
+$_TARGETNAME configure -event reset-assert {
+ set dmcontrol 0x10
+ set dmcontrol_dmactive [expr {1 << 0}]
+ set dmcontrol_ackhavereset [expr {1 << 28}]
+ set dmcontrol_haltreq [expr {1 << 31}]
+
+ global _RESETMODE
+
+ # If hardware NRST signal is connected and configured (reset_config srst_only)
+ # the device has been recently reset in 'jtag arp_init-reset', therefore
+ # DM_DMSTATUS_ANYHAVERESET reads 1.
+ # The following 'halt' command checks this status bit
+ # and shows 'Hart 0 unexpectedly reset!' if set.
+ # Prevent this message by sending an acknowledge first.
+ set val [expr {$dmcontrol_dmactive | $dmcontrol_ackhavereset}]
+ riscv dmi_write $dmcontrol $val
+
+ # Halt the core so that we can write to memory. We do this first so
+ # that it doesn't clobber our dmcontrol configuration.
+ halt
+
+ # Set haltreq appropriately for the type of reset we're doing. This
+ # replicates what the generic RISC-V reset_assert() function would
+ # do if we weren't overriding it. The $_RESETMODE hack sucks, but
+ # it's the least invasive way to determine whether we need to halt.
+ #
+ # If we didn't override the generic handler, we'd actually still have
+ # to do this: the default handler sets ndmreset, which prevents memory
+ # access even though it doesn't actually trigger a reset on this chip.
+ # So we'd need to unset it here, which involves a write to dmcontrol,
+ # Since haltreq is write-only and there's no way to leave it unchanged,
+ # we'd have to figure out its proper value anyway.
+ set val $dmcontrol_dmactive
+ if {$_RESETMODE ne "run"} {
+ set val [expr {$val | $dmcontrol_haltreq}]
+ }
+ riscv dmi_write $dmcontrol $val
+
+ # Unlock 0xe0042008 so that the next write triggers a reset
+ mww 0xe004200c 0x4b5a6978
+
+ # We need to trigger the reset using abstract memory access, since
+ # progbuf access tries to read a status code out of a core register
+ # after the write happens, which fails when the core is in reset.
+ riscv set_mem_access abstract
+
+ # Go!
+ mww 0xe0042008 0x1
+
+ # Put the memory access mode back to what it was.
+ default_mem_access
+}
+
+# Capture the mode of a given reset so that we can use it later in the
+# reset-assert handler.
+proc init_reset { mode } {
+ global _RESETMODE
+ set _RESETMODE $mode
+
+ if {[using_jtag]} {
+ jtag arp_init-reset
+ }
+}
-----------------------------------------------------------------------
Summary of changes:
tcl/target/gd32vf103.cfg | 77 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-24 21:41:18
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 1b0b07baab2b23318ddc484a58d66214f0c2a0d2 (commit)
from be5cfdc86bce09e688aad16134cb36561c85d5eb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 1b0b07baab2b23318ddc484a58d66214f0c2a0d2
Author: Marc Schink <de...@za...>
Date: Sun Nov 12 11:43:48 2023 +0100
target: Throw error in 'debug_reason' command
Instead of returning an 'error string', throw an error. This makes it
much easier to handle errors in Tcl scripts or in tools that use Tcl RPC.
Change-Id: I75c48750cfad7430fa5e6bc88fe04ebd59d34cea
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8006
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/target/target.c b/src/target/target.c
index d8e65863c..4a4c62613 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -5845,7 +5845,17 @@ COMMAND_HANDLER(handle_target_debug_reason)
struct target *target = get_current_target(CMD_CTX);
- command_print(CMD, "%s", debug_reason_name(target));
+
+ const char *debug_reason = nvp_value2name(nvp_target_debug_reason,
+ target->debug_reason)->name;
+
+ if (!debug_reason) {
+ command_print(CMD, "bug: invalid debug reason (%d)",
+ target->debug_reason);
+ return ERROR_FAIL;
+ }
+
+ command_print(CMD, "%s", debug_reason);
return ERROR_OK;
}
-----------------------------------------------------------------------
Summary of changes:
src/target/target.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-24 21:07:50
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via be5cfdc86bce09e688aad16134cb36561c85d5eb (commit)
from 53e67c37abee6506bb06eaf0d50d4d9ce045c0c8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit be5cfdc86bce09e688aad16134cb36561c85d5eb
Author: Evgeniy Naydanov <evg...@sy...>
Date: Tue Oct 31 16:53:52 2023 +0300
target: remove `target_number`
Change-Id: Id36e5ad2967303483392fd2670630289ecde2553
Signed-off-by: Evgeniy Naydanov <evg...@sy...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7998
Reviewed-by: Antonio Borneo <bor...@gm...>
Reviewed-by: Marek Vrbka <mar...@co...>
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
diff --git a/src/target/target.c b/src/target/target.c
index 9f43e2f91..d8e65863c 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -298,23 +298,6 @@ const char *target_reset_mode_name(enum target_reset_mode reset_mode)
return cp;
}
-/* determine the number of the new target */
-static int new_target_number(void)
-{
- struct target *t;
- int x;
-
- /* number is 0 based */
- x = -1;
- t = all_targets;
- while (t) {
- if (x < t->target_number)
- x = t->target_number;
- t = t->next;
- }
- return x + 1;
-}
-
static void append_to_list_all_targets(struct target *target)
{
struct target **t = &all_targets;
@@ -450,7 +433,7 @@ void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_
target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]);
}
-/* return a pointer to a configured target; id is name or number */
+/* return a pointer to a configured target; id is name or index in all_targets */
struct target *get_target(const char *id)
{
struct target *target;
@@ -463,36 +446,17 @@ struct target *get_target(const char *id)
return target;
}
- /* It's OK to remove this fallback sometime after August 2010 or so */
-
- /* no match, try as number */
- unsigned num;
- if (parse_uint(id, &num) != ERROR_OK)
+ /* try as index */
+ unsigned int index, counter;
+ if (parse_uint(id, &index) != ERROR_OK)
return NULL;
- for (target = all_targets; target; target = target->next) {
- if (target->target_number == (int)num) {
- LOG_WARNING("use '%s' as target identifier, not '%u'",
- target_name(target), num);
- return target;
- }
- }
-
- return NULL;
-}
-
-/* returns a pointer to the n-th configured target */
-struct target *get_target_by_num(int num)
-{
- struct target *target = all_targets;
+ for (target = all_targets, counter = index;
+ target && counter;
+ target = target->next, --counter)
+ ;
- while (target) {
- if (target->target_number == num)
- return target;
- target = target->next;
- }
-
- return NULL;
+ return target;
}
struct target *get_current_target(struct command_context *cmd_ctx)
@@ -2843,10 +2807,10 @@ COMMAND_HANDLER(handle_targets_command)
}
}
- struct target *target = all_targets;
+ unsigned int index = 0;
command_print(CMD, " TargetName Type Endian TapName State ");
command_print(CMD, "-- ------------------ ---------- ------ ------------------ ------------");
- while (target) {
+ for (struct target *target = all_targets; target; target = target->next, ++index) {
const char *state;
char marker = ' ';
@@ -2861,7 +2825,7 @@ COMMAND_HANDLER(handle_targets_command)
/* keep columns lined up to match the headers above */
command_print(CMD,
"%2d%c %-18s %-10s %-6s %-18s %s",
- target->target_number,
+ index,
marker,
target_name(target),
target_type_name(target),
@@ -2869,7 +2833,6 @@ COMMAND_HANDLER(handle_targets_command)
target->endianness)->name,
target->tap->dotted_name,
state);
- target = target->next;
}
return retval;
@@ -5063,8 +5026,7 @@ void target_handle_event(struct target *target, enum target_event e)
for (teap = target->event_action; teap; teap = teap->next) {
if (teap->event == e) {
- LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s",
- target->target_number,
+ LOG_DEBUG("target: %s (%s) event: %d (%s) action: %s",
target_name(target),
target_type_name(target),
e,
@@ -5849,8 +5811,7 @@ COMMAND_HANDLER(handle_target_event_list)
struct target *target = get_current_target(CMD_CTX);
struct target_event_action *teap = target->event_action;
- command_print(CMD, "Event actions for target (%d) %s\n",
- target->target_number,
+ command_print(CMD, "Event actions for target %s\n",
target_name(target));
command_print(CMD, "%-25s | Body", "Event");
command_print(CMD, "------------------------- | "
@@ -6189,9 +6150,6 @@ static int target_create(struct jim_getopt_info *goi)
/* set empty smp cluster */
target->smp_targets = &empty_smp_targets;
- /* set target number */
- target->target_number = new_target_number();
-
/* allocate memory for each unique target type */
target->type = malloc(sizeof(struct target_type));
if (!target->type) {
diff --git a/src/target/target.h b/src/target/target.h
index abeb8ed51..28a200807 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -115,7 +115,6 @@ enum target_register_class {
struct target {
struct target_type *type; /* target type definition (name, access functions) */
char *cmd_name; /* tcl Name of target */
- int target_number; /* DO NOT USE! field to be removed in 2010 */
struct jtag_tap *tap; /* where on the jtag chain is this */
int32_t coreid; /* which device on the TAP? */
@@ -412,7 +411,6 @@ int target_call_timer_callbacks_now(void);
*/
int64_t target_timer_next_event(void);
-struct target *get_target_by_num(int num);
struct target *get_current_target(struct command_context *cmd_ctx);
struct target *get_current_target_or_null(struct command_context *cmd_ctx);
struct target *get_target(const char *id);
diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
index 2aacc3620..e862fe165 100644
--- a/src/target/xtensa/xtensa.c
+++ b/src/target/xtensa/xtensa.c
@@ -1096,7 +1096,7 @@ int xtensa_assert_reset(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
- LOG_TARGET_DEBUG(target, "target_number=%i, begin", target->target_number);
+ LOG_TARGET_DEBUG(target, " begin");
xtensa_queue_pwr_reg_write(xtensa,
XDMREG_PWRCTL,
PWRCTL_JTAGDEBUGUSE(xtensa) | PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) |
-----------------------------------------------------------------------
Summary of changes:
src/target/target.c | 70 ++++++++++------------------------------------
src/target/target.h | 2 --
src/target/xtensa/xtensa.c | 2 +-
3 files changed, 15 insertions(+), 59 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-24 21:06:59
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 53e67c37abee6506bb06eaf0d50d4d9ce045c0c8 (commit)
from acde409ba07dfd692c2356fabdabab89f6e6a281 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 53e67c37abee6506bb06eaf0d50d4d9ce045c0c8
Author: Thiemo van Engelen <tva...@vi...>
Date: Fri Jun 23 09:29:25 2023 +0200
rtt_server: Add option for a message when client connects
This is useful when using the SEGGER RTT tooling, as the SEGGER RTT
tool J-Link RTT Viewer version 7.84f requires that it receives a
messages immediately after connecting. Otherwise it will give a timeout
and it will not connect.
Change-Id: I9240a1b6a93cd5c0fbd18292afb33b89013d78bf
Signed-off-by: Thiemo van Engelen <tva...@vi...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7752
Tested-by: jenkins
Reviewed-by: zapb <de...@za...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 5d73fd174..e8b207c52 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9448,8 +9448,9 @@ Return a list of all channels and their properties as Tcl list.
The list can be manipulated easily from within scripts.
@end deffn
-@deffn {Command} {rtt server start} port channel
-Start a TCP server on @var{port} for the channel @var{channel}.
+@deffn {Command} {rtt server start} port channel [message]
+Start a TCP server on @var{port} for the channel @var{channel}. When
+@var{message} is not empty, it will be sent to a client when it connects.
@end deffn
@deffn {Command} {rtt server stop} port
diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c
index df2247bac..976915347 100644
--- a/src/server/rtt_server.c
+++ b/src/server/rtt_server.c
@@ -25,6 +25,7 @@
struct rtt_service {
unsigned int channel;
+ char *hello_message;
};
static int read_callback(unsigned int channel, const uint8_t *buffer,
@@ -65,6 +66,9 @@ static int rtt_new_connection(struct connection *connection)
if (ret != ERROR_OK)
return ret;
+ if (service->hello_message)
+ connection_write(connection, service->hello_message, strlen(service->hello_message));
+
return ERROR_OK;
}
@@ -117,16 +121,30 @@ COMMAND_HANDLER(handle_rtt_start_command)
int ret;
struct rtt_service *service;
- if (CMD_ARGC != 2)
+ if (CMD_ARGC < 2 || CMD_ARGC > 3)
return ERROR_COMMAND_SYNTAX_ERROR;
- service = malloc(sizeof(struct rtt_service));
+ service = calloc(1, sizeof(struct rtt_service));
if (!service)
return ERROR_FAIL;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
+ if (CMD_ARGC >= 3) {
+ const char *hello_message = CMD_ARGV[2];
+ size_t hello_length = strlen(hello_message);
+
+ service->hello_message = malloc(hello_length + 2);
+ if (!service->hello_message) {
+ LOG_ERROR("Out of memory");
+ free(service);
+ return ERROR_FAIL;
+ }
+ strcpy(service->hello_message, hello_message);
+ service->hello_message[hello_length] = '\n';
+ service->hello_message[hello_length + 1] = '\0';
+ }
ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service);
if (ret != ERROR_OK) {
@@ -153,7 +171,7 @@ static const struct command_registration rtt_server_subcommand_handlers[] = {
.handler = handle_rtt_start_command,
.mode = COMMAND_ANY,
.help = "Start a RTT server",
- .usage = "<port> <channel>"
+ .usage = "<port> <channel> [message]"
},
{
.name = "stop",
-----------------------------------------------------------------------
Summary of changes:
doc/openocd.texi | 5 +++--
src/server/rtt_server.c | 24 +++++++++++++++++++++---
2 files changed, 24 insertions(+), 5 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:38:59
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via acde409ba07dfd692c2356fabdabab89f6e6a281 (commit)
from 8ccd7827bed2859cd21725a2c857448ab2fcedf6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit acde409ba07dfd692c2356fabdabab89f6e6a281
Author: Marc Schink <de...@za...>
Date: Sun Mar 27 17:55:53 2022 +0200
rtt/tcl: Fix line indentation
Change-Id: I21f8084ca648cfe35f8f4dba078b2227772578a8
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7993
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c
index f949aa1c9..2b8822fce 100644
--- a/src/rtt/tcl.c
+++ b/src/rtt/tcl.c
@@ -17,7 +17,7 @@
COMMAND_HANDLER(handle_rtt_setup_command)
{
-struct rtt_source source;
+ struct rtt_source source;
if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR;
-----------------------------------------------------------------------
Summary of changes:
src/rtt/tcl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:35:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 8ccd7827bed2859cd21725a2c857448ab2fcedf6 (commit)
from 4e5b009a723963228509ae65a60af4df4344a68f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8ccd7827bed2859cd21725a2c857448ab2fcedf6
Author: Marc Schink <de...@za...>
Date: Sat Nov 11 10:28:31 2023 +0100
flash/nor/stmqspi: Use correct command errors
Change-Id: I796b4e350653117bf63d18ad274a1d3d3d1337db
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8004
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c
index c9fc1bffa..a1e1d3411 100644
--- a/src/flash/nor/stmqspi.c
+++ b/src/flash/nor/stmqspi.c
@@ -646,21 +646,21 @@ COMMAND_HANDLER(stmqspi_handle_set)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], stmqspi_info->dev.size_in_bytes);
if (log2u(stmqspi_info->dev.size_in_bytes) < 8) {
command_print(CMD, "stmqspi: device size must be 2^n with n >= 8");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index++], stmqspi_info->dev.pagesize);
if (stmqspi_info->dev.pagesize > stmqspi_info->dev.size_in_bytes ||
(log2u(stmqspi_info->dev.pagesize) < 0)) {
command_print(CMD, "stmqspi: page size must be 2^n and <= device size");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], stmqspi_info->dev.read_cmd);
if ((stmqspi_info->dev.read_cmd != 0x03) &&
(stmqspi_info->dev.read_cmd != 0x13)) {
command_print(CMD, "stmqspi: only 0x03/0x13 READ cmd allowed");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], stmqspi_info->dev.qread_cmd);
@@ -678,7 +678,7 @@ COMMAND_HANDLER(stmqspi_handle_set)
(stmqspi_info->dev.qread_cmd != 0xEE)) {
command_print(CMD, "stmqspi: only 0x0B/0x0C/0x3B/0x3C/"
"0x6B/0x6C/0xBB/0xBC/0xEB/0xEC/0xEE QREAD allowed");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[index++], stmqspi_info->dev.pprog_cmd);
@@ -686,7 +686,7 @@ COMMAND_HANDLER(stmqspi_handle_set)
(stmqspi_info->dev.pprog_cmd != 0x12) &&
(stmqspi_info->dev.pprog_cmd != 0x32)) {
command_print(CMD, "stmqspi: only 0x02/0x12/0x32 PPRG cmd allowed");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (index < CMD_ARGC)
@@ -700,7 +700,7 @@ COMMAND_HANDLER(stmqspi_handle_set)
(stmqspi_info->dev.sectorsize < stmqspi_info->dev.pagesize) ||
(log2u(stmqspi_info->dev.sectorsize) < 0)) {
command_print(CMD, "stmqspi: sector size must be 2^n and <= device size");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (index < CMD_ARGC)
@@ -786,7 +786,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
num_write = CMD_ARGC - 2;
if (num_write > max) {
LOG_ERROR("at most %d bytes may be sent", max);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -811,7 +811,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
if (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) {
if ((num_write & 1) == 0) {
LOG_ERROR("number of data bytes to write must be even in dual mode");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
} else {
@@ -819,12 +819,12 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
if (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) {
if ((num_read & 1) != 0) {
LOG_ERROR("number of bytes to read must be even in dual mode");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
if ((num_write < 1) || (num_write > 5)) {
LOG_ERROR("one cmd and up to four addr bytes must be send when reading");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/stmqspi.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:35:22
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 4e5b009a723963228509ae65a60af4df4344a68f (commit)
from ea07b3c53a5538dfd9732bb9a5a70f1b1c7c7308 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4e5b009a723963228509ae65a60af4df4344a68f
Author: Marc Schink <de...@za...>
Date: Sat Nov 11 10:24:51 2023 +0100
flash/nor/pic32mx: Remove redundant error message
The correct syntax is already suggested due to the return
value used.
While at it, apply some minor code improvements.
Change-Id: I990c0f7a0871f4b1a0fcdd13afc190149302443c
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8003
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c
index 9a1a63412..0f3937cfc 100644
--- a/src/flash/nor/pic32mx.c
+++ b/src/flash/nor/pic32mx.c
@@ -866,10 +866,8 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
struct mips_ejtag *ejtag_info;
int timeout = 10;
- if (CMD_ARGC < 1) {
- command_print(CMD, "pic32mx unlock <bank>");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -932,7 +930,7 @@ static const struct command_registration pic32mx_exec_command_handlers[] = {
.name = "unlock",
.handler = pic32mx_handle_unlock_command,
.mode = COMMAND_EXEC,
- .usage = "[bank_id]",
+ .usage = "bank_id",
.help = "Unlock/Erase entire device.",
},
COMMAND_REGISTRATION_DONE
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/pic32mx.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:34:23
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via ea07b3c53a5538dfd9732bb9a5a70f1b1c7c7308 (commit)
from b310b3ba9d89a059e0edc4f374a31632ec1c58fd (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ea07b3c53a5538dfd9732bb9a5a70f1b1c7c7308
Author: Marc Schink <de...@za...>
Date: Sat Nov 11 10:19:43 2023 +0100
flash/nor/stm32l4x: Remove redundant error messages
The correct syntax is already suggested due to the return
value used.
While at it, apply some minor code improvements.
Change-Id: Id32440cdd531077008abd679add32246c4249eb2
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8001
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index 96757a931..039938512 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -2218,10 +2218,8 @@ err_lock:
COMMAND_HANDLER(stm32l4_handle_mass_erase_command)
{
- if (CMD_ARGC < 1) {
- command_print(CMD, "stm32l4x mass_erase <STM32L4 bank>");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -2239,10 +2237,8 @@ COMMAND_HANDLER(stm32l4_handle_mass_erase_command)
COMMAND_HANDLER(stm32l4_handle_option_read_command)
{
- if (CMD_ARGC < 2) {
- command_print(CMD, "stm32l4x option_read <STM32L4 bank> <option_reg offset>");
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -2266,10 +2262,8 @@ COMMAND_HANDLER(stm32l4_handle_option_read_command)
COMMAND_HANDLER(stm32l4_handle_option_write_command)
{
- if (CMD_ARGC < 3) {
- command_print(CMD, "stm32l4x option_write <STM32L4 bank> <option_reg offset> <value> [mask]");
+ if (CMD_ARGC != 3 && CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -2381,7 +2375,7 @@ COMMAND_HANDLER(stm32l4_handle_lock_command)
{
struct target *target = NULL;
- if (CMD_ARGC < 1)
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
struct flash_bank *bank;
@@ -2416,7 +2410,7 @@ COMMAND_HANDLER(stm32l4_handle_unlock_command)
{
struct target *target = NULL;
- if (CMD_ARGC < 1)
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
struct flash_bank *bank;
@@ -2520,7 +2514,7 @@ COMMAND_HANDLER(stm32l4_handle_wrp_info_command)
COMMAND_HANDLER(stm32l4_handle_otp_command)
{
- if (CMD_ARGC < 2)
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
struct flash_bank *bank;
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/stm32l4x.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:33:40
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via b310b3ba9d89a059e0edc4f374a31632ec1c58fd (commit)
from 738f1e1f72f64839462c6da97ea4ab7eba56e337 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b310b3ba9d89a059e0edc4f374a31632ec1c58fd
Author: Marc Schink <de...@za...>
Date: Sat Nov 11 10:18:53 2023 +0100
flash/nor/stm32h7x: Remove redundant error messages
The correct syntax is already suggested due to the return
value used.
While at it, apply some minor code improvements.
Change-Id: Idf3d7a46ddecd70823e06bc3997f41fcdb8e501f
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8000
Reviewed-by: Tomas Vanek <va...@fb...>
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c
index 21618b39b..c02fae992 100644
--- a/src/flash/nor/stm32h7x.c
+++ b/src/flash/nor/stm32h7x.c
@@ -1080,10 +1080,8 @@ flash_lock:
COMMAND_HANDLER(stm32x_handle_mass_erase_command)
{
- if (CMD_ARGC < 1) {
- command_print(CMD, "stm32h7x mass_erase <bank>");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1101,10 +1099,8 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
COMMAND_HANDLER(stm32x_handle_option_read_command)
{
- if (CMD_ARGC < 2) {
- command_print(CMD, "stm32h7x option_read <bank> <option_reg offset>");
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1126,10 +1122,8 @@ COMMAND_HANDLER(stm32x_handle_option_read_command)
COMMAND_HANDLER(stm32x_handle_option_write_command)
{
- if (CMD_ARGC < 3) {
- command_print(CMD, "stm32h7x option_write <bank> <option_reg offset> <value> [mask]");
+ if (CMD_ARGC != 3 && CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/stm32h7x.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:33:12
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 738f1e1f72f64839462c6da97ea4ab7eba56e337 (commit)
from 1df35d92fe59eac4603f28a2e1c6e5ee1d56e7da (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 738f1e1f72f64839462c6da97ea4ab7eba56e337
Author: Marc Schink <de...@za...>
Date: Sat Nov 11 10:17:45 2023 +0100
flash/nor/stm32f2x: Remove redundant error messages
The correct syntax is already suggested due to the return
value used.
While at it, apply some minor code improvements.
Change-Id: I676e2ebf5714c850a436854a32c2e9d2f181d537
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7999
Tested-by: jenkins
Reviewed-by: Tomas Vanek <va...@fb...>
Reviewed-by: Antonio Borneo <bor...@gm...>
diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c
index 2e0d15897..4e0f73182 100644
--- a/src/flash/nor/stm32f2x.c
+++ b/src/flash/nor/stm32f2x.c
@@ -1540,10 +1540,8 @@ static int stm32x_mass_erase(struct flash_bank *bank)
COMMAND_HANDLER(stm32x_handle_mass_erase_command)
{
- if (CMD_ARGC < 1) {
- command_print(CMD, "stm32x mass_erase <bank>");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1566,10 +1564,8 @@ COMMAND_HANDLER(stm32f2x_handle_options_read_command)
struct flash_bank *bank;
struct stm32x_flash_bank *stm32x_info = NULL;
- if (CMD_ARGC != 1) {
- command_print(CMD, "stm32f2x options_read <bank>");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (retval != ERROR_OK)
@@ -1612,10 +1608,8 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command)
struct stm32x_flash_bank *stm32x_info = NULL;
uint16_t user_options, boot_addr0, boot_addr1, options_mask;
- if (CMD_ARGC < 1) {
- command_print(CMD, "stm32f2x options_write <bank> ...");
+ if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (retval != ERROR_OK)
@@ -1627,19 +1621,14 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command)
stm32x_info = bank->driver_priv;
if (stm32x_info->has_boot_addr) {
- if (CMD_ARGC != 4) {
- command_print(CMD, "stm32f2x options_write <bank> <user_options>"
- " <boot_addr0> <boot_addr1>");
+ if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
+
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], boot_addr0);
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], boot_addr1);
stm32x_info->option_bytes.boot_addr = boot_addr0 | (((uint32_t) boot_addr1) << 16);
- } else {
- if (CMD_ARGC != 2) {
- command_print(CMD, "stm32f2x options_write <bank> <user_options>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
+ } else if (CMD_ARGC != 2) {
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options);
@@ -1674,10 +1663,8 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command)
struct stm32x_flash_bank *stm32x_info = NULL;
uint32_t optcr2_pcrop;
- if (CMD_ARGC != 2) {
- command_print(CMD, "stm32f2x optcr2_write <bank> <optcr2_value>");
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (retval != ERROR_OK)
@@ -1711,10 +1698,8 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command)
COMMAND_HANDLER(stm32x_handle_otp_command)
{
- if (CMD_ARGC < 2) {
- command_print(CMD, "stm32x otp <bank> (enable|disable|show)");
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct flash_bank *bank;
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
@@ -1787,7 +1772,7 @@ static const struct command_registration stm32f2x_exec_command_handlers[] = {
.name = "otp",
.handler = stm32x_handle_otp_command,
.mode = COMMAND_EXEC,
- .usage = "bank_id",
+ .usage = "bank_id (enable|disable|show)",
.help = "OTP (One Time Programmable) memory write enable/disable.",
},
COMMAND_REGISTRATION_DONE
-----------------------------------------------------------------------
Summary of changes:
src/flash/nor/stm32f2x.c | 35 ++++++++++-------------------------
1 file changed, 10 insertions(+), 25 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:32:53
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 1df35d92fe59eac4603f28a2e1c6e5ee1d56e7da (commit)
from dc0f79d45d4ea1fec9f31557478ef0d0cdba1d01 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 1df35d92fe59eac4603f28a2e1c6e5ee1d56e7da
Author: Marc Schink <de...@za...>
Date: Thu Nov 9 10:13:10 2023 +0100
jtag/drivers/rshim: Remove redundant error message
The correct syntax is already suggested due to the return
value used.
Change-Id: I0f4a7f93fdf056e7517c754d6d4ecd7928f1d226
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7992
Reviewed-by: Antonio Borneo <bor...@gm...>
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c
index 6170e86bd..21fc7fd37 100644
--- a/src/jtag/drivers/rshim.c
+++ b/src/jtag/drivers/rshim.c
@@ -434,10 +434,8 @@ static void rshim_disconnect(struct adiv5_dap *dap)
COMMAND_HANDLER(rshim_dap_device_command)
{
- if (CMD_ARGC != 1) {
- command_print(CMD, "Too many arguments");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
free(rshim_dev_path);
rshim_dev_path = strdup(CMD_ARGV[0]);
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/rshim.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|
|
From: openocd-gerrit <ope...@us...> - 2023-11-18 11:32:14
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via dc0f79d45d4ea1fec9f31557478ef0d0cdba1d01 (commit)
from acc1717970d42344812542f72ab7b17349e71242 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit dc0f79d45d4ea1fec9f31557478ef0d0cdba1d01
Author: Marc Schink <de...@za...>
Date: Thu Nov 9 10:12:51 2023 +0100
jtag/drivers/jtag_vpi: Remove redundant error messages
The correct syntax is already suggested due to the return
value used.
Change-Id: I971a579014c1eaf13b1932f7fa87c020a8eba69c
Signed-off-by: Marc Schink <de...@za...>
Reviewed-on: https://review.openocd.org/c/openocd/+/7971
Reviewed-by: Antonio Borneo <bor...@gm...>
Reviewed-by: Tomas Vanek <va...@fb...>
Tested-by: jenkins
diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c
index f19e9ab44..c2b3b0808 100644
--- a/src/jtag/drivers/jtag_vpi.c
+++ b/src/jtag/drivers/jtag_vpi.c
@@ -593,10 +593,8 @@ static int jtag_vpi_quit(void)
COMMAND_HANDLER(jtag_vpi_set_port)
{
- if (CMD_ARGC == 0) {
- LOG_ERROR("Command \"jtag_vpi set_port\" expects 1 argument (TCP port number)");
+ if (CMD_ARGC == 0)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port);
LOG_INFO("jtag_vpi: server port set to %u", server_port);
@@ -607,10 +605,8 @@ COMMAND_HANDLER(jtag_vpi_set_port)
COMMAND_HANDLER(jtag_vpi_set_address)
{
- if (CMD_ARGC == 0) {
- LOG_ERROR("Command \"jtag_vpi set_address\" expects 1 argument (IP address)");
+ if (CMD_ARGC == 0)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
free(server_address);
server_address = strdup(CMD_ARGV[0]);
@@ -621,10 +617,8 @@ COMMAND_HANDLER(jtag_vpi_set_address)
COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler)
{
- if (CMD_ARGC != 1) {
- LOG_ERROR("Command \"jtag_vpi stop_sim_on_exit\" expects 1 argument (on|off)");
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit);
return ERROR_OK;
-----------------------------------------------------------------------
Summary of changes:
src/jtag/drivers/jtag_vpi.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|