diff options
Diffstat (limited to 'src/target/espressif')
-rw-r--r-- | src/target/espressif/esp32.c | 3 | ||||
-rw-r--r-- | src/target/espressif/esp32_apptrace.c | 8 | ||||
-rw-r--r-- | src/target/espressif/esp32s2.c | 5 | ||||
-rw-r--r-- | src/target/espressif/esp32s3.c | 4 | ||||
-rw-r--r-- | src/target/espressif/esp_algorithm.h | 125 | ||||
-rw-r--r-- | src/target/espressif/esp_xtensa.c | 72 | ||||
-rw-r--r-- | src/target/espressif/esp_xtensa.h | 3 | ||||
-rw-r--r-- | src/target/espressif/esp_xtensa_apptrace.c | 2 | ||||
-rw-r--r-- | src/target/espressif/esp_xtensa_smp.c | 19 | ||||
-rw-r--r-- | src/target/espressif/esp_xtensa_smp.h | 10 |
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); |