aboutsummaryrefslogtreecommitdiff
path: root/src/target/espressif
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/espressif')
-rw-r--r--src/target/espressif/esp32.c3
-rw-r--r--src/target/espressif/esp32_apptrace.c8
-rw-r--r--src/target/espressif/esp32s2.c5
-rw-r--r--src/target/espressif/esp32s3.c4
-rw-r--r--src/target/espressif/esp_algorithm.h125
-rw-r--r--src/target/espressif/esp_xtensa.c72
-rw-r--r--src/target/espressif/esp_xtensa.h3
-rw-r--r--src/target/espressif/esp_xtensa_apptrace.c2
-rw-r--r--src/target/espressif/esp_xtensa_smp.c19
-rw-r--r--src/target/espressif/esp_xtensa_smp.h10
10 files changed, 162 insertions, 89 deletions
diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c
index 324aa39..4deb5e0 100644
--- a/src/target/espressif/esp32.c
+++ b/src/target/espressif/esp32.c
@@ -175,7 +175,8 @@ static int esp32_soc_reset(struct target *target)
LOG_DEBUG("Resuming the target");
xtensa = target_to_xtensa(target);
xtensa->suppress_dsr_errors = true;
- res = xtensa_resume(target, 0, ESP32_RTC_SLOW_MEM_BASE + 4, 0, 0);
+ res = xtensa_resume(target, false, ESP32_RTC_SLOW_MEM_BASE + 4, false,
+ false);
xtensa->suppress_dsr_errors = false;
if (res != ERROR_OK) {
LOG_ERROR("Failed to run stub (%d)!", res);
diff --git a/src/target/espressif/esp32_apptrace.c b/src/target/espressif/esp32_apptrace.c
index 125f366..3070960 100644
--- a/src/target/espressif/esp32_apptrace.c
+++ b/src/target/espressif/esp32_apptrace.c
@@ -649,7 +649,7 @@ static int esp32_apptrace_wait4halt(struct esp32_apptrace_cmd_ctx *ctx, struct t
if (res != ERROR_OK)
return res;
if (target->state == TARGET_HALTED) {
- LOG_USER("%s: HALTED", target->cmd_name);
+ LOG_TARGET_USER(target, "HALTED");
break;
}
alive_sleep(500);
@@ -708,7 +708,7 @@ int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx,
}
while (stat) {
/* allow this CPU to leave ERI write critical section */
- res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
+ res = target_resume(ctx->cpus[k], true, 0, true, false);
if (res != ERROR_OK) {
LOG_ERROR("Failed to resume target (%d)!", res);
breakpoint_remove(ctx->cpus[k], bp_addr);
@@ -796,7 +796,7 @@ static int esp32_apptrace_connect_targets(struct esp32_apptrace_cmd_ctx *ctx,
/* in SMP mode we need to call target_resume for one core only */
continue;
}
- res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
+ res = target_resume(ctx->cpus[k], true, 0, true, false);
if (res != ERROR_OK) {
command_print(ctx->cmd, "Failed to resume target (%d)!", res);
return res;
@@ -1352,7 +1352,7 @@ static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx)
/* in SMP mode we need to call target_resume for one core only */
continue;
}
- res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
+ res = target_resume(ctx->cpus[k], true, 0, true, false);
if (res != ERROR_OK) {
LOG_ERROR("sysview: Failed to resume target '%s' (%d)!", target_name(ctx->cpus[k]), res);
return res;
diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c
index 2abde47..4f3914f 100644
--- a/src/target/espressif/esp32s2.c
+++ b/src/target/espressif/esp32s2.c
@@ -370,7 +370,8 @@ static int esp32s2_on_halt(struct target *target)
return ret;
}
-static int esp32s2_step(struct target *target, int current, target_addr_t address, int handle_breakpoints)
+static int esp32s2_step(struct target *target, bool current,
+ target_addr_t address, bool handle_breakpoints)
{
int ret = xtensa_step(target, current, address, handle_breakpoints);
if (ret == ERROR_OK) {
@@ -397,7 +398,7 @@ static int esp32s2_poll(struct target *target)
if (ret == ERROR_OK && esp_xtensa->semihost.need_resume) {
esp_xtensa->semihost.need_resume = false;
/* Resume xtensa_resume will handle BREAK instruction. */
- ret = target_resume(target, 1, 0, 1, 0);
+ ret = target_resume(target, true, 0, true, false);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to resume target");
return ret;
diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c
index 22e1630..7507c11 100644
--- a/src/target/espressif/esp32s3.c
+++ b/src/target/espressif/esp32s3.c
@@ -175,7 +175,8 @@ static int esp32s3_soc_reset(struct target *target)
LOG_DEBUG("Resuming the target");
xtensa = target_to_xtensa(target);
xtensa->suppress_dsr_errors = true;
- res = xtensa_resume(target, 0, ESP32_S3_RTC_SLOW_MEM_BASE + 4, 0, 0);
+ res = xtensa_resume(target, false, ESP32_S3_RTC_SLOW_MEM_BASE + 4, false,
+ false);
xtensa->suppress_dsr_errors = false;
if (res != ERROR_OK) {
LOG_ERROR("Failed to run stub (%d)!", res);
@@ -421,4 +422,5 @@ struct target_type esp32s3_target = {
.deinit_target = esp_xtensa_target_deinit,
.commands = esp32s3_command_handlers,
+ .profiling = esp_xtensa_profiling,
};
diff --git a/src/target/espressif/esp_algorithm.h b/src/target/espressif/esp_algorithm.h
index 11d2757..185234f 100644
--- a/src/target/espressif/esp_algorithm.h
+++ b/src/target/espressif/esp_algorithm.h
@@ -36,11 +36,13 @@
* 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)
+ * 3) If a user specifies an initializer func esp_algorithm_run_data::usr_func_init
+ * it is called just before the stub starts.
+ * 4) If user specifies stub communication func esp_algorithm_run_data::usr_func
+ * (@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,
+ * 6) If the user specified arguments cleanup func esp_algorithm_run_data::usr_func_done,
* it is called just after the stub finishes.
*
* There are two options to run code on target under OpenOCD control:
@@ -190,60 +192,6 @@ struct esp_algorithm_reg_args {
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);
@@ -283,14 +231,61 @@ struct esp_algorithm_run_data {
};
/** 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;
+
+ /**
+ * @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.
+ */
+ int (*usr_func)(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 usr_func.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX.
+ */
+ int (*usr_func_init)(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 usr_func.
+ *
+ * @return ERROR_OK on success, otherwise ERROR_XXX.
+ */
+ void (*usr_func_done)(struct target *target,
+ struct esp_algorithm_run_data *run,
+ void *usr_arg);
+
+ /**
+ * @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.
+ */
+ int (*algo_func)(struct target *target, struct esp_algorithm_run_data *run, void *arg);
+
/** HW specific API */
const struct esp_algorithm_hw *hw;
};
diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c
index 11895d2..4cadcb3 100644
--- a/src/target/espressif/esp_xtensa.c
+++ b/src/target/espressif/esp_xtensa.c
@@ -179,3 +179,75 @@ int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *break
return xtensa_breakpoint_remove(target, breakpoint);
/* flash breakpoints will be handled in another patch */
}
+
+int esp_xtensa_profiling(struct target *target, uint32_t *samples,
+ uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
+{
+ struct timeval timeout, now;
+ struct xtensa *xtensa = target_to_xtensa(target);
+ int retval = ERROR_OK;
+ int res;
+
+ /* Vary samples per pass to avoid sampling a periodic function periodically */
+ #define MIN_PASS 200
+ #define MAX_PASS 1000
+
+ gettimeofday(&timeout, NULL);
+ timeval_add_time(&timeout, seconds, 0);
+
+ uint8_t buf[sizeof(uint32_t) * MAX_PASS];
+
+ /* Capture one sample to verify the register is present and working */
+ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf);
+ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
+ if (res != ERROR_OK) {
+ LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go");
+ return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
+ } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) {
+ LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go");
+ return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
+ }
+
+ LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can...");
+
+ /* Make sure the target is running */
+ target_poll(target);
+ if (target->state == TARGET_HALTED)
+ retval = target_resume(target, true, 0, false, false);
+
+ if (retval != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Error while resuming target");
+ return retval;
+ }
+
+ uint32_t sample_count = 0;
+
+ for (;;) {
+ uint32_t remaining = max_num_samples - sample_count;
+ uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS;
+ this_pass = this_pass > remaining ? remaining : this_pass;
+ for (uint32_t i = 0; i < this_pass; ++i)
+ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t));
+ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
+ if (res != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!");
+ return res;
+ }
+
+ for (uint32_t i = 0; i < this_pass; ++i) {
+ uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32);
+ samples[sample_count++] = sample32;
+ }
+ gettimeofday(&now, NULL);
+ if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) {
+ LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count);
+ break;
+ }
+ }
+
+ *num_samples = sample_count;
+ return retval;
+
+ #undef MIN_PASS
+ #undef MAX_PASS
+}
diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h
index 00f67a3..56c903f 100644
--- a/src/target/espressif/esp_xtensa.h
+++ b/src/target/espressif/esp_xtensa.h
@@ -37,6 +37,9 @@ void esp_xtensa_queue_tdi_idle(struct target *target);
int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
int esp_xtensa_poll(struct target *target);
+int esp_xtensa_profiling(struct target *target, uint32_t *samples,
+ uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
+
int esp_xtensa_on_halt(struct target *target);
#endif /* OPENOCD_TARGET_ESP_XTENSA_H */
diff --git a/src/target/espressif/esp_xtensa_apptrace.c b/src/target/espressif/esp_xtensa_apptrace.c
index 5741ab0..313f6ce 100644
--- a/src/target/espressif/esp_xtensa_apptrace.c
+++ b/src/target/espressif/esp_xtensa_apptrace.c
@@ -277,7 +277,7 @@ static int esp_xtensa_swdbg_activate(struct target *target, int enab)
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
- LOG_ERROR("%s: writing DCR failed!", target->cmd_name);
+ LOG_TARGET_ERROR(target, "writing DCR failed");
return res;
}
diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c
index c49146d..b9e2156 100644
--- a/src/target/espressif/esp_xtensa_smp.c
+++ b/src/target/espressif/esp_xtensa_smp.c
@@ -218,7 +218,7 @@ int esp_xtensa_smp_poll(struct target *target)
!esp_xtensa_smp->other_core_does_resume) {
esp_xtensa->semihost.need_resume = false;
/* Resume xtensa_resume will handle BREAK instruction. */
- ret = target_resume(target, 1, 0, 1, 0);
+ ret = target_resume(target, true, 0, true, false);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to resume target");
return ret;
@@ -229,7 +229,7 @@ int esp_xtensa_smp_poll(struct target *target)
/* check whether any core polled by esp_xtensa_smp_update_halt_gdb() requested resume */
if (target->smp && other_core_resume_req) {
/* Resume xtensa_resume will handle BREAK instruction. */
- ret = target_resume(target, 1, 0, 1, 0);
+ ret = target_resume(target, true, 0, true, false);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to resume target");
return ret;
@@ -334,8 +334,7 @@ static inline int esp_xtensa_smp_smpbreak_restore(struct target *target, uint32_
}
static int esp_xtensa_smp_resume_cores(struct target *target,
- int handle_breakpoints,
- int debug_execution)
+ bool handle_breakpoints, bool debug_execution)
{
struct target_list *head;
struct target *curr;
@@ -348,7 +347,7 @@ static int esp_xtensa_smp_resume_cores(struct target *target,
if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) {
/* resume current address, not in SMP mode */
curr->smp = 0;
- int res = esp_xtensa_smp_resume(curr, 1, 0, handle_breakpoints, debug_execution);
+ int res = esp_xtensa_smp_resume(curr, true, 0, handle_breakpoints, debug_execution);
curr->smp = 1;
if (res != ERROR_OK)
return res;
@@ -358,10 +357,10 @@ static int esp_xtensa_smp_resume_cores(struct target *target,
}
int esp_xtensa_smp_resume(struct target *target,
- int current,
+ bool current,
target_addr_t address,
- int handle_breakpoints,
- int debug_execution)
+ bool handle_breakpoints,
+ bool debug_execution)
{
int res;
uint32_t smp_break;
@@ -420,9 +419,9 @@ int esp_xtensa_smp_resume(struct target *target,
}
int esp_xtensa_smp_step(struct target *target,
- int current,
+ bool current,
target_addr_t address,
- int handle_breakpoints)
+ bool handle_breakpoints)
{
int res;
uint32_t smp_break = 0;
diff --git a/src/target/espressif/esp_xtensa_smp.h b/src/target/espressif/esp_xtensa_smp.h
index 39afd8a..ec074c1 100644
--- a/src/target/espressif/esp_xtensa_smp.h
+++ b/src/target/espressif/esp_xtensa_smp.h
@@ -27,14 +27,14 @@ struct esp_xtensa_smp_common {
int esp_xtensa_smp_poll(struct target *target);
int esp_xtensa_smp_resume(struct target *target,
- int current,
+ bool current,
target_addr_t address,
- int handle_breakpoints,
- int debug_execution);
+ bool handle_breakpoints,
+ bool debug_execution);
int esp_xtensa_smp_step(struct target *target,
- int current,
+ bool current,
target_addr_t address,
- int handle_breakpoints);
+ bool handle_breakpoints);
int esp_xtensa_smp_assert_reset(struct target *target);
int esp_xtensa_smp_deassert_reset(struct target *target);
int esp_xtensa_smp_soft_reset_halt(struct target *target);