From 3841fd3e4cc70014b08cad9b7befb234d0dea588 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sat, 19 Apr 2025 22:13:36 +0300 Subject: [PATCH 1/5] hosted/ftdi_bmp: Register generic FT2232H on Icebreaker for JTAG on MPSSE interface A --- src/platforms/hosted/ftdi_bmp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index e664d466ead..db83f843170 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -359,6 +359,19 @@ const cable_desc_s cable_desc[] = { .bb_swdio_in_pin = MPSSE_CS, .name = "hifive1", }, + { + /* + * 1bitSquared Icebreaker FT2232H + * Direct connection on Interface A, JTAG only + */ + .vendor = 0x0403U, + .product = 0x6010U, + .interface = INTERFACE_A, + .init.data[0] = MPSSE_CS | MPSSE_DO | MPSSE_DI, + .init.dirs[0] = MPSSE_CS | MPSSE_DO | MPSSE_SK, + .description = "Dual RS232-HS", + .name = "icebreaker", + }, { /* * https://www.olimex.com/Products/ARM/JTAG/ARM-USB-TINY-H/ From 232cb9419acc69666141ebd9a7e94a2f707b2440 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sat, 19 Apr 2025 22:14:25 +0300 Subject: [PATCH 2/5] jtag_devs: Register Hazard3/ice40 TAP as a RISC-V DTM --- src/target/jtag_devs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/target/jtag_devs.c b/src/target/jtag_devs.c index ecd6eca761a..748977a3085 100644 --- a/src/target/jtag_devs.c +++ b/src/target/jtag_devs.c @@ -410,6 +410,14 @@ const jtag_dev_descr_s dev_descr[] = { .idmask = 0x0fffffffU, #if ENABLE_DEBUG == 1 .descr = "RISC-V debug v0.13.", +#endif + .handler = riscv_jtag_dtm_handler, + }, + { + .idcode = 0xdeadbeefU, + .idmask = 0xffffffffU, +#if ENABLE_DEBUG == 1 + .descr = "RISC-V Hazard3 DTM.", #endif .handler = riscv_jtag_dtm_handler, }, From 2daf09d80e06f59ac962a7d1ea51edff1a0bc422 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sat, 19 Apr 2025 22:25:50 +0300 Subject: [PATCH 3/5] riscv32: Add very basic support for Hazard3 SoC on Icebreaker SPRAM --- src/target/riscv32.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target/riscv32.c b/src/target/riscv32.c index 0d98a1b1596..5aa0e8c797e 100644 --- a/src/target/riscv32.c +++ b/src/target/riscv32.c @@ -71,6 +71,13 @@ static void riscv32_regs_write(target_s *target, const void *data); static int riscv32_breakwatch_set(target_s *target, breakwatch_s *breakwatch); static int riscv32_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); +bool hazard3_probe(target_s *const target) +{ + target->driver = "Hazard3"; + target_add_ram32(target, 0x0, 131072); + return true; +} + bool riscv32_probe(target_s *const target) { /* 'E' base ISA has 16 GPRs + PC, 'I' base ISA has 32 GPRs + PC */ @@ -95,6 +102,9 @@ bool riscv32_probe(target_s *const target) case JEP106_MANUFACTURER_RASPBERRY: PROBE(rp2350_probe); break; + case 0xe77: + PROBE(hazard3_probe); + break; default: break; } From 421ca41c9b1f0f15d9cd0492c6e8ad9b0af303b4 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sun, 20 Apr 2025 13:52:08 +0300 Subject: [PATCH 4/5] riscv_debug: Detect Semihosting breakpoints and connect with common support code --- src/target/riscv_debug.c | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index b16d60a1129..2f78b4c3705 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -37,6 +37,7 @@ #include "gdb_reg.h" #include "riscv_debug.h" #include "buffer_utils.h" +#include "semihosting.h" #include @@ -864,6 +865,31 @@ bool riscv_csr_write(riscv_hart_s *const hart, const uint16_t reg, const void *c return true; } +static target_addr_t riscv_pc_read(riscv_hart_s *const hart) +{ + target_addr_t data = 0; + riscv_csr_read(hart, RV_DPC, &data); + //riscv32_reg_read(target, 32, &data, sizeof(data)); + return data; +} + +static bool riscv_hostio_request(target_s *const target) +{ + /* Read out syscall number from a0/x10 and first argument from a1/x11 */ + uint32_t syscall = 0U; + target_reg_read(target, 10, &syscall, sizeof(syscall)); + uint32_t a1 = 0U; + target_reg_read(target, 11, &a1, sizeof(a1)); + + /* Hand off to the main semihosting implementation */ + const int32_t result = semihosting_request(target, syscall, a1); + + /* Write the result back to the target */ + target_reg_write(target, 10, &result, sizeof(result)); + /* Return if the request was in any way interrupted */ + return target->tc->interrupted; +} + uint8_t riscv_mem_access_width(const riscv_hart_s *const hart, const target_addr_t address, const size_t length) { /* Grab the Hart's most maxmimally aligned possible write width */ @@ -1103,6 +1129,21 @@ static target_halt_reason_e riscv_halt_poll(target_s *const target, target_addr6 status &= RV_DCSR_CAUSE_MASK; /* Dispatch on the cause code */ switch (status) { + case RV_HALT_CAUSE_EBREAK: { + /* If we've hit a programmed breakpoint, check for semihosting call. */ + const target_addr_t program_counter = riscv_pc_read(hart); + uint32_t instructions[3] = {0}; + target_mem32_read(target, &instructions, program_counter - 4U, 12); + /* A semihosting call is three consecutive uncompressed instructions: slli zero, zero 0x1f; ebreak, srai zero, zero, 7. */ + if (instructions[0] == 0x01f01013 && instructions[1] == RV_EBREAK && instructions[2] == 0x40705013) { + if (riscv_hostio_request(target)) + return TARGET_HALT_REQUEST; + + riscv_halt_resume(target, false); + return TARGET_HALT_RUNNING; + } + return TARGET_HALT_BREAKPOINT; + } case RV_HALT_CAUSE_TRIGGER: /* XXX: Need to read out the triggers to find the one causing this, and grab the watch value */ return TARGET_HALT_BREAKPOINT; From e0b6125858026b40b1544febbe538396f8b512c3 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Sat, 26 Apr 2025 20:10:05 +0300 Subject: [PATCH 5/5] riscv_debug: Step over ebreak instructions --- src/target/riscv_debug.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index 2f78b4c3705..e6943db9e32 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -1102,6 +1102,19 @@ static void riscv_halt_resume(target_s *target, const bool step) } if (!riscv_csr_write(hart, RV_DCSR | RV_CSR_FORCE_32_BIT, &stepping_config)) return; + /* Step over coded breakpoints */ + uint32_t dcsr_cause = 0U; + riscv_csr_read(hart, RV_DCSR, &dcsr_cause); + dcsr_cause &= RV_DCSR_CAUSE_MASK; + if (dcsr_cause == RV_HALT_CAUSE_EBREAK) { + /* Read the instruction to resume on */ + uint32_t program_counter = riscv_pc_read(hart); + /* If it actually is a breakpoint instruction, update the program counter one past it. */ + if (target_mem32_read32(target, program_counter) == RV_EBREAK) { + program_counter += 4U; + riscv_csr_write(hart, RV_DPC, &program_counter); + } + } /* Request the hart to resume */ if (!riscv_dm_write(hart->dbg_module, RV_DM_CONTROL, hart->hartsel | RV_DM_CTRL_RESUME_REQ)) return;