aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Welwarsky <matthias@welwarsky.de>2016-01-19 22:36:54 +0100
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>2016-02-13 23:04:49 +0000
commite026d3ff1bf31f531bf97bc151b4693a6a52f8e7 (patch)
treeb4e41251ac76c393729935d183cb321c24191759
parentde239311629e684e88a2e60d9d19c77d1fc35ae5 (diff)
downloadriscv-openocd-e026d3ff1bf31f531bf97bc151b4693a6a52f8e7.zip
riscv-openocd-e026d3ff1bf31f531bf97bc151b4693a6a52f8e7.tar.gz
riscv-openocd-e026d3ff1bf31f531bf97bc151b4693a6a52f8e7.tar.bz2
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>
-rw-r--r--doc/openocd.texi14
-rw-r--r--src/jtag/drivers/ftdi.c55
2 files changed, 60 insertions, 9 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 78298b8..2e45114 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -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}
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
index d8c7d64..7f11391 100644
--- a/src/jtag/drivers/ftdi.c
+++ b/src/jtag/drivers/ftdi.c
@@ -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
};