Support cJTAG JScan3 mode
This commit is contained in:
parent
f61098c225
commit
bd5649dfbe
|
@ -110,7 +110,7 @@ m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])])
|
||||||
|
|
||||||
m4_define([USB1_ADAPTERS],
|
m4_define([USB1_ADAPTERS],
|
||||||
[[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]],
|
[[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]],
|
||||||
[[ftdi_cjtag], [cJTAG (OScan1) tunneled thru MPSSE], [FTDI_CJTAG]],
|
[[ftdi_cjtag], [cJTAG (OScan1, JScan3) tunneled thru MPSSE], [FTDI_CJTAG]],
|
||||||
[[stlink], [ST-Link Programmer], [HLADAPTER_STLINK]],
|
[[stlink], [ST-Link Programmer], [HLADAPTER_STLINK]],
|
||||||
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
|
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
|
||||||
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
|
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
|
||||||
|
|
|
@ -2602,6 +2602,15 @@ probes by defining the signal TMSC_EN using
|
||||||
@command{ftdi layout_signal TMSC_EN -data <mask>}.
|
@command{ftdi layout_signal TMSC_EN -data <mask>}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Command} {ftdi jscan3_mode} on|off
|
||||||
|
Enable or disable JScan3 mode. This mode uses the classic 4-wire JTAG protocol
|
||||||
|
in chips whose JTAG port is only compliant with the cJTAG standard (IEEE 1149.7).
|
||||||
|
|
||||||
|
Since cJTAG needs a 2-wire escape sequence to select the operating mode,
|
||||||
|
a cJTAG adapter like ARM-JTAG-SWD by Olimex is still required. This means
|
||||||
|
that a cJTAG probe configuration script must be used too.
|
||||||
|
@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]
|
||||||
Creates a signal with the specified @var{name}, controlled by one or more FTDI
|
Creates a signal with the specified @var{name}, controlled by one or more FTDI
|
||||||
GPIO pins via a range of possible buffer connections. The masks are FTDI GPIO
|
GPIO pins via a range of possible buffer connections. The masks are FTDI GPIO
|
||||||
|
|
|
@ -106,6 +106,10 @@ static uint8_t ftdi_jtag_mode = JTAG_MODE;
|
||||||
static bool swd_mode;
|
static bool swd_mode;
|
||||||
|
|
||||||
#if BUILD_FTDI_CJTAG == 1
|
#if BUILD_FTDI_CJTAG == 1
|
||||||
|
#define ESCAPE_SEQ_OAC_BIT2 28
|
||||||
|
|
||||||
|
static void cjtag_reset_online_activate(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The cJTAG 2-wire OScan1 protocol, in lieu of 4-wire JTAG, is a configuration option
|
The cJTAG 2-wire OScan1 protocol, in lieu of 4-wire JTAG, is a configuration option
|
||||||
for some SoCs. An FTDI-based adapter that can be configured to appropriately drive
|
for some SoCs. An FTDI-based adapter that can be configured to appropriately drive
|
||||||
|
@ -119,7 +123,6 @@ static bool swd_mode;
|
||||||
to the two-wire clocking and signaling of OScan1 protocol, if placed into OScan1 mode
|
to the two-wire clocking and signaling of OScan1 protocol, if placed into OScan1 mode
|
||||||
during initialization.
|
during initialization.
|
||||||
*/
|
*/
|
||||||
static void oscan1_reset_online_activate(void);
|
|
||||||
static void oscan1_mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
|
static void oscan1_mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
|
||||||
unsigned in_offset, unsigned length, uint8_t mode);
|
unsigned in_offset, unsigned length, uint8_t mode);
|
||||||
static void oscan1_mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
|
static void oscan1_mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
|
||||||
|
@ -128,6 +131,11 @@ static void oscan1_mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *
|
||||||
unsigned length, bool tdi, uint8_t mode);
|
unsigned length, bool tdi, uint8_t mode);
|
||||||
|
|
||||||
static bool oscan1_mode;
|
static bool oscan1_mode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The cJTAG 4-wire JScan3 allows to use standard JTAG protocol with cJTAG hardware
|
||||||
|
*/
|
||||||
|
static bool jscan3_mode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_USB_IDS 8
|
#define MAX_USB_IDS 8
|
||||||
|
@ -670,7 +678,7 @@ static void ftdi_execute_command(struct jtag_command *cmd)
|
||||||
switch (cmd->type) {
|
switch (cmd->type) {
|
||||||
case JTAG_RESET:
|
case JTAG_RESET:
|
||||||
#if BUILD_FTDI_CJTAG == 1
|
#if BUILD_FTDI_CJTAG == 1
|
||||||
oscan1_reset_online_activate(); /* put the target back into OScan1 mode */
|
cjtag_reset_online_activate(); /* put the target back into selected cJTAG mode */
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case JTAG_RUNTEST:
|
case JTAG_RUNTEST:
|
||||||
|
@ -679,7 +687,7 @@ static void ftdi_execute_command(struct jtag_command *cmd)
|
||||||
case JTAG_TLR_RESET:
|
case JTAG_TLR_RESET:
|
||||||
ftdi_execute_statemove(cmd);
|
ftdi_execute_statemove(cmd);
|
||||||
#if BUILD_FTDI_CJTAG == 1
|
#if BUILD_FTDI_CJTAG == 1
|
||||||
oscan1_reset_online_activate(); /* put the target back into OScan1 mode */
|
cjtag_reset_online_activate(); /* put the target back into selected cJTAG mode */
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case JTAG_PATHMOVE:
|
case JTAG_PATHMOVE:
|
||||||
|
@ -760,15 +768,19 @@ static int ftdi_initialize(void)
|
||||||
if (sig->data_mask)
|
if (sig->data_mask)
|
||||||
ftdi_set_signal(sig, '1');
|
ftdi_set_signal(sig, '1');
|
||||||
#if BUILD_FTDI_CJTAG == 1
|
#if BUILD_FTDI_CJTAG == 1
|
||||||
} else if (oscan1_mode) {
|
} else if (oscan1_mode || jscan3_mode) {
|
||||||
struct signal *sig = find_signal_by_name("JTAG_SEL");
|
struct signal *sig = find_signal_by_name("JTAG_SEL");
|
||||||
if (!sig) {
|
if (!sig) {
|
||||||
LOG_ERROR("OScan1 mode is active but JTAG_SEL signal is not defined");
|
LOG_ERROR("A cJTAG mode is active but JTAG_SEL signal is not defined");
|
||||||
return ERROR_JTAG_INIT_FAILED;
|
return ERROR_JTAG_INIT_FAILED;
|
||||||
}
|
}
|
||||||
/* A dummy JTAG_SEL would have zero mask */
|
/* A dummy JTAG_SEL would have zero mask */
|
||||||
if (sig->data_mask)
|
if (sig->data_mask)
|
||||||
ftdi_set_signal(sig, '0');
|
ftdi_set_signal(sig, '0');
|
||||||
|
else if (jscan3_mode) {
|
||||||
|
LOG_ERROR("In JScan3 mode JTAG_SEL signal cannot be dummy, data mask needed");
|
||||||
|
return ERROR_JTAG_INIT_FAILED;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,11 +920,11 @@ static void cjtag_set_tck_tms_tdi(struct signal *tck, char tckvalue, struct sign
|
||||||
ftdi_set_signal(tck, tckvalue);
|
ftdi_set_signal(tck, tckvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void oscan1_reset_online_activate(void)
|
static void cjtag_reset_online_activate(void)
|
||||||
{
|
{
|
||||||
/* After TAP reset, the OSCAN1-to-JTAG adapter is in offline and
|
/* After TAP reset, the cJTAG-to-JTAG adapter is in offline and
|
||||||
non-activated state. Escape sequences are needed to bring
|
non-activated state. Escape sequences are needed to bring the
|
||||||
the TAP online and activated into OSCAN1 mode. */
|
TAP online and activated into the desired working mode. */
|
||||||
|
|
||||||
struct signal *tck = find_signal_by_name("TCK");
|
struct signal *tck = find_signal_by_name("TCK");
|
||||||
struct signal *tdi = find_signal_by_name("TDI");
|
struct signal *tdi = find_signal_by_name("TDI");
|
||||||
|
@ -920,7 +932,7 @@ static void oscan1_reset_online_activate(void)
|
||||||
struct signal *tdo = find_signal_by_name("TDO");
|
struct signal *tdo = find_signal_by_name("TDO");
|
||||||
uint16_t tdovalue;
|
uint16_t tdovalue;
|
||||||
|
|
||||||
static const struct {
|
static struct {
|
||||||
int8_t tck;
|
int8_t tck;
|
||||||
int8_t tms;
|
int8_t tms;
|
||||||
int8_t tdi;
|
int8_t tdi;
|
||||||
|
@ -982,7 +994,7 @@ static void oscan1_reset_online_activate(void)
|
||||||
/* TCK=0, TMS=1, TDI=0 (falling edge TCK with TMSC still 0) */
|
/* TCK=0, TMS=1, TDI=0 (falling edge TCK with TMSC still 0) */
|
||||||
{'0', '1', '0'},
|
{'0', '1', '0'},
|
||||||
|
|
||||||
/* Drive cJTAG escape sequence for activation */
|
/* Drive cJTAG escape sequence for OScan1 activation -- OAC = 1100 -> 2 wires -- */
|
||||||
/* TCK=1, TMS=1, TDI=0 (rising edge TCK with TMSC still 0... online mode activated... also OAC bit0==0) */
|
/* TCK=1, TMS=1, TDI=0 (rising edge TCK with TMSC still 0... online mode activated... also OAC bit0==0) */
|
||||||
{'1', '1', '0'},
|
{'1', '1', '0'},
|
||||||
/* TCK=0, TMS=1, TDI=0 (falling edge TCK) */
|
/* TCK=0, TMS=1, TDI=0 (falling edge TCK) */
|
||||||
|
@ -1029,12 +1041,17 @@ static void oscan1_reset_online_activate(void)
|
||||||
{'0', '1', '0'},
|
{'0', '1', '0'},
|
||||||
/* TCK=1, TMS=1, TDI=0 (rising edge TCK... CP bit3==0) */
|
/* TCK=1, TMS=1, TDI=0 (rising edge TCK... CP bit3==0) */
|
||||||
{'1', '1', '0'},
|
{'1', '1', '0'},
|
||||||
|
/* TCK=0, TMS=1, TDI=0 (falling edge TCK) */
|
||||||
|
{'0', '1', '0'},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!oscan1_mode && !jscan3_mode)
|
||||||
|
return; /* Nothing to do */
|
||||||
|
|
||||||
if (!oscan1_mode)
|
if (oscan1_mode && jscan3_mode) {
|
||||||
|
LOG_ERROR("Both oscan1_mode and jscan3_mode are \"on\". At most one of them can be enabled.");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tck) {
|
if (!tck) {
|
||||||
LOG_ERROR("Can't run cJTAG online/activate escape sequences: TCK signal is not defined");
|
LOG_ERROR("Can't run cJTAG online/activate escape sequences: TCK signal is not defined");
|
||||||
|
@ -1056,10 +1073,20 @@ static void oscan1_reset_online_activate(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (jscan3_mode) {
|
||||||
|
/* Update the sequence above to enable JScan3 instead of OScan1 */
|
||||||
|
sequence[ESCAPE_SEQ_OAC_BIT2].tdi = '0';
|
||||||
|
sequence[ESCAPE_SEQ_OAC_BIT2+1].tdi = '0';
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the sequence to the adapter */
|
/* Send the sequence to the adapter */
|
||||||
for (size_t i = 0; i < sizeof(sequence)/sizeof(sequence[0]); i++)
|
for (size_t i = 0; i < sizeof(sequence)/sizeof(sequence[0]); i++)
|
||||||
cjtag_set_tck_tms_tdi(tck, sequence[i].tck, tms, sequence[i].tms, tdi, sequence[i].tdi);
|
cjtag_set_tck_tms_tdi(tck, sequence[i].tck, tms, sequence[i].tms, tdi, sequence[i].tdi);
|
||||||
|
|
||||||
|
/* If JScan3 mode, configure cJTAG adapter to 4-wire */
|
||||||
|
if (jscan3_mode)
|
||||||
|
ftdi_set_signal(find_signal_by_name("JTAG_SEL"), '1');
|
||||||
|
|
||||||
ftdi_get_signal(tdo, &tdovalue); /* Just to force a flush */
|
ftdi_get_signal(tdo, &tdovalue); /* Just to force a flush */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,6 +1315,18 @@ COMMAND_HANDLER(ftdi_handle_oscan1_mode_command)
|
||||||
command_print(CMD, "oscan1 mode: %s.", oscan1_mode ? "on" : "off");
|
command_print(CMD, "oscan1 mode: %s.", oscan1_mode ? "on" : "off");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(ftdi_handle_jscan3_mode_command)
|
||||||
|
{
|
||||||
|
if (CMD_ARGC > 1)
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
|
if (CMD_ARGC == 1)
|
||||||
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], jscan3_mode);
|
||||||
|
|
||||||
|
command_print(CMD, "jscan3 mode: %s.", jscan3_mode ? "on" : "off");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct command_registration ftdi_subcommand_handlers[] = {
|
static const struct command_registration ftdi_subcommand_handlers[] = {
|
||||||
|
@ -1359,6 +1398,13 @@ static const struct command_registration ftdi_subcommand_handlers[] = {
|
||||||
.help = "set to 'on' to use OScan1 mode for signaling, otherwise 'off' (default is 'off')",
|
.help = "set to 'on' to use OScan1 mode for signaling, otherwise 'off' (default is 'off')",
|
||||||
.usage = "(on|off)",
|
.usage = "(on|off)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "jscan3_mode",
|
||||||
|
.handler = &ftdi_handle_jscan3_mode_command,
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.help = "set to 'on' to use JScan3 mode for signaling, otherwise 'off' (default is 'off')",
|
||||||
|
.usage = "(on|off)",
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue