From 66e480d86175878512488fd71fc0b9e82314dcfe Mon Sep 17 00:00:00 2001 From: Greg Savin <43152568+SiFiveGregS@users.noreply.github.com> Date: Thu, 4 Apr 2019 15:50:11 -0700 Subject: [PATCH] Checking in for backup. --- configure.ac | 1 + src/target/riscv/riscv-013.c | 106 +++++++++++++++++++++++++++++++++++ src/target/riscv/riscv.c | 47 ++++++++++++++++ src/target/riscv/riscv.h | 5 ++ src/target/target.c | 18 ++++++ src/target/target.h | 3 + 6 files changed, 180 insertions(+) diff --git a/configure.ac b/configure.ac index ab05cc656..eb1189d66 100644 --- a/configure.ac +++ b/configure.ac @@ -111,6 +111,7 @@ m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])]) m4_define([USB1_ADAPTERS], [[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]], [[ftdi_oscan1], [cJTAG OSCAN1 tunneled thru MPSSE], [FTDI_OSCAN1]], + [[riscv_arty_bscan], [Access to RISCV on Arty board via BSCAN], [RISCV_ARTY_BSCAN]], [[stlink], [ST-Link JTAG Programmer], [HLADAPTER_STLINK]], [[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]], [[ulink], [Keil ULINK JTAG Programmer], [ULINK]], diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index d7bfac9d1..95cc56b2d 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -404,8 +404,108 @@ static void dump_field(int idle, const struct scan_field *field) /*** Utility functions. ***/ +#if BUILD_RISCV_ARTY_BSCAN == 1 +static void select_dmi_via_bscan(struct target *target) +{ + jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE); + jtag_add_dr_scan(target->tap, bscan_tunneled_select_dmi_num_fields, bscan_tunneled_select_dmi, TAP_IDLE); +} + +static uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out) +{ + /* jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE); */ + + /* On BSCAN TAP: Select IR=USER4, issue tunneled IR scan via BSCAN TAP's DR */ + + uint8_t zero[4] = {0}; + uint8_t one[4] = {1}; + uint8_t tunneled_ir_width[4] = {target->bscan_tunnel_ir_width}; + uint8_t tunneled_dr_width[4] = {32}; + uint8_t out_0[4] = {out & 0x1}; + uint8_t out_31_1[4]; + uint8_t in_value[4]; + + buf_set_u32(out_31_1, 0, 32, (out >> 1)); + + struct scan_field tunneled_ir[] = { + { + .num_bits = 1, + .out_value = zero, + .in_value = NULL, + }, + { + .num_bits = 7, + .out_value = tunneled_ir_width, + .in_value = NULL, + }, + { + .num_bits = target->bscan_tunnel_ir_width, + .out_value = ir_dtmcontrol, + .in_value = NULL, + }, + { + .num_bits = 3, + .out_value = zero, + .in_value = NULL, + } + + }; + struct scan_field tunneled_dr[] = { + { + .num_bits = 1, + .out_value = one, + .in_value = NULL, + }, + { + .num_bits = 7, + .out_value = tunneled_dr_width, + .in_value = NULL, + }, + /* for BSCAN tunnel. there is a one TCK skew between shift in and shift out, so splitting the DR payload into 2 fields */ + { + .num_bits = 1, + .out_value = out_0, + .in_value = NULL, + }, + { + .num_bits = 32, + .out_value = out_31_1, + .in_value = in_value, + }, + { + .num_bits = 3, + .out_value = zero, + .in_value = NULL, + } + }; + + jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE); + jtag_add_dr_scan(target->tap, DIM(tunneled_ir), tunneled_ir, TAP_IDLE); + jtag_add_dr_scan(target->tap, DIM(tunneled_dr), tunneled_dr, TAP_IDLE); + select_dmi_via_bscan(target); + + int retval = jtag_execute_queue(); + if (retval != ERROR_OK) { + LOG_ERROR("failed jtag scan: %d", retval); + return retval; + } + + uint32_t in = buf_get_u32(in_value, 0, 32); + LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in); + + return in; +} + +#endif + static void select_dmi(struct target *target) { +#if BUILD_RISCV_ARTY_BSCAN == 1 + if (target->bscan_tunnel_ir_width != 0) { + select_dmi_via_bscan(target); + return; + } +#endif jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); } @@ -415,6 +515,12 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out) uint8_t in_value[4]; uint8_t out_value[4]; +#if BUILD_RISCV_ARTY_BSCAN == 1 + if (target->bscan_tunnel_ir_width != 0) { + return dtmcontrol_scan_via_bscan(target, out); + } +#endif + buf_set_u32(out_value, 0, 32, out); jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 5cdcc018d..6d5a9ea15 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -170,6 +170,44 @@ struct scan_field select_idcode = { .out_value = ir_idcode }; +#if BUILD_RISCV_ARTY_BSCAN == 1 + +uint8_t ir_user4[4] = {0x23}; +struct scan_field select_user4 = { + .in_value = NULL, + .out_value = ir_user4 +}; + + +uint8_t zero[4] = {0}; +uint8_t one[4] = {1}; +uint8_t tunneled_ir_width[4] = {5}; /* overridden by assignment in riscv_init_target */ +struct scan_field _bscan_tunneled_select_dmi[] = { + { + .num_bits = 1, + .out_value = zero, + .in_value = NULL, + }, + { + .num_bits = 7, + .out_value = tunneled_ir_width, + .in_value = NULL, + }, + { + .num_bits = 0, /* initialized in riscv_init_target to ir width of DM */ + .out_value = ir_dbus, + .in_value = NULL, + }, + { + .num_bits = 3, + .out_value = zero, + .in_value = NULL, + } +}; +struct scan_field *bscan_tunneled_select_dmi = _bscan_tunneled_select_dmi; +uint32_t bscan_tunneled_select_dmi_num_fields = sizeof(bscan_tunneled_select_dmi)/sizeof(bscan_tunneled_select_dmi[0]); +#endif + struct trigger { uint64_t address; uint32_t length; @@ -266,6 +304,15 @@ static int riscv_init_target(struct command_context *cmd_ctx, select_dbus.num_bits = target->tap->ir_length; select_idcode.num_bits = target->tap->ir_length; +#if BUILD_RISCV_ARTY_BSCAN == 1 + if (target->bscan_tunnel_ir_width != 0) { + select_user4.num_bits = target->bscan_tunnel_ir_width; + tunneled_ir_width[0] = target->bscan_tunnel_ir_width; + bscan_tunneled_select_dmi[2].num_bits = target->bscan_tunnel_ir_width; + } + +#endif + riscv_semihosting_init(target); target->debug_reason = DBG_REASON_DBGRQ; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index ade1bf0df..d14f7f764 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -165,6 +165,11 @@ extern uint8_t ir_dbus[4]; extern struct scan_field select_dbus; extern uint8_t ir_idcode[4]; extern struct scan_field select_idcode; +#if BUILD_RISCV_ARTY_BSCAN == 1 +extern struct scan_field select_user4; +extern struct scan_field *bscan_tunneled_select_dmi; +extern uint32_t bscan_tunneled_select_dmi_num_fields; +#endif /*** OpenOCD Interface */ int riscv_openocd_poll(struct target *target); diff --git a/src/target/target.c b/src/target/target.c index 036c065d4..30583ad47 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4603,6 +4603,7 @@ enum target_cfg_param { TCFG_RTOS, TCFG_DEFER_EXAMINE, TCFG_GDB_PORT, + TCFG_BSCAN_TUNNEL_IR_WIDTH, }; static Jim_Nvp nvp_config_opts[] = { @@ -4619,6 +4620,9 @@ static Jim_Nvp nvp_config_opts[] = { { .name = "-rtos", .value = TCFG_RTOS }, { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, { .name = "-gdb-port", .value = TCFG_GDB_PORT }, +#if BUILD_RISCV_ARTY_BSCAN == 1 + { .name = "-bscan-tunnel-ir-width", .value = TCFG_BSCAN_TUNNEL_IR_WIDTH }, +#endif { .name = NULL, .value = -1 } }; @@ -4920,6 +4924,20 @@ no_params: Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1); /* loop for more */ break; + + case TCFG_BSCAN_TUNNEL_IR_WIDTH: + if (goi->isconfigure) { + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->bscan_tunnel_ir_width = (int32_t)w; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->bscan_tunnel_ir_width)); + /* loop for more */ + break; } } /* while (goi->argc) */ diff --git a/src/target/target.h b/src/target/target.h index 7c9db3090..1ce1b1c57 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -210,6 +210,9 @@ struct target { /* The semihosting information, extracted from the target. */ struct semihosting *semihosting; +#if BUILD_RISCV_ARTY_BSCAN == 1 + int bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */ +#endif }; struct target_list {