Merge pull request #729 from mrv96/patch-1

Support for custom TMSC buffer: cJTAG OScan1 improvement
This commit is contained in:
Tim Newsome 2022-09-23 09:49:50 -07:00 committed by GitHub
commit 8bb25e0079
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 3 deletions

View File

@ -2583,10 +2583,23 @@ and initially asserted reset signals.
@end deffn @end deffn
@deffn {Command} {ftdi oscan1_mode} on|off @deffn {Command} {ftdi oscan1_mode} on|off
Enable or disable OSCAN1 mode. This mode is intended for use with an adapter, Enable or disable OScan1 mode. This mode is intended for use with an adapter,
such as the ARM-JTAG-SWD by Olimex, that sits in between the FTDI chip and the such as the ARM-JTAG-SWD by Olimex, that sits in between the FTDI chip and the
target. The adapter uses the normal JTAG signals to control TCKC and TMSC target. The cJTAG prococol is composed of two wires: TCKC (clock) and TMSC (data).
(bidirectional) signals used in 2-wire cJTAG. TMSC is a bidirectional signal which is time-multiplexed alternating TDI, TMS and
TDO. The multiplexing is achieved by a tri-state buffer which puts TMSC in Hi-Z
when the device is supposed to take the control of the line (TDO phase).
The ARM-JTAG-SWD adapter uses standard TRST and TMS signals to control TMSC
direction. TRST is used by the adapter as selector for the multiplexers which set
the JTAG probe in 2-wire mode. Whatever signal is used for this purpose, it must
be defined with the name JTAG_SEL using @command{ftdi layout_signal}. JTAG_SEL is
set to 0 during OScan1 initialization.
Some JTAG probes like the Digilent JTAG-HS2, support cJTAG by using a
separate pin to control when TMS is driven onto TMSC. You can use such
probes by defining the signal TMSC_EN using
@command{ftdi layout_signal TMSC_EN -data <mask>}.
@end deffn @end deffn
@deffn {Command} {ftdi layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-input}|@option{-ninput} input_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name] @deffn {Command} {ftdi layout_signal} name [@option{-data}|@option{-ndata} data_mask] [@option{-input}|@option{-ninput} input_mask] [@option{-oe}|@option{-noe} oe_mask] [@option{-alias}|@option{-nalias} name]

View File

@ -808,6 +808,8 @@ static void oscan1_mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, u
static const uint8_t zero; static const uint8_t zero;
static const uint8_t one = 1; static const uint8_t one = 1;
struct signal *tmsc_en = find_signal_by_name("TMSC_EN");
LOG_DEBUG_IO("oscan1_mpsse_clock_data: %sout %d bits", in ? "in" : "", length); LOG_DEBUG_IO("oscan1_mpsse_clock_data: %sout %d bits", in ? "in" : "", length);
for (unsigned i = 0; i < length; i++) { for (unsigned i = 0; i < length; i++) {
@ -833,8 +835,14 @@ static void oscan1_mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, u
mpsse_clock_tms_cs_out(mpsse_ctx, &one, 0, 1, false, mode); mpsse_clock_tms_cs_out(mpsse_ctx, &one, 0, 1, false, mode);
} }
if (tmsc_en)
ftdi_set_signal(tmsc_en, '0'); /* put TMSC in high impedance */
/* drive another TCK without driving TMSC (TDO cycle) */ /* drive another TCK without driving TMSC (TDO cycle) */
mpsse_clock_tms_cs(mpsse_ctx, &zero, 0, in, in_offset+i, 1, false, mode); mpsse_clock_tms_cs(mpsse_ctx, &zero, 0, in, in_offset+i, 1, false, mode);
if (tmsc_en)
ftdi_set_signal(tmsc_en, '1'); /* drive again TMSC */
} }
} }
@ -845,6 +853,8 @@ static void oscan1_mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out,
static const uint8_t zero; static const uint8_t zero;
static const uint8_t one = 1; static const uint8_t one = 1;
struct signal *tmsc_en = find_signal_by_name("TMSC_EN");
LOG_DEBUG_IO("oscan1_mpsse_clock_tms_cs: %sout %d bits, tdi=%d", in ? "in" : "", length, tdi); LOG_DEBUG_IO("oscan1_mpsse_clock_tms_cs: %sout %d bits, tdi=%d", in ? "in" : "", length, tdi);
for (unsigned i = 0; i < length; i++) { for (unsigned i = 0; i < length; i++) {
@ -871,8 +881,14 @@ static void oscan1_mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out,
mpsse_clock_tms_cs_out(mpsse_ctx, &one, 0, 1, (tmsbit != 0), mode); mpsse_clock_tms_cs_out(mpsse_ctx, &one, 0, 1, (tmsbit != 0), mode);
} }
if (tmsc_en)
ftdi_set_signal(tmsc_en, '0'); /* put TMSC in high impedance */
/* drive another TCK without driving TMSC (TDO cycle) */ /* drive another TCK without driving TMSC (TDO cycle) */
mpsse_clock_tms_cs(mpsse_ctx, &zero, 0, in, in_offset+i, 1, false, mode); mpsse_clock_tms_cs(mpsse_ctx, &zero, 0, in, in_offset+i, 1, false, mode);
if (tmsc_en)
ftdi_set_signal(tmsc_en, '1'); /* drive again TMSC */
} }
} }

View File

@ -0,0 +1,19 @@
# this supports JTAG-HS2 (and apparently Nexys4 as well)
adapter driver ftdi
ftdi device_desc "Digilent Adept USB Device"
ftdi vid_pid 0x0403 0x6014
ftdi channel 0
ftdi layout_init 0xc0e8 0xe0eb
reset_config none
# These signals are used for cJTAG escape sequence on initialization only
ftdi layout_signal TCK -data 0x0001
ftdi layout_signal TDI -data 0x0002
ftdi layout_signal TDO -input 0x0004
ftdi layout_signal TMS -data 0x0008
ftdi layout_signal JTAG_SEL -ndata 0xc000
ftdi layout_signal TMSC_EN -data 0x0020