aboutsummaryrefslogtreecommitdiff
path: root/src/target/espressif/esp_xtensa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/espressif/esp_xtensa.c')
-rw-r--r--src/target/espressif/esp_xtensa.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c
index 44764ae..0bd2cdd 100644
--- a/src/target/espressif/esp_xtensa.c
+++ b/src/target/espressif/esp_xtensa.c
@@ -17,6 +17,49 @@
#include "esp_xtensa.h"
#include "esp_semihosting.h"
+#define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_) \
+ do { \
+ uint32_t __internal_val = (_e_); \
+ if (!xtensa_data_addr_valid(target, __internal_val)) { \
+ LOG_ERROR("No valid stub data entry found (0x%" PRIx32 ")!", __internal_val); \
+ return; \
+ } \
+ } while (0)
+
+#define ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(_e_) \
+ do { \
+ uint32_t __internal_val = (_e_); \
+ if (__internal_val == 0) { \
+ LOG_ERROR("No valid stub code entry found (0x%" PRIx32 ")!", __internal_val); \
+ return; \
+ } \
+ } while (0)
+
+static void esp_xtensa_dbgstubs_info_update(struct target *target);
+static void esp_xtensa_dbgstubs_addr_check(struct target *target);
+
+static int esp_xtensa_dbgstubs_restore(struct target *target)
+{
+ struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+
+ if (esp_xtensa->esp.dbg_stubs.base == 0)
+ return ERROR_OK;
+
+ LOG_TARGET_INFO(target, "Restore debug stubs address %" PRIx32, esp_xtensa->esp.dbg_stubs.base);
+ int res = esp_xtensa_apptrace_status_reg_write(target, esp_xtensa->esp.dbg_stubs.base);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to write trace status (%d)!", res);
+ return res;
+ }
+ return ERROR_OK;
+}
+int esp_xtensa_on_halt(struct target *target)
+{
+ /* debug stubs can be used in HALTED state only, so it is OK to get info about them here */
+ esp_xtensa_dbgstubs_info_update(target);
+ return ERROR_OK;
+}
+
int esp_xtensa_init_arch_info(struct target *target,
struct esp_xtensa_common *esp_xtensa,
struct xtensa_debug_module_config *dm_cfg,
@@ -39,6 +82,11 @@ void esp_xtensa_target_deinit(struct target *target)
{
LOG_DEBUG("start");
+ if (target_was_examined(target)) {
+ int ret = esp_xtensa_dbgstubs_restore(target);
+ if (ret != ERROR_OK)
+ return;
+ }
xtensa_target_deinit(target);
free(target_to_esp_xtensa(target)); /* same as free(xtensa) */
}
@@ -50,7 +98,68 @@ int esp_xtensa_arch_state(struct target *target)
int esp_xtensa_poll(struct target *target)
{
- return xtensa_poll(target);
+ struct xtensa *xtensa = target_to_xtensa(target);
+ struct esp_xtensa_common *esp_xtensa_common = target_to_esp_xtensa(target);
+
+ int ret = xtensa_poll(target);
+
+ if (xtensa_dm_power_status_get(&xtensa->dbg_mod) & PWRSTAT_COREWASRESET(xtensa)) {
+ LOG_TARGET_DEBUG(target, "Clear debug stubs info");
+ memset(&esp_xtensa_common->esp.dbg_stubs, 0, sizeof(esp_xtensa_common->esp.dbg_stubs));
+ }
+ if (target->state != TARGET_DEBUG_RUNNING)
+ esp_xtensa_dbgstubs_addr_check(target);
+ return ret;
+}
+
+static void esp_xtensa_dbgstubs_addr_check(struct target *target)
+{
+ struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+ uint32_t vec_addr = 0;
+
+ if (esp_xtensa->esp.dbg_stubs.base != 0)
+ return;
+
+ int res = esp_xtensa_apptrace_status_reg_read(target, &vec_addr);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to read debug stubs address location (%d)!", res);
+ return;
+ }
+ if (xtensa_data_addr_valid(target, vec_addr)) {
+ LOG_TARGET_INFO(target, "Detected debug stubs @ %" PRIx32, vec_addr);
+ res = esp_xtensa_apptrace_status_reg_write(target, 0);
+ if (res != ERROR_OK)
+ LOG_ERROR("Failed to clear debug stubs address location (%d)!", res);
+ esp_xtensa->esp.dbg_stubs.base = vec_addr;
+ }
+}
+
+static void esp_xtensa_dbgstubs_info_update(struct target *target)
+{
+ struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+
+ if (esp_xtensa->esp.dbg_stubs.base == 0 || esp_xtensa->esp.dbg_stubs.entries_count != 0)
+ return;
+
+ int res = esp_dbgstubs_table_read(target, &esp_xtensa->esp.dbg_stubs);
+ if (res != ERROR_OK)
+ return;
+ if (esp_xtensa->esp.dbg_stubs.entries_count == 0)
+ return;
+
+ /* read debug stubs descriptor */
+ ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(esp_xtensa->esp.dbg_stubs.entries[ESP_DBG_STUB_DESC]);
+ res = target_read_buffer(target, esp_xtensa->esp.dbg_stubs.entries[ESP_DBG_STUB_DESC],
+ sizeof(struct esp_dbg_stubs_desc),
+ (uint8_t *)&esp_xtensa->esp.dbg_stubs.desc);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to read debug stubs descriptor (%d)!", res);
+ return;
+ }
+ ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.tramp_addr);
+ ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(esp_xtensa->esp.dbg_stubs.desc.min_stack_addr);
+ ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.data_alloc);
+ ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(esp_xtensa->esp.dbg_stubs.desc.data_free);
}
int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint)