> I'm happy with the previous set of patches I submitted (nov 30),
> it's been working well for me for the past couple of weeks
> with no issues.

I had to make some fixes to make it compile.

Could you read over the patch now and write up a commit comment?

To create a patch, try:

git add .
git commit --author="Andrew Leech <coronasen...@gmail.com>"
=> type commit comment
git format-patch HEAD^

-- 
Øyvind Harboe

Can Zylin Consulting help on your project?

US toll free 1-866-980-3434 / International +47 51 63 25 00

http://www.zylin.com/zy1000.html
ARM7 ARM9 ARM11 XScale Cortex
JTAG debugger and flash programmer
From 708c04f66d957cd32c226ce291dc61b35685de60 Mon Sep 17 00:00:00 2001
From: Andrew Leech <coronasen...@gmail.com>
Date: Tue, 30 Nov 2010 10:13:38 +1100
Subject: [PATCH] SVF Chain Handling (was: lpc3131 and Actel FPGA chain programming)

On Wed, Nov 24, 2010 at 12:10 AM, Wookey <woo...@wookware.org> wrote:
> +++ Andrew Leech [2010-11-17 14:02 +1100]:
>>
>> Yep I rewrote the command line parser, so the usage is now:
>> "usage: svf [-tap device.tap] [-quiet] <file>"
>>
>> Arguments are checked in a loop so it will accept switches and <file>
>> in any order. quiet or -quiet are both recognised. And of course, -tap
>> is optional. As such it is now back compatible, much nicer and more
>> flexible. There's also a help switch that simply prints usage in case
>> anyone tries it.
>
> As someone who has previously used svf and xsvf functionality with
> chained devices I'd like to add another 'yes please this is great'
> vote, and thank andrew for his work (I'm glad someone understands
> this stuff :-)
>
> Oddly I have previously found that xsvf files would work even when
> they were generated single but used in a chain (or maybe it was the
> other way round). I was quite suprised about this and assumed that
> openocd was already doing something clever equivalent to the
> functionality this patch provides. But obviously that was just dumb
> luck.
>
> And yes the above syntax is the right way tto do this. Breaking
> existing scripts is something we should work hard to avoid as it can
> make openocd updates in production environments very awkward..
>
> Wookey

Yeah I'm much happier allowing previous syntax to work fine without
modification. I haven't looked at the xsvf module at all, while it
would be neater to bring it in line with this one, or even roll both
of them rolled together, I don't have any xilinx parts or software so
haven't had any call to use it. The xsvf parser or format may very
well have chain functionality built into it, I'm not sure.

Well I've made a whole heap more updates, and eventually realised I
should be splitting them up into separate patches, as many of them are
(or should be) somewhat independent. That was a bit of a hassle, but
it's neater this way.... as well as being openocd policy from what
I've read.

svf_chain_cmd_parser.patch : Main patch, chain tap handling and
updated command parser, mostly the same as earlier submitted patch.
svf_file_handling.patch: converts file handling from open to fopen
etc. Also input files are read as whole lines before parsing.
Debatable whether this is neater code, but it does result in 10% speed
improvement for me, and should be more portable.
svf_progress_indicator.patch: Adds progress indicator (xx% readout)
when (-)progress flag added to command line. this works in both quiet
and non-quiet modes. This patch is dependent on
svf_file_handling.patch being previously applied.
svf_time_output_format.patch: time taken readout at end of svf
operation converted from direct ms output to minutes-seconds-ms output
for better readability.

I've used this newer version to program my a3p125 and a3p060 parts on
identical chains with lpc3131 multiple times with different flags and
haven't had any problems.

One significant finding is the time difference when non-quiet
(default) mode is used, particularly on windows the verbose output
slows the overall operation down a _lot_. I'm talking 1mins 19sec for
quiet compared to 6mins 40sec on verbose. The time difference on linux
was much much less severe but I haven't tested it with the full length
file, but but on a much shorter test file it was a difference of 8
seconds to 14 seconds. The programming works fine either way, just
printing the lines takes some time. This slow file is ~290,000 lines
of svf, so not surprising that it takes some time to print all this to
console.

Andrew
---
 src/svf/svf.c |  369 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 291 insertions(+), 78 deletions(-)

diff --git a/src/svf/svf.c b/src/svf/svf.c
index 62e2324..054413a 100644
--- a/src/svf/svf.c
+++ b/src/svf/svf.c
@@ -206,21 +206,33 @@ struct svf_check_tdo_para
 static struct svf_check_tdo_para *svf_check_tdo_para = NULL;
 static int svf_check_tdo_para_index = 0;
 
-static int svf_read_command_from_file(int fd);
+static int svf_read_command_from_file(FILE * fd);
 static int svf_check_tdo(void);
 static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len);
 static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str);
 
-static int svf_fd = 0;
+static FILE * svf_fd = NULL;
+static char * svf_read_line = NULL;
+static size_t svf_read_line_size = 0;
 static char *svf_command_buffer = NULL;
-static int svf_command_buffer_size = 0;
+static size_t svf_command_buffer_size = 0;
 static int svf_line_number = 1;
+static int svf_getline (char **lineptr, size_t *n, FILE *stream);
 
 #define SVF_MAX_BUFFER_SIZE_TO_COMMIT	(4 * 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;
 
+// Targetting particular tap
+static int svf_tap_is_specified = 0;
+static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi);
+
+// Progress Indicator
+static int svf_progress_enabled = 0;
+static long svf_total_lines = 0;
+static int svf_percentage = 0;
+static int svf_last_printed_percentage = -1;
 
 static void svf_free_xxd_para(struct svf_xxr_para *para)
 {
@@ -301,46 +313,71 @@ int svf_add_statemove(tap_state_t state_to)
 
 COMMAND_HANDLER(handle_svf_command)
 {
-#define SVF_NUM_OF_OPTIONS			1
+#define SVF_MIN_NUM_OF_OPTIONS			1
+#define SVF_MAX_NUM_OF_OPTIONS			5
+#define USAGE [-tap device.tap] <file> [quiet] [progress]
+#define PRINT_USAGE	command_print(CMD_CTX, "svf USAGE")
 	int command_num = 0;
 	int ret = ERROR_OK;
-	long long time_ago;
+	long long time_measure_ms;
+	int time_measure_s, time_measure_m;
+
+	/* use NULL to indicate a "plain" svf file which accounts for
+	   any additional devices in the scan chain, otherwise the device
+	   that should be affected
+	*/
+	struct jtag_tap *tap = NULL;
 
-	if ((CMD_ARGC < 1) || (CMD_ARGC > (1 + SVF_NUM_OF_OPTIONS)))
+	if ((CMD_ARGC < SVF_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > SVF_MAX_NUM_OF_OPTIONS))
 	{
-		command_print(CMD_CTX, "usage: svf <file> [quiet]");
+		PRINT_USAGE;
 		return ERROR_FAIL;
 	}
 
-	// parse variant
+	// parse command line
 	svf_quiet = 0;
-	for (unsigned i = 1; i < CMD_ARGC; i++)
+	for (unsigned int i = 0; i < CMD_ARGC; i++)
 	{
-		if (!strcmp(CMD_ARGV[i], "quiet"))
+		if (strcmp(CMD_ARGV[i], "-tap") == 0)
+		{
+			tap = jtag_tap_by_string(CMD_ARGV[i+1]);
+			if (!tap)
+			{
+				command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i+1]);
+				return ERROR_FAIL;
+			}
+			i++;
+		}
+		else if ((strcmp(CMD_ARGV[i], "quiet") == 0) || (strcmp(CMD_ARGV[i], "-quiet") == 0))
 		{
 			svf_quiet = 1;
 		}
-		else
+		else if ((strcmp(CMD_ARGV[i], "progress") == 0) || (strcmp(CMD_ARGV[i], "-progress") == 0))
 		{
-			LOG_ERROR("unknown variant for svf: %s", CMD_ARGV[i]);
-
+			svf_progress_enabled = 1;
+		}
+		else if ((svf_fd = fopen(CMD_ARGV[i], "r")) == NULL)
+		{
+			int err = errno;
+			PRINT_USAGE;
+			command_print(CMD_CTX, "open(\"%s\"): %s", CMD_ARGV[i], strerror(err));
 			// no need to free anything now
 			return ERROR_FAIL;
 		}
+		else
+		{
+			LOG_USER("svf processing file: \"%s\"", CMD_ARGV[i]);
+		}
 	}
 
-	if ((svf_fd = open(CMD_ARGV[0], O_RDONLY)) < 0)
+	if (svf_fd == NULL)
 	{
-		command_print(CMD_CTX, "file \"%s\" not found", CMD_ARGV[0]);
-
-		// no need to free anything now
+		PRINT_USAGE;
 		return ERROR_FAIL;
 	}
 
-	LOG_USER("svf processing file: \"%s\"", CMD_ARGV[0]);
-
 	// get time
-	time_ago = timeval_ms();
+	time_measure_ms = timeval_ms();
 
 	// init
 	svf_line_number = 1;
@@ -388,8 +425,97 @@ COMMAND_HANDLER(handle_svf_command)
 	// TAP_RESET
 	jtag_add_tlr();
 
+	if (tap)
+	{
+		/* Tap is specified, set header/trailer paddings */
+		int header_ir_len = 0, header_dr_len = 0, trailer_ir_len = 0, trailer_dr_len = 0;
+		struct jtag_tap *check_tap;
+
+		svf_tap_is_specified = 1;
+
+		for (check_tap = jtag_all_taps(); check_tap; check_tap = check_tap->next_tap) {
+			if (check_tap->abs_chain_position < tap->abs_chain_position)
+			{
+				//Header
+				header_ir_len += check_tap->ir_length;
+				header_dr_len ++;
+			}
+			else if (check_tap->abs_chain_position > tap->abs_chain_position)
+			{
+				//Trailer
+				trailer_ir_len += check_tap->ir_length;
+				trailer_dr_len ++;
+			}
+		}
+
+		// HDR %d TDI (0)
+		if (ERROR_OK != svf_set_padding(&svf_para.hdr_para, header_dr_len, 0))
+		{
+			LOG_ERROR("failed to set data header");
+			return ERROR_FAIL;
+		}
+
+		// HIR %d TDI (0xFF)
+		if (ERROR_OK != svf_set_padding(&svf_para.hir_para, header_ir_len, 0xFF))
+		{
+			LOG_ERROR("failed to set instruction header");
+			return ERROR_FAIL;
+		}
+
+		// TDR %d TDI (0)
+		if (ERROR_OK != svf_set_padding(&svf_para.tdr_para, trailer_dr_len, 0))
+		{
+			LOG_ERROR("failed to set data trailer");
+			return ERROR_FAIL;
+		}
+
+		// TIR %d TDI (0xFF)
+		if (ERROR_OK != svf_set_padding(&svf_para.tir_para, trailer_ir_len, 0xFF))
+		{
+			LOG_ERROR("failed to set instruction trailer");
+			return ERROR_FAIL;
+		}
+
+	}
+
+	if (svf_progress_enabled)
+	{
+		// Count total lines in file.
+		while ( ! feof (svf_fd) )
+		 {
+		   svf_getline (&svf_command_buffer, &svf_command_buffer_size, svf_fd);
+		   svf_total_lines++;
+		 }
+		rewind(svf_fd);
+	}
 	while (ERROR_OK == svf_read_command_from_file(svf_fd))
 	{
+		// Log Output
+		if (svf_quiet)
+		{
+			if (svf_progress_enabled)
+			{
+				svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5;
+				if (svf_last_printed_percentage != svf_percentage)
+				{
+					LOG_USER_N("\r%d%%    ", svf_percentage);
+					svf_last_printed_percentage = svf_percentage;
+				}
+			}
+		}
+		else
+		{
+			if (svf_progress_enabled)
+			{
+				svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5;
+				LOG_USER_N("%3d%%  %s", svf_percentage, svf_read_line);
+			}
+			else
+			{
+				LOG_USER_N("%s",svf_read_line);
+			}
+		}
+			// Run Command
 		if (ERROR_OK != svf_run_command(CMD_CTX, svf_command_buffer))
 		{
 			LOG_ERROR("fail to run command at line %d", svf_line_number);
@@ -408,11 +534,19 @@ COMMAND_HANDLER(handle_svf_command)
 	}
 
 	// print time
-	command_print(CMD_CTX, "%lld ms used", timeval_ms() - time_ago);
+	time_measure_ms = timeval_ms() - time_measure_ms;
+	time_measure_s = time_measure_ms / 1000;
+	time_measure_ms %= 1000;
+	time_measure_m = time_measure_s / 60;
+	time_measure_s %= 60;
+	if (time_measure_ms < 1000)
+	{
+		command_print(CMD_CTX, "\r\nTime used: %dm%ds%lldms ", time_measure_m, time_measure_s, time_measure_ms);
+	}
 
 free_all:
 
-	close(svf_fd);
+	fclose(svf_fd);
 	svf_fd = 0;
 
 	// free buffers
@@ -465,36 +599,91 @@ free_all:
 	return ret;
 }
 
+static int svf_getline (char **lineptr, size_t *n, FILE *stream)
+{
+#define MIN_CHUNK 16	//Buffer is increased by this size each time as required
+  size_t i = 0;
+
+  if (*lineptr == NULL)
+    {
+      *n = MIN_CHUNK;
+      *lineptr = (char *)malloc (*n);
+      if (!*lineptr)
+        {
+		  return -1;
+        }
+    }
+
+	(*lineptr)[0] = fgetc(stream);
+	while ((*lineptr)[i] != '\n')
+	{
+		(*lineptr)[++i] = fgetc(stream);
+		if (feof(stream))
+		{
+			(*lineptr)[0] = 0;
+			return -1;
+		}
+		if ((i + 2) > *n)
+		{
+			*n += MIN_CHUNK;
+			*lineptr = realloc(*lineptr, *n);
+		}
+	}
+
+	(*lineptr)[++i] = 0;
+
+	return sizeof(*lineptr);
+}
+
 #define SVFP_CMD_INC_CNT			1024
-static int svf_read_command_from_file(int fd)
+static int svf_read_command_from_file(FILE * fd)
 {
 	unsigned char ch;
-	char *tmp_buffer = NULL;
-	int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
+	int i = 0;
+	size_t cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
 
-	while (!cmd_ok && (read(fd, &ch, 1) > 0))
+	if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+	{
+		return ERROR_FAIL;
+	}
+	svf_line_number++;
+	ch = svf_read_line[0];
+	while (!cmd_ok && (ch != 0))
 	{
 		switch (ch)
 		{
 		case '!':
 			slash = 0;
-			comment = 1;
+			if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+			{
+				return ERROR_FAIL;
+			}
+			svf_line_number++;
+			i = -1;
 			break;
 		case '/':
 			if (++slash == 2)
 			{
-				comment = 1;
+				slash = 0;
+				if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+				{
+					return ERROR_FAIL;
+				}
+				svf_line_number++;
+				i = -1;
 			}
 			break;
 		case ';':
 			slash = 0;
-			if (!comment)
-			{
-				cmd_ok = 1;
-			}
+			cmd_ok = 1;
 			break;
 		case '\n':
 			svf_line_number++;
+			if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+			{
+				return ERROR_FAIL;
+			}
+			i = -1;
 		case '\r':
 			slash = 0;
 			comment = 0;
@@ -502,54 +691,40 @@ static int svf_read_command_from_file(int fd)
 			if (!cmd_pos)
 				break;
 		default:
-			if (!comment)
+			/* The parsing code currently expects a space
+			 * before parentheses -- "TDI (123)".  Also a
+			 * space afterwards -- "TDI (123) TDO(456)".
+			 * But such spaces are optional... instead of
+			 * parser updates, cope with that by adding the
+			 * spaces as needed.
+			 *
+			 * Ensure there are 3 bytes available, for:
+			 *  - current character
+			 *  - added space.
+			 *  - terminating NUL ('\0')
+			 */
+			if ((cmd_pos + 2) >= svf_command_buffer_size)
 			{
-				/* The parsing code currently expects a space
-				 * before parentheses -- "TDI (123)".  Also a
-				 * space afterwards -- "TDI (123) TDO(456)".
-				 * But such spaces are optional... instead of
-				 * parser updates, cope with that by adding the
-				 * spaces as needed.
-				 *
-				 * Ensure there are 3 bytes available, for:
-				 *  - current character
-				 *  - added space.
-				 *  - terminating NUL ('\0')
-				 */
-				if ((cmd_pos + 2) >= svf_command_buffer_size)
+				svf_command_buffer = realloc(svf_command_buffer, (cmd_pos + 2));
+				if (svf_command_buffer == NULL)
 				{
-					/* REVISIT use realloc(); simpler */
-					tmp_buffer = malloc(
-							svf_command_buffer_size
-							+ SVFP_CMD_INC_CNT);
-					if (NULL == tmp_buffer)
-					{
-						LOG_ERROR("not enough memory");
-						return ERROR_FAIL;
-					}
-					if (svf_command_buffer_size > 0)
-						memcpy(tmp_buffer,
-							svf_command_buffer,
-							svf_command_buffer_size);
-					if (svf_command_buffer != NULL)
-						free(svf_command_buffer);
-					svf_command_buffer = tmp_buffer;
-					svf_command_buffer_size += SVFP_CMD_INC_CNT;
-					tmp_buffer = NULL;
+					LOG_ERROR("not enough memory");
+					return ERROR_FAIL;
 				}
+			}
 
-				/* insert a space before '(' */
-				if ('(' == ch)
-					svf_command_buffer[cmd_pos++] = ' ';
+			/* insert a space before '(' */
+			if ('(' == ch)
+				svf_command_buffer[cmd_pos++] = ' ';
 
-				svf_command_buffer[cmd_pos++] = (char)toupper(ch);
+			svf_command_buffer[cmd_pos++] = (char)toupper(ch);
 
-				/* insert a space after ')' */
-				if (')' == ch)
-					svf_command_buffer[cmd_pos++] = ' ';
-			}
+			/* insert a space after ')' */
+			if (')' == ch)
+				svf_command_buffer[cmd_pos++] = ' ';
 			break;
 		}
+		ch = svf_read_line[++i];
 	}
 
 	if (cmd_ok)
@@ -645,6 +820,19 @@ static int svf_adjust_array_length(uint8_t **arr, int orig_bit_len, int new_bit_
 	return ERROR_OK;
 }
 
+static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi)
+{
+	int error = ERROR_OK;
+	error |= svf_adjust_array_length(&para->tdi, para->len, len);
+	memset(para->tdi, tdi, (len + 7) >> 3);
+	error |= svf_adjust_array_length(&para->tdo, para->len, len);
+	error |= svf_adjust_array_length(&para->mask, para->len, len);
+	para->len = len;
+	para->data_mask = XXR_TDI;
+
+	return error;
+}
+
 static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_len, int bit_len)
 {
 	int i, str_len = strlen(str), str_hbyte_len = (bit_len + 3) >> 2;
@@ -803,11 +991,8 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
 	struct scan_field field;
 	// for STATE
 	tap_state_t *path = NULL, state;
-
-	if (!svf_quiet)
-	{
-		LOG_USER("%s", svf_command_buffer);
-	}
+	// flag padding commands skipped due to -tap command
+	int padding_command_skipped = 0;
 
 	if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu))
 	{
@@ -886,15 +1071,35 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
 		}
 		break;
 	case HDR:
+		if (svf_tap_is_specified)
+		{
+			padding_command_skipped = 1;
+			break;
+		}
 		xxr_para_tmp = &svf_para.hdr_para;
 		goto XXR_common;
 	case HIR:
+		if (svf_tap_is_specified)
+		{
+			padding_command_skipped = 1;
+			break;
+		}
 		xxr_para_tmp = &svf_para.hir_para;
 		goto XXR_common;
 	case TDR:
+		if (svf_tap_is_specified)
+		{
+			padding_command_skipped = 1;
+			break;
+		}
 		xxr_para_tmp = &svf_para.tdr_para;
 		goto XXR_common;
 	case TIR:
+		if (svf_tap_is_specified)
+		{
+			padding_command_skipped = 1;
+			break;
+		}
 		xxr_para_tmp = &svf_para.tir_para;
 		goto XXR_common;
 	case SDR:
@@ -1454,6 +1659,14 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
 		break;
 	}
 
+	if (!svf_quiet)
+	{
+		if (padding_command_skipped)
+		{
+			LOG_USER("(Above Padding command skipped, as per -tap argument)");
+		}
+	}
+
 	if (debug_level >= LOG_LVL_DEBUG)
 	{
 		// for convenient debugging, execute tap if possible
@@ -1498,7 +1711,7 @@ static const struct command_registration svf_command_handlers[] = {
 		.handler = handle_svf_command,
 		.mode = COMMAND_EXEC,
 		.help = "Runs a SVF file.",
-		.usage = "filename ['quiet']",
+		.usage = "USAGE",
 	},
 	COMMAND_REGISTRATION_DONE
 };
-- 
1.7.0.4

_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to