target/espressif: read entry addresses of pre-defined stub functions
[openocd.git] / src / target / espressif / esp_xtensa.c
index 3dfcc0fb2c5642e63045ce6c3e2c5a27c1afa6c0..0bd2cdd9dd36968c1a53a82e7aa06fcae1e6595a 100644 (file)
 #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)
 {
-       /* will be used in the next patches */
+       /* 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;
 }
 
@@ -45,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) */
 }
@@ -56,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)

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)