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

Reply via email to