From 7ae5983ba12080af998717a46a25f4059a70508c Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Tue, 28 Jan 2025 20:36:02 +0300 Subject: [PATCH 1/4] hosted/ftdi: Implement jtagtap_cycle like tms_seq --- src/platforms/hosted/ftdi_jtag.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/ftdi_jtag.c b/src/platforms/hosted/ftdi_jtag.c index a88f0e4ee9c..2b22b2bc89f 100644 --- a/src/platforms/hosted/ftdi_jtag.c +++ b/src/platforms/hosted/ftdi_jtag.c @@ -149,6 +149,18 @@ static bool ftdi_jtag_next(const bool tms, const bool tdi) static void ftdi_jtag_cycle(const bool tms, const bool tdi, const size_t clock_cycles) { - for (size_t i = 0; i < clock_cycles; i++) - ftdi_jtag_next(tms, tdi); + DEBUG_PROBE("%s: %zu clock cycles with TMS %s and TDI %s\n", __func__, clock_cycles, tms ? "high" : "low", + tdi ? "high" : "low"); + uint64_t tms_states = (UINT64_C(1) << clock_cycles) - 1ULL; + if (!tms) + tms_states = 0; + for (size_t cycle = 0U; cycle < clock_cycles; cycle += 7U) { + const uint8_t cmd[3U] = { + MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, + MIN(7U, clock_cycles - cycle) - 1U, + (tdi ? 0x80U : 0U) | (tms_states & 0x7fU), + }; + tms_states >>= 7U; + ftdi_buffer_write_arr(cmd); + } } From a2ba626bdc4cde55db230429b8dc99dd7b557193 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Tue, 28 Jan 2025 20:48:52 +0300 Subject: [PATCH 2/4] hosted/ftdi: Add buffering to jtagtap_cycle --- src/platforms/hosted/ftdi_jtag.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/platforms/hosted/ftdi_jtag.c b/src/platforms/hosted/ftdi_jtag.c index 2b22b2bc89f..97dcf86dfa3 100644 --- a/src/platforms/hosted/ftdi_jtag.c +++ b/src/platforms/hosted/ftdi_jtag.c @@ -154,6 +154,8 @@ static void ftdi_jtag_cycle(const bool tms, const bool tdi, const size_t clock_c uint64_t tms_states = (UINT64_C(1) << clock_cycles) - 1ULL; if (!tms) tms_states = 0; + uint8_t cmds[30U] = {0}; /* Up to ceil[64 // 7] = 10 commands, 3 byte each */ + size_t cmd_count = 0; for (size_t cycle = 0U; cycle < clock_cycles; cycle += 7U) { const uint8_t cmd[3U] = { MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, @@ -161,6 +163,7 @@ static void ftdi_jtag_cycle(const bool tms, const bool tdi, const size_t clock_c (tdi ? 0x80U : 0U) | (tms_states & 0x7fU), }; tms_states >>= 7U; - ftdi_buffer_write_arr(cmd); + memcpy(&cmds[sizeof(cmd) * cmd_count++], cmd, sizeof(cmd)); } + ftdi_buffer_write(cmds, 3U * cmd_count); } From d095eaea62d09cf17a0cb650bbf84653a243c5b5 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Tue, 28 Jan 2025 21:02:18 +0300 Subject: [PATCH 3/4] hosted/ftdi: Simplify jtagtap_cycle via CLK_BYTES/CLK_BITS opcode --- src/platforms/hosted/ftdi_jtag.c | 45 +++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/platforms/hosted/ftdi_jtag.c b/src/platforms/hosted/ftdi_jtag.c index 97dcf86dfa3..765859e499f 100644 --- a/src/platforms/hosted/ftdi_jtag.c +++ b/src/platforms/hosted/ftdi_jtag.c @@ -149,21 +149,40 @@ static bool ftdi_jtag_next(const bool tms, const bool tdi) static void ftdi_jtag_cycle(const bool tms, const bool tdi, const size_t clock_cycles) { + if (clock_cycles >= 0x80000U) + return; DEBUG_PROBE("%s: %zu clock cycles with TMS %s and TDI %s\n", __func__, clock_cycles, tms ? "high" : "low", tdi ? "high" : "low"); - uint64_t tms_states = (UINT64_C(1) << clock_cycles) - 1ULL; - if (!tms) - tms_states = 0; - uint8_t cmds[30U] = {0}; /* Up to ceil[64 // 7] = 10 commands, 3 byte each */ - size_t cmd_count = 0; - for (size_t cycle = 0U; cycle < clock_cycles; cycle += 7U) { - const uint8_t cmd[3U] = { - MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, - MIN(7U, clock_cycles - cycle) - 1U, - (tdi ? 0x80U : 0U) | (tms_states & 0x7fU), + + /* Update state of TMS & TDI using 0x4b opcode, then trigger 8a+b cycles using 0x8f, 0x8e. */ + const uint8_t cmd[3] = { + MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, + 0, + (tdi ? 0x80U : 0U) | (tms ? 0x01U : 0U), + }; + ftdi_buffer_write_arr(cmd); + + /* + * 0x8f CLK_BYTES: Length of 0..n will generate 1..1+n byte cycles, + * i.e. emit 8..8*(n+1) clocks, so adjust clock_bytes down by 1. + */ + size_t clock_bytes = clock_cycles / 8U; + if (clock_bytes > 0) { + clock_bytes--; + const uint8_t cmd8[3U] = { + CLK_BYTES, + clock_bytes & 0xffU, + clock_bytes >> 8U, }; - tms_states >>= 7U; - memcpy(&cmds[sizeof(cmd) * cmd_count++], cmd, sizeof(cmd)); + ftdi_buffer_write_arr(cmd8); } - ftdi_buffer_write(cmds, 3U * cmd_count); + /* 0x8e CLK_BITS: Length of 0..7 will emit 1..8 clocks */ + const uint8_t clock_bits = clock_cycles % 8U - 1U; + if (clock_bits >= 8U) + return; + const uint8_t cmd1[2U] = { + CLK_BITS, + clock_bits, + }; + ftdi_buffer_write_arr(cmd1); } From f9e0169a080844601eafb6b09255610765dd49d4 Mon Sep 17 00:00:00 2001 From: ALTracer <11005378+ALTracer@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:30:20 +0300 Subject: [PATCH 4/4] hosted/ftdi: jtagtap_cycle: Express divmod by 8 as shift and mask --- src/platforms/hosted/ftdi_jtag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/hosted/ftdi_jtag.c b/src/platforms/hosted/ftdi_jtag.c index 765859e499f..31a03c24f27 100644 --- a/src/platforms/hosted/ftdi_jtag.c +++ b/src/platforms/hosted/ftdi_jtag.c @@ -166,7 +166,7 @@ static void ftdi_jtag_cycle(const bool tms, const bool tdi, const size_t clock_c * 0x8f CLK_BYTES: Length of 0..n will generate 1..1+n byte cycles, * i.e. emit 8..8*(n+1) clocks, so adjust clock_bytes down by 1. */ - size_t clock_bytes = clock_cycles / 8U; + size_t clock_bytes = clock_cycles >> 3U; if (clock_bytes > 0) { clock_bytes--; const uint8_t cmd8[3U] = { @@ -177,7 +177,7 @@ static void ftdi_jtag_cycle(const bool tms, const bool tdi, const size_t clock_c ftdi_buffer_write_arr(cmd8); } /* 0x8e CLK_BITS: Length of 0..7 will emit 1..8 clocks */ - const uint8_t clock_bits = clock_cycles % 8U - 1U; + const uint8_t clock_bits = (clock_cycles & 7U) - 1U; if (clock_bits >= 8U) return; const uint8_t cmd1[2U] = {