Skip to content

Commit

Permalink
target/espressif: fix apptrace init error on riscv chips
Browse files Browse the repository at this point in the history
  • Loading branch information
erhankur committed Jul 2, 2024
1 parent 7faa516 commit eab53c1
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 11 deletions.
18 changes: 18 additions & 0 deletions src/target/espressif/esp32c2.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
/* ASSIST_DEBUG registers */
#define ESP32C2_ASSIST_DEBUG_CPU0_MON_REG 0x600CE000

/* memory map */
#define ESP32C2_IRAM_LOW 0x4037C000
#define ESP32C2_IRAM_HIGH 0x403C0000
#define ESP32C2_DRAM_LOW 0x3FCA0000
#define ESP32C2_DRAM_HIGH 0x3FCE0000

enum esp32c2_reset_reason {
ESP32C2_CHIP_POWER_ON_RESET = 0x01, /* Power on reset */
ESP32C2_CORE_SW_RESET = 0x03, /* Software resets the digital core by RTC_CNTL_SW_SYS_RST */
Expand Down Expand Up @@ -94,6 +100,16 @@ static void esp32c2_print_reset_reason(struct target *target, uint32_t reset_rea
esp32c2_get_reset_reason(reset_reason_reg_val));
}

static bool esp32c2_is_iram_address(target_addr_t addr)
{
return addr >= ESP32C2_IRAM_LOW && addr < ESP32C2_IRAM_HIGH;
}

static bool esp32c2_is_dram_address(target_addr_t addr)
{
return addr >= ESP32C2_DRAM_LOW && addr < ESP32C2_DRAM_HIGH;
}

static const struct esp_semihost_ops esp32c2_semihost_ops = {
.prepare = NULL,
.post_reset = esp_semihosting_post_reset
Expand Down Expand Up @@ -122,6 +138,8 @@ static int esp32c2_target_create(struct target *target, Jim_Interp *interp)
esp_riscv->print_reset_reason = &esp32c2_print_reset_reason;
esp_riscv->existent_csrs = NULL;
esp_riscv->existent_csr_size = 0;
esp_riscv->is_dram_address = esp32c2_is_dram_address;
esp_riscv->is_iram_address = esp32c2_is_iram_address;

if (esp_riscv_alloc_trigger_addr(target) != ERROR_OK)
return ERROR_FAIL;
Expand Down
17 changes: 17 additions & 0 deletions src/target/espressif/esp32c3.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
/* ASSIST_DEBUG registers */
#define ESP32C3_ASSIST_DEBUG_CPU0_MON_REG 0x600CE000

#define ESP32C3_IRAM_LOW 0x4037C000
#define ESP32C3_IRAM_HIGH 0x403E0000
#define ESP32C3_DRAM_LOW 0x3FC80000
#define ESP32C3_DRAM_HIGH 0x3FCE0000

enum esp32c3_reset_reason {
ESP32C3_CHIP_POWER_ON_RESET = 0x01, /* Power on reset */
ESP32C3_CHIP_BROWN_OUT_RESET = 0x01, /* VDD voltage is not stable and resets the chip */
Expand Down Expand Up @@ -111,6 +116,16 @@ static void esp32c3_print_reset_reason(struct target *target, uint32_t reset_rea
esp32c3_get_reset_reason(reset_reason_reg_val));
}

static bool esp32c3_is_iram_address(target_addr_t addr)
{
return addr >= ESP32C3_IRAM_LOW && addr < ESP32C3_IRAM_HIGH;
}

static bool esp32c3_is_dram_address(target_addr_t addr)
{
return addr >= ESP32C3_DRAM_LOW && addr < ESP32C3_DRAM_HIGH;
}

static const struct esp_semihost_ops esp32c3_semihost_ops = {
.prepare = NULL,
.post_reset = esp_semihosting_post_reset
Expand Down Expand Up @@ -139,6 +154,8 @@ static int esp32c3_target_create(struct target *target, Jim_Interp *interp)
esp_riscv->print_reset_reason = &esp32c3_print_reset_reason;
esp_riscv->existent_csrs = NULL;
esp_riscv->existent_csr_size = 0;
esp_riscv->is_dram_address = esp32c3_is_dram_address;
esp_riscv->is_iram_address = esp32c3_is_iram_address;

if (esp_riscv_alloc_trigger_addr(target) != ERROR_OK)
return ERROR_FAIL;
Expand Down
10 changes: 10 additions & 0 deletions src/target/espressif/esp32c6.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
/* ASSIST_DEBUG registers */
#define ESP32C6_ASSIST_DEBUG_CPU0_MON_REG 0x600C2000

#define ESP32C6_DRAM_LOW 0x40800000
#define ESP32C6_DRAM_HIGH 0x40880000

enum esp32c6_reset_reason {
ESP32C6_CHIP_POWER_ON_RESET = 0x01, /* Power on reset */
ESP32C6_CHIP_BROWN_OUT_RESET = 0x01, /* VDD voltage is not stable and resets the chip */
Expand Down Expand Up @@ -109,6 +112,11 @@ static void esp32c6_print_reset_reason(struct target *target, uint32_t reset_rea
esp32c6_get_reset_reason(reset_reason_reg_val));
}

static bool esp32c6_is_idram_address(target_addr_t addr)
{
return addr >= ESP32C6_DRAM_LOW && addr < ESP32C6_DRAM_HIGH;
}

static const struct esp_semihost_ops esp32c6_semihost_ops = {
.prepare = NULL,
.post_reset = esp_semihosting_post_reset
Expand Down Expand Up @@ -148,6 +156,8 @@ static int esp32c6_target_create(struct target *target, Jim_Interp *interp)
esp_riscv->print_reset_reason = &esp32c6_print_reset_reason;
esp_riscv->existent_csrs = esp32c6_csrs;
esp_riscv->existent_csr_size = ARRAY_SIZE(esp32c6_csrs);
esp_riscv->is_dram_address = esp32c6_is_idram_address;
esp_riscv->is_iram_address = esp32c6_is_idram_address;

if (esp_riscv_alloc_trigger_addr(target) != ERROR_OK)
return ERROR_FAIL;
Expand Down
10 changes: 10 additions & 0 deletions src/target/espressif/esp32h2.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
/* ASSIST_DEBUG registers */
#define ESP32H2_ASSIST_DEBUG_CPU0_MON_REG 0x600C2000

#define ESP32H2_DRAM_LOW 0x40800000
#define ESP32H2_DRAM_HIGH 0x40850000

enum esp32h2_reset_reason {
ESP32H2_CHIP_POWER_ON_RESET = 0x01, /* Vbat power on reset */
ESP32H2_RTC_SW_SYS_RESET = 0x03, /* Software reset digital core */
Expand Down Expand Up @@ -113,6 +116,11 @@ static void esp32h2_print_reset_reason(struct target *target, uint32_t reset_rea
esp32h2_get_reset_reason(reset_reason_reg_val));
}

static bool esp32h2_is_idram_address(target_addr_t addr)
{
return addr >= ESP32H2_DRAM_LOW && addr < ESP32H2_DRAM_HIGH;
}

static const struct esp_semihost_ops esp32h2_semihost_ops = {
.prepare = NULL,
.post_reset = esp_semihosting_post_reset
Expand Down Expand Up @@ -152,6 +160,8 @@ static int esp32h2_target_create(struct target *target, Jim_Interp *interp)
esp_riscv->print_reset_reason = &esp32h2_print_reset_reason;
esp_riscv->existent_csrs = esp32h2_csrs;
esp_riscv->existent_csr_size = ARRAY_SIZE(esp32h2_csrs);
esp_riscv->is_dram_address = esp32h2_is_idram_address;
esp_riscv->is_iram_address = esp32h2_is_idram_address;

if (esp_riscv_alloc_trigger_addr(target) != ERROR_OK)
return ERROR_FAIL;
Expand Down
30 changes: 26 additions & 4 deletions src/target/espressif/esp32p4.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
(addr) < (ESP32P4_IRAM0_NON_CACHEABLE_ADDRESS_HIGH))
#define ESP32P4_ADDRESS_IS_L2MEM(addr) (ESP32P4_ADDRESS_IS_NONCACHEABLE(addr) || ESP32P4_ADDRESS_IS_CACHEABLE(addr))

#define ESP32P4_RESERVED_ADDRESS_LOW 0x00000000U
#define ESP32P4_RESERVED_ADDRESS_HIGH 0x300FFFFFU

/* max supported hw breakpoint and watchpoint count */
#define ESP32P4_BP_NUM 3
#define ESP32P4_WP_NUM 3
Expand Down Expand Up @@ -143,6 +146,16 @@ static void esp32p4_print_reset_reason(struct target *target, uint32_t reset_rea
esp32p4_get_reset_reason(reset_reason_reg_val, ESP32P4_HP_CORE_RESET_CAUSE_SHIFT));
}

static bool esp32p4_is_l2mem_address(target_addr_t addr)
{
return ESP32P4_ADDRESS_IS_L2MEM(addr);
}

static bool esp32p4_is_reserved_address(target_addr_t addr)
{
return addr < ESP32P4_RESERVED_ADDRESS_HIGH;
}

static const struct esp_semihost_ops esp32p4_semihost_ops = {
.prepare = NULL,
.post_reset = esp_semihosting_post_reset
Expand Down Expand Up @@ -190,6 +203,8 @@ static int esp32p4_target_create(struct target *target, Jim_Interp *interp)
esp_riscv->print_reset_reason = &esp32p4_print_reset_reason;
esp_riscv->existent_csrs = esp32p4_csrs;
esp_riscv->existent_csr_size = ARRAY_SIZE(esp32p4_csrs);
esp_riscv->is_dram_address = esp32p4_is_l2mem_address;
esp_riscv->is_iram_address = esp32p4_is_l2mem_address;

if (esp_riscv_alloc_trigger_addr(target) != ERROR_OK)
return ERROR_FAIL;
Expand Down Expand Up @@ -225,8 +240,7 @@ static inline uint32_t esp32p4_make_non_cachable_addr(uint32_t address)
{
return (address & ESP32P4_NON_CACHEABLE_OFFSET) ? (address + ESP32P4_NON_CACHEABLE_OFFSET) : address;
}
// We will call sync cache only at running state before/after accessing memory from sysbus.
// Halted state will be handled by execute_fence() before/after accessing memory from progbuf.

static int esp32p4_sync_cache(struct target *target, uint32_t op)
{
int res;
Expand All @@ -251,13 +265,20 @@ static int esp32p4_sync_cache(struct target *target, uint32_t op)
static int esp32p4_read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
if (target->state == TARGET_RUNNING && ESP32P4_ADDRESS_IS_L2MEM(address)) {
/* TODO: check that do we still need the cache related things */
if (ESP32P4_ADDRESS_IS_L2MEM(address)) {
int res = esp32p4_sync_cache(target, ESP32P4_CACHE_SYNC_WRITEBACK);
if (res != ERROR_OK)
LOG_TARGET_WARNING(target, "Cache writeback failed! Read main memory anyway.");
address = esp32p4_make_non_cachable_addr(address);
}

if (esp32p4_is_reserved_address(address)) {
/* TODO: OCD-976 */
memset(buffer, 0, size * count);
return ERROR_OK;
}

return esp_riscv_read_memory(target, address, size, count, buffer);
}

Expand All @@ -266,7 +287,8 @@ static int esp32p4_write_memory(struct target *target, target_addr_t address,
{
bool cache_invalidate = false;

if (target->state == TARGET_RUNNING && ESP32P4_ADDRESS_IS_L2MEM(address)) {
/* TODO: check that do we still need the cache related things */
if (ESP32P4_ADDRESS_IS_L2MEM(address)) {
/* write to main memory and invalidate cache */
esp32p4_sync_cache(target, ESP32P4_CACHE_SYNC_WRITEBACK);
address = esp32p4_make_non_cachable_addr(address);
Expand Down
2 changes: 2 additions & 0 deletions src/target/espressif/esp_riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ struct esp_riscv_common {
bool was_reset;
const char **existent_csrs;
size_t existent_csr_size;
bool (*is_iram_address)(target_addr_t addr);
bool (*is_dram_address)(target_addr_t addr);
};

static inline struct esp_riscv_common *target_to_esp_riscv(const struct target *target)
Expand Down
4 changes: 2 additions & 2 deletions src/target/espressif/esp_riscv_apptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ int esp_riscv_apptrace_info_init(struct target *target, target_addr_t ctrl_addr,
return res;
}

/* We may read mem_cfg_addr as zero, when target algorithm code is not running yet.
/* When target algorithm code is not running yet, we may read mem_cfg_addr as garbage (invalid addr)
For some targets (e.g. esp32p4), reading invalid address will be an error */
if (mem_cfg_addr > 0) {
if (esp_riscv->is_dram_address(mem_cfg_addr)) {
for (int i = 0; i < 2; i++) {
LOG_DEBUG("memory block %d start @ 0x%x!", i, mem_cfg_addr);
res = target_read_u32(target, mem_cfg_addr, &esp_riscv->apptrace.mem_blocks[i].start);
Expand Down
5 changes: 0 additions & 5 deletions tcl/target/esp32p4.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,6 @@ proc create_esp32p4_target { } {
#configure_shutdown_command

configure_esp_riscv_default_settings

# It is essential to ensure that a cache and/or pipeline flush occurs before memory access.
# In RISC-V, this is achieved by executing the fence instruction before reading or writing to memory.
# This is why we have adjusted the memory access order to prioritize program buffer first.
riscv set_mem_access progbuf sysbus abstract
}

create_esp32p4_target
Expand Down

0 comments on commit eab53c1

Please sign in to comment.