jtag ftdi: sample TDO on falling edge of TCK

Due to signal propagation delays, sampling TDO on rising TCK can become
quite peculiar at fast TCK rates. However, FTDI chips offer a possiblity
to sample TDO on falling edge. With this change, stable operation can be
achieved at 30MHz clock even over 10cm ribbon cable.

Change-Id: Icaf240535dae15512e3c60a944e22a5fbc1b0b06
Signed-off-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-on: http://openocd.zylin.com/3180
Tested-by: jenkins
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
This commit is contained in:
Matthias Welwarsky 2016-01-19 22:36:54 +01:00 committed by Andreas Fritiofson
parent de23931162
commit e026d3ff1b
2 changed files with 60 additions and 9 deletions

View File

@ -2610,8 +2610,22 @@ Set a previously defined signal to the specified level.
@end itemize
@end deffn
@deffn {Command} {ftdi_tdo_sample_edge} @option{rising}|@option{falling}
Configure TCK edge at which the adapter samples the value of the TDO signal
Due to signal propagation delays, sampling TDO on rising TCK can become quite
peculiar at high JTAG clock speeds. However, FTDI chips offer a possiblity to sample
TDO on falling edge of TCK. With some board/adapter configurations, this may increase
stability at higher JTAG clocks.
@itemize @minus
@item @option{rising}, sample TDO on rising edge of TCK - this is the default
@item @option{falling}, sample TDO on falling edge of TCK
@end itemize
@end deffn
For example adapter definitions, see the configuration files shipped in the
@file{interface/ftdi} directory.
@end deffn
@deffn {Interface Driver} {remote_bitbang}

View File

@ -86,11 +86,13 @@
#include "mpsse.h"
#define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
#define JTAG_MODE_ALT (LSB_FIRST | NEG_EDGE_IN | NEG_EDGE_OUT)
#define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
static char *ftdi_device_desc;
static char *ftdi_serial;
static uint8_t ftdi_channel;
static uint8_t ftdi_jtag_mode = JTAG_MODE;
static bool swd_mode;
@ -244,7 +246,7 @@ static void move_to_state(tap_state_t goal_state)
0,
tms_count,
false,
JTAG_MODE);
ftdi_jtag_mode);
}
static int ftdi_speed(int speed)
@ -257,6 +259,9 @@ static int ftdi_speed(int speed)
return retval;
}
if (!swd_mode && speed >= 10000000 && ftdi_jtag_mode != JTAG_MODE_ALT)
LOG_INFO("ftdi: if you experience problems at higher adapter clocks, try "
"the command \"ftdi_tdo_sample_edge falling\"");
return ERROR_OK;
}
@ -304,7 +309,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd)
while (i > 0) {
/* there are no state transitions in this code, so omit state tracking */
unsigned this_len = i > 7 ? 7 : i;
mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, JTAG_MODE);
mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, ftdi_jtag_mode);
i -= this_len;
}
@ -344,7 +349,7 @@ static void ftdi_execute_tms(struct jtag_command *cmd)
0,
cmd->cmd.tms->num_bits,
false,
JTAG_MODE);
ftdi_jtag_mode);
}
static void ftdi_execute_pathmove(struct jtag_command *cmd)
@ -391,7 +396,7 @@ static void ftdi_execute_pathmove(struct jtag_command *cmd)
0,
bit_count,
false,
JTAG_MODE);
ftdi_jtag_mode);
bit_count = 0;
}
}
@ -446,7 +451,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
field->in_value,
0,
field->num_bits - 1,
JTAG_MODE);
ftdi_jtag_mode);
uint8_t last_bit = 0;
if (field->out_value)
bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1);
@ -458,14 +463,14 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
field->num_bits - 1,
1,
last_bit,
JTAG_MODE);
ftdi_jtag_mode);
tap_set_state(tap_state_transition(tap_get_state(), 1));
mpsse_clock_tms_cs_out(mpsse_ctx,
&tms_bits,
1,
1,
last_bit,
JTAG_MODE);
ftdi_jtag_mode);
tap_set_state(tap_state_transition(tap_get_state(), 0));
} else
mpsse_clock_data(mpsse_ctx,
@ -474,7 +479,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
field->in_value,
0,
field->num_bits,
JTAG_MODE);
ftdi_jtag_mode);
}
if (tap_get_state() != tap_get_end_state())
@ -553,7 +558,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd)
while (num_cycles > 0) {
/* there are no state transitions in this code, so omit state tracking */
unsigned this_len = num_cycles > 7 ? 7 : num_cycles;
mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, JTAG_MODE);
mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, ftdi_jtag_mode);
num_cycles -= this_len;
}
@ -832,6 +837,29 @@ COMMAND_HANDLER(ftdi_handle_vid_pid_command)
return ERROR_OK;
}
COMMAND_HANDLER(ftdi_handle_tdo_sample_edge_command)
{
Jim_Nvp *n;
static const Jim_Nvp nvp_ftdi_jtag_modes[] = {
{ .name = "rising", .value = JTAG_MODE },
{ .name = "falling", .value = JTAG_MODE_ALT },
{ .name = NULL, .value = -1 },
};
if (CMD_ARGC > 0) {
n = Jim_Nvp_name2value_simple(nvp_ftdi_jtag_modes, CMD_ARGV[0]);
if (n->name == NULL)
return ERROR_COMMAND_SYNTAX_ERROR;
ftdi_jtag_mode = n->value;
}
n = Jim_Nvp_value2name_simple(nvp_ftdi_jtag_modes, ftdi_jtag_mode);
command_print(CMD_CTX, "ftdi samples TDO on %s edge of TCK", n->name);
return ERROR_OK;
}
static const struct command_registration ftdi_command_handlers[] = {
{
.name = "ftdi_device_desc",
@ -884,6 +912,15 @@ static const struct command_registration ftdi_command_handlers[] = {
.help = "the vendor ID and product ID of the FTDI device",
.usage = "(vid pid)* ",
},
{
.name = "ftdi_tdo_sample_edge",
.handler = &ftdi_handle_tdo_sample_edge_command,
.mode = COMMAND_ANY,
.help = "set which TCK clock edge is used for sampling TDO "
"- default is rising-edge (Setting to falling-edge may "
"allow signalling speed increase)",
.usage = "(rising|falling)",
},
COMMAND_REGISTRATION_DONE
};