This is an automated email from Gerrit. "Name of user not set <liam.fletc...@microchip.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8617
-- gerrit commit 36932d0bfe2948645a50aead0ca9b69371a42b88 Author: Liam Fletcher <liam.fletc...@microchip.com> Date: Tue Mar 18 09:55:42 2025 +0000 target/riscv: allow access to multiple debug modules The DMI register in the JTAG IEEE 1149.1 TAP controller contains a 2 bit opcode, a 32 bit data field and a variable length address field. Extend the openocd RISC-V Debug Spec implementation to allow accessing of DMs using this address field. This is to support next generation devices, allowing support for up to 32 DMs. Change-Id: I47afe546a85243fc5a0061f37f15b6829cd497b8 Signed-off-by: Liam Fletcher <liam.fletc...@microchip.com> Signed-off-by: Daire McNamara <daire.mcnam...@microchip.com> Signed-off-by: Ken O'Hagan <ken.oha...@microchip.com> Signed-off-by: Ciaran Lappin <ciaran.lap...@microchip.com> diff --git a/src/helper/replacements.h b/src/helper/replacements.h index ecc0e5e955..ebbe716ca7 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -279,6 +279,7 @@ typedef struct { #endif /* HAVE_ELF_H */ #ifndef HAVE_ELF64 +#define EI_NIDENT (16) typedef uint64_t Elf64_Addr; typedef uint16_t Elf64_Half; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index bb450ce623..54864852a0 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -84,6 +84,8 @@ static int write_memory(struct target *target, target_addr_t address, #define RISCV013_INFO(r) riscv013_info_t *r = get_info(target) +#define DMADDR_SHIFT (10) + /*** JTAG registers. ***/ typedef enum { @@ -132,6 +134,7 @@ typedef enum { typedef struct { struct list_head list; unsigned int abs_chain_position; + int addr; /* The number of harts connected to this DM. */ int hart_count; @@ -241,7 +244,8 @@ static dm013_info_t *get_dm(struct target *target) dm013_info_t *dm = NULL; list_for_each_entry(entry, &dm_list, list) { if (entry->abs_chain_position == abs_chain_position) { - dm = entry; + if (entry->addr == target->dmaddr) + dm = entry; break; } } @@ -252,6 +256,7 @@ static dm013_info_t *get_dm(struct target *target) if (!dm) return NULL; dm->abs_chain_position = abs_chain_position; + dm->addr = target->dmaddr; dm->current_hartid = -1; dm->hart_count = -1; INIT_LIST_HEAD(&dm->target_list); @@ -558,6 +563,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, uint32_t data_out, int timeout_sec, bool exec, bool ensure_success) { select_dmi(target); + address |= (target->dmaddr << DMADDR_SHIFT); dmi_status_t status; uint32_t address_in; @@ -2183,7 +2189,7 @@ static int sample_memory_bus_v1(struct target *target, sbcs_write |= DM_SBCS_SBREADONDATA; sbcs_write |= sb_sbaccess(config->bucket[i].size_bytes); if (!sbcs_valid || sbcs_write != sbcs) { - riscv_batch_add_dmi_write(batch, DM_SBCS, sbcs_write); + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBCS, sbcs_write); sbcs = sbcs_write; sbcs_valid = true; } @@ -2192,18 +2198,18 @@ static int sample_memory_bus_v1(struct target *target, (!sbaddress1_valid || sbaddress1 != config->bucket[i].address >> 32)) { sbaddress1 = config->bucket[i].address >> 32; - riscv_batch_add_dmi_write(batch, DM_SBADDRESS1, sbaddress1); + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBADDRESS1, sbaddress1); sbaddress1_valid = true; } if (!sbaddress0_valid || sbaddress0 != (config->bucket[i].address & 0xffffffff)) { sbaddress0 = config->bucket[i].address; - riscv_batch_add_dmi_write(batch, DM_SBADDRESS0, sbaddress0); + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBADDRESS0, sbaddress0); sbaddress0_valid = true; } if (config->bucket[i].size_bytes > 4) - riscv_batch_add_dmi_read(batch, DM_SBDATA1); - riscv_batch_add_dmi_read(batch, DM_SBDATA0); + riscv_batch_add_dmi_read(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBDATA1); + riscv_batch_add_dmi_read(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBDATA0); result_bytes += 1 + config->bucket[i].size_bytes; } } @@ -2214,7 +2220,7 @@ static int sample_memory_bus_v1(struct target *target, break; } - size_t sbcs_key = riscv_batch_add_dmi_read(batch, DM_SBCS); + size_t sbcs_key = riscv_batch_add_dmi_read(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBCS); int result = batch_run(target, batch); if (result != ERROR_OK) @@ -3164,8 +3170,8 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres unsigned int reads = 0; for (unsigned int j = index; j < count; j++) { if (size > 4) - riscv_batch_add_dmi_read(batch, DM_DATA1); - riscv_batch_add_dmi_read(batch, DM_DATA0); + riscv_batch_add_dmi_read(batch, (target->dmaddr << DMADDR_SHIFT) | DM_DATA1); + riscv_batch_add_dmi_read(batch, (target->dmaddr << DMADDR_SHIFT) | DM_DATA0); reads++; if (riscv_batch_full(batch)) @@ -3677,20 +3683,20 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, break; if (size > 12) - riscv_batch_add_dmi_write(batch, DM_SBDATA3, + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBDATA3, ((uint32_t) p[12]) | (((uint32_t) p[13]) << 8) | (((uint32_t) p[14]) << 16) | (((uint32_t) p[15]) << 24)); if (size > 8) - riscv_batch_add_dmi_write(batch, DM_SBDATA2, + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBDATA2, ((uint32_t) p[8]) | (((uint32_t) p[9]) << 8) | (((uint32_t) p[10]) << 16) | (((uint32_t) p[11]) << 24)); if (size > 4) - riscv_batch_add_dmi_write(batch, DM_SBDATA1, + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBDATA1, ((uint32_t) p[4]) | (((uint32_t) p[5]) << 8) | (((uint32_t) p[6]) << 16) | @@ -3702,7 +3708,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, } if (size > 1) value |= ((uint32_t) p[1]) << 8; - riscv_batch_add_dmi_write(batch, DM_SBDATA0, value); + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_SBDATA0, value); log_memory_access(address + i * size, value, size, false); next_address += size; @@ -3909,8 +3915,8 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, setup_needed = false; } else { if (size > 4) - riscv_batch_add_dmi_write(batch, DM_DATA1, value >> 32); - riscv_batch_add_dmi_write(batch, DM_DATA0, value); + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_DATA1, value >> 32); + riscv_batch_add_dmi_write(batch, (target->dmaddr << DMADDR_SHIFT) | DM_DATA0, value); if (riscv_batch_full(batch)) break; } @@ -4001,7 +4007,6 @@ static int write_memory(struct target *target, target_addr_t address, continue; ret = write_memory_progbuf(target, address, size, count, buffer); - if (ret != ERROR_OK) progbuf_result = "failed"; } else if (method == RISCV_MEM_ACCESS_SYSBUS) { diff --git a/src/target/target.c b/src/target/target.c index ce468cc90a..e09cafadd5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4884,6 +4884,7 @@ enum target_cfg_param { TCFG_WORK_AREA_BACKUP, TCFG_ENDIAN, TCFG_COREID, + TCFG_DMADDR, TCFG_CHAIN_POSITION, TCFG_DBGBASE, TCFG_RTOS, @@ -4901,6 +4902,7 @@ static struct jim_nvp nvp_config_opts[] = { { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP }, { .name = "-endian", .value = TCFG_ENDIAN }, { .name = "-coreid", .value = TCFG_COREID }, + { .name = "-dmaddr", .value = TCFG_DMADDR }, { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, { .name = "-rtos", .value = TCFG_RTOS }, @@ -5142,6 +5144,20 @@ no_params: /* loop for more */ break; + case TCFG_DMADDR: + if (goi->is_configure) { + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) + return e; + target->dmaddr = (int32_t)w; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dmaddr)); + /* loop for more */ + break; + case TCFG_CHAIN_POSITION: if (goi->is_configure) { Jim_Obj *o_t; diff --git a/src/target/target.h b/src/target/target.h index 47f02ec266..171fc5e49a 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -118,6 +118,7 @@ struct target { char *cmd_name; /* tcl Name of target */ struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ + int32_t dmaddr; /* which dm to use (riscv only) */ /** Should we defer examine to later */ bool defer_examine; --