aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/loaders/trampoline/espressif/xtensa/Makefile38
-rw-r--r--contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.S41
-rw-r--r--contrib/loaders/trampoline/espressif/xtensa/esp_xtensa_stub_tramp_win.inc3
-rw-r--r--src/target/espressif/Makefile.am2
-rw-r--r--src/target/espressif/esp.c10
-rw-r--r--src/target/espressif/esp.h2
-rw-r--r--src/target/espressif/esp32.c4
-rw-r--r--src/target/espressif/esp32s2.c4
-rw-r--r--src/target/espressif/esp32s3.c4
-rw-r--r--src/target/espressif/esp_xtensa.c8
-rw-r--r--src/target/espressif/esp_xtensa_algorithm.c140
-rw-r--r--src/target/espressif/esp_xtensa_algorithm.h19
12 files changed, 274 insertions, 1 deletions
diff --git a/contrib/loaders/trampoline/espressif/xtensa/Makefile b/contrib/loaders/trampoline/espressif/xtensa/Makefile
new file mode 100644
index 0000000..bd1f630
--- /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 0000000..e0c827d
--- /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 0000000..1657223
--- /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 1fbd926..cf82ee9 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 9583d64..600f6d7 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 3ba2b8b..6e0a2d2 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 b510f28..324aa39 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 dadc130..2abde47 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 5036956..22e1630 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 0bd2cdd..11895d2 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 0000000..68005cb
--- /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(&params[0], "a0", 32, PARAM_OUT); /*TODO: move to tramp */
+ init_reg_param(&params[1], "a1", 32, PARAM_OUT);
+ init_reg_param(&params[2], "a8", 32, PARAM_OUT);
+ init_reg_param(&params[3], "windowbase", 32, PARAM_OUT); /*TODO: move to tramp */
+ init_reg_param(&params[4], "windowstart", 32, PARAM_OUT); /*TODO: move to tramp */
+ init_reg_param(&params[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 0000000..36fa1a3
--- /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 */