Hello,
In attempting to use openocd with an Amontec JTAG key to program a
Xilinx FPGA, I encountered a series of issues I though others might be
interested in. I don't have sensible proposed solutions for any of the
problems I encountered, but perhaps someone on this mailing list is
interested all the same.
The SVF file is a few SVF commands, with one very large SDR command in
the middle; something like:
SDR 27025501 TDI (00000000800000008000 ... ) SMASK (1fffffff ...
This was generated by some Xilinx tools I believe. The file was roughly
13MB large, most of which was this one SDR command.
The first problem is that openocd failed to read the SVF file; with the
error message:
buffer is not enough, report to author
Not sure which author this is talking about, so I thought I'd inspect
the code. And so the saga began...
This code here is within an "#if 1" clause, the "#else" looks like it
had code to dynamically allocate enough memory for the command.
Unfortunately, just changing the "#if 1" to an "#if 0" was not enough -
I tried this once I got things working and ended up with strange TDO
check errors. Hence I ended up just making the static buffer size large
enough for my needs (16MB).
On it's own, this isn't quite enough: the data gets copied into some
sort of "command" object allocated in cmd_queue_alloc(). I patched this
code to handle allocating sizes of > CMD_QUEUE_PAGE_SIZE; without this I
got a segfault in memcpy() as there is an un-checked memcpy() into the
memory on this command.
At this point, openocd no longer crashes with my SVF file. Unfortunately
I started hitting USB/FTDI errors.
Using the open source libftdi (version 0.17) driver I get the following:
Error: ftdi_write_data: usb bulk write failed
Error: couldn't write MPSSE commands to FT2232
Digging into this some more, I found the error was -110 (ETIMEDOUT).
Using instead the libftd2xx binary driver, I got:
Error: couldn't read enough bytes from FT2232 device (2 < 3)
Error: couldn't read from FT2232
Giving up on that and going back to the libftdi driver, I found the
following mailing list thread, which suggested that the buffer size was
too large:
http://lists.berlios.de/pipermail/openocd-development/2009-February/004695.html
Reducing this buffer size to 768 (from 128K!) did not immediately fix
the problem at all. Instead I got:
openocd: ft2232.c:403: buffer_write: Assertion `(unsigned)
ft2232_buffer_size < (unsigned) 768' failed.
I dug into the ft2232_large_scan() function and found this line which
looks like it attempts to do 64K writes at a time:
thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
Changing the 64K in that line to instead use 768 made no difference. I
tried 512. This worked; no more assertion. I don't have justification
for why I needed 512 here.
At this stage I got the libftdi driver giving the same error message as
the libftd2xx driver: trying to read 3 bytes, only got 2 bytes. This
seemed like progress so I moved on to diagnosing this error.
I guessed it was just an off-by-one error, and found the following
lines, which looked suspicious:
if (type != SCAN_OUT)
thisrun_read += 1;
I commented these two lines out, with again no basis other than guess-work.
Now it worked perfectly.
The patch to make all this work in the end was rather small; see attached.
Regards,
Sam
diff -ru ./openocd-0.5.0/src/jtag/commands.c ./openocd-0.5.0-hacked/src/jtag/commands.c
--- ./openocd-0.5.0/src/jtag/commands.c 2011-08-09 06:34:19.000000000 +0100
+++ ./openocd-0.5.0-hacked/src/jtag/commands.c 2011-08-26 17:23:36.270859282 +0100
@@ -110,7 +110,10 @@
{
*p_page = malloc(sizeof(struct cmd_queue_page));
(*p_page)->used = 0;
- (*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
+ if (size < CMD_QUEUE_PAGE_SIZE)
+ (*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
+ else
+ (*p_page)->address = malloc(size);
(*p_page)->next = NULL;
}
diff -ru ./openocd-0.5.0/src/jtag/drivers/ft2232.c ./openocd-0.5.0-hacked/src/jtag/drivers/ft2232.c
--- ./openocd-0.5.0/src/jtag/drivers/ft2232.c 2011-08-09 06:34:19.000000000 +0100
+++ ./openocd-0.5.0-hacked/src/jtag/drivers/ft2232.c 2011-08-26 17:57:31.520616715 +0100
@@ -385,7 +385,8 @@
#define FT2232_BUFFER_READ_QUEUE_SIZE (64*4)
#endif
-#define FT2232_BUFFER_SIZE 131072
+// #define FT2232_BUFFER_SIZE 131072
+#define FT2232_BUFFER_SIZE 768
static uint8_t* ft2232_buffer = NULL;
static int ft2232_buffer_size = 0;
@@ -1192,7 +1193,8 @@
/* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */
}
- thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+ //thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+ thisrun_bytes = (num_bytes > 513) ? 512 : (num_bytes - 1);
thisrun_read = thisrun_bytes;
num_bytes -= thisrun_bytes;
buffer_write((uint8_t) (thisrun_bytes - 1));
@@ -1321,8 +1323,8 @@
clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit);
}
- if (type != SCAN_OUT)
- thisrun_read += 1;
+ //if (type != SCAN_OUT)
+ // thisrun_read += 1;
if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
{
diff -ru ./openocd-0.5.0/src/svf/svf.c ./openocd-0.5.0-hacked/src/svf/svf.c
--- ./openocd-0.5.0/src/svf/svf.c 2011-08-09 06:34:19.000000000 +0100
+++ ./openocd-0.5.0-hacked/src/svf/svf.c 2011-08-26 17:39:27.280340300 +0100
@@ -219,7 +219,8 @@
static int svf_line_number = 1;
static int svf_getline (char **lineptr, size_t *n, FILE *stream);
-#define SVF_MAX_BUFFER_SIZE_TO_COMMIT (1024 * 1024)
+// #define SVF_MAX_BUFFER_SIZE_TO_COMMIT (1024 * 1024)
+#define SVF_MAX_BUFFER_SIZE_TO_COMMIT (16 * 1024 * 1024)
static uint8_t *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
static int svf_buffer_index = 0, svf_buffer_size = 0;
static int svf_quiet = 0;
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development