Here's another patch I've had kicking around for a while, now cleaned up a
bit.
I was having a problem using an ARM-OCD-USB-H cable where after using the
interactive "frequency" command, the TCK frequency was 5 times what I
wanted.
The ARM-OCD-USB vs ARM-OCD-USB-H cables are wired pretty much the same,
but for the "H" chip on the latter.
The only distinction made in the tap/cable/ft2232.c between the H and
non-H versions is in
calling of ft2232_set_frequency() vs ft2232h_set_frequency() for
ARM-USB-OCD-H. ft2232h_set_frequency() is only called in intitial
setup, and ft2232_set_frequency is called afterwards. The result is
that user-requested TCK frequencies are 5x what the user asked for.
It looks like the driver tables were assuming they could call
ft2232_set_frequency() as a generic thing for either chip. But that's
not correct: the calculation for FT2232H is different once the divider
is disabled to take it out of FT2232 compatibility mode.
This was most clear in the ARM-OCD-USB vs ARM-OCD-USB-H cable drivers,
whose short init routines both call ft2232_armusbocd_init_common
with an is_ft2232h argument of 0 and 1, respectively.
The fix in this patch:
- store the value of is_ft2232h from init time in the params struct
- make a single compatible ft2232_set_frequency() function, which uses
the is_ft2232h flag to determine the base (maximum) rate for the divider
calculation.
another change I considered but decided not to make:
- if the requested frequency is less than the maximum for non-H
parts, we could change back to non-H compatibility mode, 6 MHz base frequency.
- but except for not being able to hit very low frequencies,
this actually is less flexible, as the frequencies available are very coarse
near the 6 MHz limit.
So instead, I left things as they were before; FT2232H chips always use
the 30 MHz base frequency, which results in a minimum frequency of 457
Hz - which should be slow enough for everyone.
Another issue that we don't address: some cables have comments about
maximum frequencies that are lower than the chip's maximum TCK rate
for other hardware reasons. This suggested-maximum is still set in
the init routines, and is still not rememembered. So users invoking
the "frequency" command or python set_frequency() method still need to
be aware of their hardware's limitations when overriding the default TCK
frequency.
One last cleanup included: rather than calling ft2232_set_frequency
(cable, FT2232_MAX_TCK_FREQ); or ft2232_set_frequency (cable,
FT2232H_MAX_TCK_FREQ); in all of the init routines, we can simply call:
ft2232_set_frequency (cable, 0) in all of the init routines, because
ft2232_set_frequency() defaults to setting the maximum frequency. This
makes the code clear that most cables set the default, and makes the few
non-default cases stand out.
Note that when using FT2232H/FT4232H cables, the default of 30 MHz
requires careful attention to the electrical environment of the JTAG
signals. long ribbon cables are likely to be problematic - or at least
seldom work for me.
So users may need to set a lower frequency, and its nice when the
frequency requested is actually what gets set.
From 71532eb4332f4fcfc058cd06b8a4b63e7f77b976 Mon Sep 17 00:00:00 2001
From: Steve Tell <t...@telltronics.org>
Date: Thu, 29 Jun 2017 17:31:38 -0400
Subject: [PATCH] Rework FT2232(H)_set_frequency() and calls. An is_ft2232h
flag is stored n
struct params, so that the correct calculation can be done subsequent
"frequency" commands. Previously, TCK would end up 5x faster than expected
for FT2232/FT4232H cables.
---
urjtag/src/tap/cable/ft2232.c | 95 +++++++++++++++++++++-------------------
1 files changed, 50 insertions(+), 45 deletions(-)
diff --git a/urjtag/src/tap/cable/ft2232.c b/urjtag/src/tap/cable/ft2232.c
index 53e9445..32792af 100644
--- a/urjtag/src/tap/cable/ft2232.c
+++ b/urjtag/src/tap/cable/ft2232.c
@@ -279,6 +279,8 @@ typedef struct
int signals;
urj_tap_cable_cx_cmd_root_t cmd_root;
+ /* is this an FT232H/FT2232H/FT4232H chip? else non-H */
+ int is_ft2232h;
} params_t;
@@ -298,32 +300,48 @@ ft2232h_disable_clockdiv_by5 (urj_cable_t *cable)
}
static void
-ft2232_set_frequency_common (urj_cable_t *cable, uint32_t new_frequency,
uint32_t max_frequency)
+ft2232h_enable_clockdiv_by5 (urj_cable_t *cable)
{
params_t *params = cable->params;
urj_tap_cable_cx_cmd_root_t *cmd_root = ¶ms->cmd_root;
- if (!new_frequency || new_frequency > max_frequency)
- new_frequency = max_frequency;
+ urj_tap_cable_cx_cmd_queue( cmd_root, 0 );
+ urj_tap_cable_cx_cmd_push( cmd_root, ENABLE_CLOCKDIV );
+}
+
+static void
+ft2232_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
+{
+ params_t *params = cable->params;
+ urj_tap_cable_cx_cmd_root_t *cmd_root = ¶ms->cmd_root;
+ uint32_t base_frequency;
+
+ if (params->is_ft2232h)
+ base_frequency = FT2232H_MAX_TCK_FREQ;
+ else
+ base_frequency = FT2232_MAX_TCK_FREQ;
+
+ if (!new_frequency || new_frequency > base_frequency)
+ new_frequency = base_frequency;
- /* update ft2232 frequency if cable setting changed */
+ /* update ft2232(h) frequency if cable setting changed */
if (new_frequency != params->mpsse_frequency)
{
uint32_t div;
- div = max_frequency / new_frequency;
- if (max_frequency % new_frequency)
+ div = base_frequency / new_frequency;
+ if (base_frequency % new_frequency)
div++;
if (div >= (1 << 16))
{
div = (1 << 16) - 1;
urj_warning (_("Warning: Setting lowest supported frequency for
FT2232%s: %d\n"),
- max_frequency == FT2232H_MAX_TCK_FREQ ? "H" : "",
max_frequency/div);
+ params->is_ft2232h ? "H" : "", base_frequency/div);
+ }
+ if (params->is_ft2232h) {
+ ft2232h_disable_clockdiv_by5 (cable);
}
-
- if (max_frequency == FT2232H_MAX_TCK_FREQ)
- ft2232h_disable_clockdiv_by5 (cable);
/* send new divisor to device */
div -= 1;
@@ -335,24 +353,11 @@ ft2232_set_frequency_common (urj_cable_t *cable, uint32_t
new_frequency, uint32_
urj_tap_cable_cx_xfer (cmd_root, &imm_cmd, cable,
URJ_TAP_CABLE_COMPLETELY);
- params->mpsse_frequency = max_frequency / (div + 1);
+ params->mpsse_frequency = base_frequency / (div + 1);
cable->frequency = params->mpsse_frequency;
}
}
-
-static void
-ft2232_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
-{
- ft2232_set_frequency_common (cable, new_frequency, FT2232_MAX_TCK_FREQ);
-}
-
-static void
-ft2232h_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
-{
- ft2232_set_frequency_common (cable, new_frequency, FT2232H_MAX_TCK_FREQ);
-}
-
static int
ft2232_generic_init (urj_cable_t *cable)
{
@@ -384,7 +389,7 @@ ft2232_generic_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = -1; /* not used */
params->bit_reset = -1; /* not used */
@@ -437,7 +442,7 @@ ft2232_jtagkey_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_JTAGKEY_TRST_N_OUT + 8; /* member of HIGH byte
*/
params->bit_reset = BIT_JTAGKEY_SRST_N_OUT + 8; /* member of HIGH byte
*/
@@ -491,10 +496,8 @@ ft2232_armusbocd_init_common (urj_cable_t *cable, int
is_ft2232h)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- if (is_ft2232h)
- ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ);
- else
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
+ params->is_ft2232h = is_ft2232h;
params->bit_trst = BIT_ARMUSBOCD_nTRST + 8; /* member of HIGH byte
*/
params->bit_reset = BIT_ARMUSBOCD_nTSRST + 8; /* member of HIGH byte
*/
@@ -551,12 +554,13 @@ ft2232_gnice_init_common (urj_cable_t *cable, int
is_ft2232h)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
+ params->is_ft2232h = is_ft2232h;
if (is_ft2232h)
/* On ADI boards with the onboard EZKIT Debug Agent, max TCK where
things
work is 15MHz. */
- ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ / 2);
+ ft2232_set_frequency (cable, FT2232H_MAX_TCK_FREQ / 2);
else
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_GNICE_nTRST + 8; /* member of HIGH byte */
params->bit_reset = -1; /* not used */
@@ -620,7 +624,7 @@ ft2232_oocdlinks_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_OOCDLINKS_nTRST + 8; /* member of HIGH byte */
params->bit_reset = BIT_OOCDLINKS_nSRST + 8; /* member of HIGH byte
*/
@@ -669,7 +673,7 @@ ft2232_turtelizer2_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = -1; /* not used */
params->bit_reset = BIT_TURTELIZER2_RST; /* member of LOW byte */
@@ -722,7 +726,7 @@ ft2232_usbjtagrs232_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_USBJTAGRS232_nTRST + 8; /* member of HIGH byte */
params->bit_reset = BIT_USBJTAGRS232_nSRST + 8; /* member of HIGH
byte */
@@ -820,7 +824,7 @@ ft2232_signalyzer_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_SIGNALYZER_nTRST; /* member of LOW byte */
params->bit_reset = BIT_SIGNALYZER_nSRST; /* member of LOW byte */
@@ -866,7 +870,7 @@ ft2232_flyswatter_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_FLYSWATTER_nTRST; /* member of LOW byte */
params->bit_reset = BIT_FLYSWATTER_nSRST; /* member of LOW byte */
@@ -924,7 +928,7 @@ ft2232_usbscarab2_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = BIT_USBSCARAB2_TRST + 8; /* member of HIGH byte */
params->bit_reset = BIT_USBSCARAB2_nSRST + 8; /* member of HIGH byte
*/
@@ -959,8 +963,8 @@ ft2232_ktlink_init (urj_cable_t *cable)
urj_log (URJ_LOG_LEVEL_NORMAL, "nSRST pin state is high...\n");
/* Set some internal parameters such as speed, reset signals, etc. */
- ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ);
- ft2232h_disable_clockdiv_by5 (cable);
+ params->is_ft2232h = 1;
+ ft2232_set_frequency (cable, 0);
params->bit_reset = BIT_KTLINK_SRST + 8; /* member of HIGH byte */
params->signals = URJ_POD_CS_RESET;
@@ -1050,7 +1054,8 @@ ft2232_milkymist_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232h_set_frequency (cable, FT2232H_MAX_TCK_FREQ);
+ params->is_ft2232h = 1;
+ ft2232_set_frequency (cable, 0);
params->bit_trst = -1; /* not used */
params->bit_reset = -1; /* not used */
@@ -1092,7 +1097,7 @@ ft2232_digilenths1_init (urj_cable_t *cable)
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_value);
urj_tap_cable_cx_cmd_push (cmd_root, params->high_byte_dir);
- ft2232_set_frequency (cable, FT2232_MAX_TCK_FREQ);
+ ft2232_set_frequency (cable, 0);
params->bit_trst = -1; /* not used */
params->bit_reset = -1; /* not used */
@@ -2390,7 +2395,7 @@ const urj_cable_driver_t
urj_tap_cable_ft2232_gniceplus_driver = {
ft2232_cable_free,
ft2232_gniceplus_init,
ft2232_gnice_done,
- ft2232h_set_frequency,
+ ft2232_set_frequency,
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
@@ -2570,7 +2575,7 @@ const urj_cable_driver_t
urj_tap_cable_ft2232_ktlink_driver = {
ft2232_cable_free,
ft2232_ktlink_init,
ft2232_ktlink_done,
- ft2232h_set_frequency,
+ ft2232_set_frequency,
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
@@ -2590,7 +2595,7 @@ const urj_cable_driver_t
urj_tap_cable_ft2232_milkymist_driver = {
ft2232_cable_free,
ft2232_milkymist_init,
ft2232_milkymist_done,
- ft2232h_set_frequency,
+ ft2232_set_frequency,
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
--
1.7.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
UrJTAG-development mailing list
UrJTAG-development@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/urjtag-development