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

@@ -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
};