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:
parent
de23931162
commit
e026d3ff1b
|
@ -2610,8 +2610,22 @@ Set a previously defined signal to the specified level.
|
||||||
@end itemize
|
@end itemize
|
||||||
@end deffn
|
@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
|
For example adapter definitions, see the configuration files shipped in the
|
||||||
@file{interface/ftdi} directory.
|
@file{interface/ftdi} directory.
|
||||||
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Driver} {remote_bitbang}
|
@deffn {Interface Driver} {remote_bitbang}
|
||||||
|
|
|
@ -86,11 +86,13 @@
|
||||||
#include "mpsse.h"
|
#include "mpsse.h"
|
||||||
|
|
||||||
#define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
|
#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)
|
#define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
|
||||||
|
|
||||||
static char *ftdi_device_desc;
|
static char *ftdi_device_desc;
|
||||||
static char *ftdi_serial;
|
static char *ftdi_serial;
|
||||||
static uint8_t ftdi_channel;
|
static uint8_t ftdi_channel;
|
||||||
|
static uint8_t ftdi_jtag_mode = JTAG_MODE;
|
||||||
|
|
||||||
static bool swd_mode;
|
static bool swd_mode;
|
||||||
|
|
||||||
|
@ -244,7 +246,7 @@ static void move_to_state(tap_state_t goal_state)
|
||||||
0,
|
0,
|
||||||
tms_count,
|
tms_count,
|
||||||
false,
|
false,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ftdi_speed(int speed)
|
static int ftdi_speed(int speed)
|
||||||
|
@ -257,6 +259,9 @@ static int ftdi_speed(int speed)
|
||||||
return retval;
|
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;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +309,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd)
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
/* there are no state transitions in this code, so omit state tracking */
|
/* there are no state transitions in this code, so omit state tracking */
|
||||||
unsigned this_len = i > 7 ? 7 : i;
|
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;
|
i -= this_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +349,7 @@ static void ftdi_execute_tms(struct jtag_command *cmd)
|
||||||
0,
|
0,
|
||||||
cmd->cmd.tms->num_bits,
|
cmd->cmd.tms->num_bits,
|
||||||
false,
|
false,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftdi_execute_pathmove(struct jtag_command *cmd)
|
static void ftdi_execute_pathmove(struct jtag_command *cmd)
|
||||||
|
@ -391,7 +396,7 @@ static void ftdi_execute_pathmove(struct jtag_command *cmd)
|
||||||
0,
|
0,
|
||||||
bit_count,
|
bit_count,
|
||||||
false,
|
false,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
bit_count = 0;
|
bit_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,7 +451,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
|
||||||
field->in_value,
|
field->in_value,
|
||||||
0,
|
0,
|
||||||
field->num_bits - 1,
|
field->num_bits - 1,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
uint8_t last_bit = 0;
|
uint8_t last_bit = 0;
|
||||||
if (field->out_value)
|
if (field->out_value)
|
||||||
bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1);
|
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,
|
field->num_bits - 1,
|
||||||
1,
|
1,
|
||||||
last_bit,
|
last_bit,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
tap_set_state(tap_state_transition(tap_get_state(), 1));
|
tap_set_state(tap_state_transition(tap_get_state(), 1));
|
||||||
mpsse_clock_tms_cs_out(mpsse_ctx,
|
mpsse_clock_tms_cs_out(mpsse_ctx,
|
||||||
&tms_bits,
|
&tms_bits,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
last_bit,
|
last_bit,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
tap_set_state(tap_state_transition(tap_get_state(), 0));
|
tap_set_state(tap_state_transition(tap_get_state(), 0));
|
||||||
} else
|
} else
|
||||||
mpsse_clock_data(mpsse_ctx,
|
mpsse_clock_data(mpsse_ctx,
|
||||||
|
@ -474,7 +479,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
|
||||||
field->in_value,
|
field->in_value,
|
||||||
0,
|
0,
|
||||||
field->num_bits,
|
field->num_bits,
|
||||||
JTAG_MODE);
|
ftdi_jtag_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tap_get_state() != tap_get_end_state())
|
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) {
|
while (num_cycles > 0) {
|
||||||
/* there are no state transitions in this code, so omit state tracking */
|
/* there are no state transitions in this code, so omit state tracking */
|
||||||
unsigned this_len = num_cycles > 7 ? 7 : num_cycles;
|
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;
|
num_cycles -= this_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,6 +837,29 @@ COMMAND_HANDLER(ftdi_handle_vid_pid_command)
|
||||||
return ERROR_OK;
|
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[] = {
|
static const struct command_registration ftdi_command_handlers[] = {
|
||||||
{
|
{
|
||||||
.name = "ftdi_device_desc",
|
.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",
|
.help = "the vendor ID and product ID of the FTDI device",
|
||||||
.usage = "(vid pid)* ",
|
.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
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue