On Sunday 07 March 2010, Michal Demin wrote:
> Copy of this patch can by
> downloaded here: http://robot.mysteria.cz/buspirate.patch

Better ... I can apply that one.

I attach a version with minor fixes, mostly from running "checkpatch"
so it's whitespace and linelength stuff. But also added a NEWS entry.

A few more issues I saw while fixing those:

        - You're not using DEBUG_JTAG_IO()

        - You're writing directly to stderr instead of using LOG_DEBUG

        - the "/dev/ttyUSB0" default is troublesome ... loses on MS-Windows
          and likely other systems, even on Linux with multiple usb-serial
          adapters.  Best to just not have a default if makes trouble.

Can you send either an updated patch with those fixes, or just a small
fixup patch for those issues?

support Bus Pirate as a JTAG adapter.

This includes a driver and matching config file.  This support needs to be
enabled through the initial "configure" (use "--enable-buspirate").

[ [email protected]: linelength and whitespace fixes, NEWS ]

# ttyUSB0 -- bad default; better to not have one
# much acess to "stderr" instead of LOG_DEBUG
# should use the DEBUG_JTAG_IO() wrapper
# ... adds #ifdeffery (ugh)

---
 NEWS                         |    1 
 configure.in                 |   11 
 doc/openocd.texi             |    3 
 src/jtag/drivers/Makefile.am |    3 
 src/jtag/drivers/buspirate.c |  987 +++++++++++++++++++++++++++++++++++++++++
 src/jtag/interfaces.c        |    6 
 tcl/interface/buspirate.cfg  |   16 
 7 files changed, 1027 insertions(+)

--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ history for details about what changed, 
 and other issues not mentioned here.
 
 JTAG Layer:
+	New driver for "Bus Pirate"
 
 Boundary Scan:
 
--- a/configure.in
+++ b/configure.in
@@ -474,6 +474,10 @@ AC_ARG_ENABLE(arm-jtag-ew,
   AS_HELP_STRING([--enable-arm-jtag-ew], [Enable building support for the Olimex ARM-JTAG-EW Programmer]),
   [build_armjtagew=$enableval], [build_armjtagew=no])
 
+AC_ARG_ENABLE(buspirate,
+  AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]),
+  [build_buspirate=$enableval], [build_buspirate=no])
+
 AC_ARG_ENABLE(minidriver_dummy,
   AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]),
   [build_minidriver_dummy=$enableval], [build_minidriver_dummy=no])
@@ -741,6 +745,12 @@ else
   AC_DEFINE(BUILD_ARMJTAGEW, 0, [0 if you don't want the ARM-JTAG-EW JTAG driver.])
 fi
 
+if test $build_buspirate = yes; then
+  AC_DEFINE(BUILD_BUSPIRATE, 1, [1 if you want the Buspirate JTAG driver.])
+else
+  AC_DEFINE(BUILD_BUSPIRATE, 0, [0 if you don't want the Buspirate JTAG driver.])
+fi
+
 #-- Deal with MingW/Cygwin FTD2XX issues
 
 if test $is_win32 = yes; then
@@ -1035,6 +1045,7 @@ AM_CONDITIONAL(JLINK, test $build_jlink 
 AM_CONDITIONAL(VSLLINK, test $build_vsllink = yes)
 AM_CONDITIONAL(RLINK, test $build_rlink = yes)
 AM_CONDITIONAL(ARMJTAGEW, test $build_armjtagew = yes)
+AM_CONDITIONAL(BUSPIRATE, test $build_buspirate = yes)
 AM_CONDITIONAL(USB, test $build_usb = yes)
 AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes)
 AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes)
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -432,6 +432,9 @@ Raisonance has an adapter called @b{RLin
 
 @item @b{ARM-JTAG-EW}
 @* Link: @url{http://www.olimex.com/dev/arm-jtag-ew.html}
+
+...@item @b{Buspirate}
+...@* Link: @url{http://dangerousprototypes.com/bus-pirate-manual/}
 @end itemize
 
 @section IBM PC Parallel Printer Port Based
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -64,6 +64,9 @@ endif
 if ARMJTAGEW
 DRIVERFILES += arm-jtag-ew.c
 endif
+if BUSPIRATE
+DRIVERFILES += buspirate.c
+endif
 
 noinst_HEADERS = \
 	bitbang.h \
--- /dev/null
+++ b/src/jtag/drivers/buspirate.c
@@ -0,0 +1,987 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Michal Demin                                    *
+ *   based on usbprog.c and arm-jtag-ew.c                                  *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/interface.h>
+#include <jtag/commands.h>
+
+#include <termios.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#undef DEBUG_SERIAL
+/*#define DEBUG_SERIAL */
+static int buspirate_execute_queue(void);
+static int buspirate_speed(int speed);
+static int buspirate_khz(int khz, int *jtag_speed);
+static int buspirate_init(void);
+static int buspirate_quit(void);
+
+static void buspirate_end_state(tap_state_t state);
+static void buspirate_state_move(void);
+static void buspirate_path_move(int num_states, tap_state_t *path);
+static void buspirate_runtest(int num_cycles);
+static void buspirate_scan(bool ir_scan, enum scan_type type,
+	uint8_t *buffer, int scan_size, struct scan_command *command);
+
+
+#define CMD_UNKOWN        0x00
+#define CMD_PORT_MODE     0x01
+#define CMD_FEATURE       0x02
+#define CMD_READ_ADCS     0x03
+/*#define CMD_TAP_SHIFT     0x04 // old protocol */
+#define CMD_TAP_SHIFT     0x05
+#define CMD_ENTER_OOCD    0x06
+#define CMD_UART_SPEED    0x07
+#define CMD_JTAG_SPEED    0x08
+
+enum {
+	MODE_HIZ = 0,
+	MODE_JTAG = 1,		/* push-pull outputs */
+	MODE_JTAG_OD = 2,	/* open-drain outputs */
+};
+
+enum {
+	FEATURE_LED = 0x01,
+	FEATURE_VREG = 0x02,
+	FEATURE_TRST = 0x04,
+	FEATURE_SRST = 0x08,
+	FEATURE_PULLUP = 0x10
+};
+
+enum {
+	ACTION_DISABLE = 0,
+	ACTION_ENABLE = 1
+};
+
+enum {
+	SERIAL_NORMAL = 0,
+	SERIAL_FAST = 1
+};
+
+
+static int buspirate_fd = -1;
+static int buspirate_pinmode = MODE_JTAG_OD;
+static int buspirate_baudrate = SERIAL_NORMAL;
+static int buspirate_vreg;
+static int buspirate_pullup;
+static char *buspirate_port;
+
+
+/* TAP interface */
+static void buspirate_tap_init(void);
+static int buspirate_tap_execute(void);
+static void buspirate_tap_append(int tms, int tdi);
+static void buspirate_tap_append_scan(int length, uint8_t *buffer,
+		struct scan_command *command);
+static void buspirate_tap_make_space(int scan, int bits);
+
+static void buspirate_reset(int trst, int srst);
+
+/* low level interface */
+static void buspirate_jtag_reset(int);
+static void buspirate_jtag_enable(int);
+static unsigned char buspirate_jtag_command(int, char *, int);
+static void buspirate_jtag_set_speed(int, char);
+static void buspirate_jtag_set_mode(int, char);
+static void buspirate_jtag_set_feature(int, char, char);
+static void buspirate_jtag_get_adcs(int);
+
+/* low level HW communication interface */
+static int buspirate_serial_setspeed(int fd, speed_t speed);
+static int buspirate_serial_write(int fd, char *buf, int size);
+static int buspirate_serial_read(int fd, char *buf, int size);
+static void buspirate_print_buffer(char *buf, int size);
+
+static int buspirate_speed(int speed)
+{
+	/* TODO */
+	LOG_INFO("Want to set speed to %dkHz, but not implemented :(", speed);
+	return ERROR_OK;
+}
+
+static int buspirate_khz(int khz, int *jtag_speed)
+{
+	*jtag_speed = khz;
+	return ERROR_OK;
+}
+
+static int buspirate_execute_queue(void)
+{
+	/* currently processed command */
+	struct jtag_command *cmd = jtag_command_queue;
+	int scan_size;
+	enum scan_type type;
+	uint8_t *buffer;
+
+	while (cmd) {
+		switch (cmd->type) {
+		case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+			LOG_DEBUG("runtest %i cycles, end in %s",
+				cmd->cmd.runtest->num_cycles,
+				tap_state_name(cmd->cmd.runtest
+					->end_state));
+#endif
+			buspirate_end_state(cmd->cmd.runtest
+					->end_state);
+			buspirate_runtest(cmd->cmd.runtest
+					->num_cycles);
+			break;
+		case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+			LOG_DEBUG("statemove end in %s",
+				tap_state_name(cmd->cmd.statemove
+						->end_state));
+#endif
+			buspirate_end_state(cmd->cmd.statemove
+					->end_state);
+			buspirate_state_move();
+			break;
+		case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+			LOG_DEBUG("pathmove: %i states, end in %s",
+				cmd->cmd.pathmove->num_states,
+				tap_state_name(cmd->cmd.pathmove
+					->path[cmd->cmd.pathmove
+						->num_states - 1]));
+#endif
+			buspirate_path_move(cmd->cmd.pathmove
+					->num_states,
+					cmd->cmd.pathmove->path);
+			break;
+		case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+			LOG_DEBUG("scan end in %s",
+				tap_state_name(cmd->cmd.scan
+					->end_state));
+#endif
+
+			buspirate_end_state(cmd->cmd.scan
+					->end_state);
+
+			scan_size = jtag_build_buffer(cmd->cmd.scan,
+					&buffer);
+			type = jtag_scan_type(cmd->cmd.scan);
+			buspirate_scan(cmd->cmd.scan->ir_scan, type,
+				buffer, scan_size, cmd->cmd.scan);
+
+			break;
+		case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+			LOG_DEBUG("reset trst: %i srst %i",
+				cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+			/* flush buffers, so we can reset */
+			buspirate_tap_execute();
+
+			if (cmd->cmd.reset->trst == 1)
+				tap_set_state(TAP_RESET);
+			buspirate_reset(cmd->cmd.reset->trst,
+					cmd->cmd.reset->srst);
+			break;
+		case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+			LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
+#endif
+			buspirate_tap_execute();
+			jtag_sleep(cmd->cmd.sleep->us);
+				break;
+		default:
+			LOG_ERROR("BUG: unknown JTAG command type encountered");
+			exit(-1);
+		}
+
+		cmd = cmd->next;
+	}
+
+	return buspirate_tap_execute();
+}
+
+static int buspirate_init(void)
+{
+	buspirate_print_buffer("", 0);
+
+	/* FIXME this default is OS-specific, and won't work when
+	 * there are multiple usb-to-serial adaptors present...
+	 */
+	if (buspirate_port == NULL)
+		buspirate_port = "/dev/ttyUSB0";
+
+
+	buspirate_fd = open(buspirate_port, O_RDWR | O_NOCTTY);
+	if (buspirate_fd == -1) {
+		LOG_ERROR("Could not open serial port.");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	buspirate_serial_setspeed(buspirate_fd, B115200);
+
+	buspirate_jtag_enable(buspirate_fd);
+
+	if (buspirate_baudrate != SERIAL_NORMAL)
+		buspirate_jtag_set_speed(buspirate_fd, SERIAL_FAST);
+
+	LOG_INFO("Buspirate Interface ready!");
+
+	buspirate_tap_init();
+	buspirate_jtag_set_mode(buspirate_fd, buspirate_pinmode);
+	buspirate_jtag_set_feature(buspirate_fd, FEATURE_VREG,
+		(buspirate_vreg == 1) ? ACTION_ENABLE : ACTION_DISABLE);
+	buspirate_jtag_set_feature(buspirate_fd, FEATURE_PULLUP,
+		(buspirate_pullup == 1) ? ACTION_ENABLE : ACTION_DISABLE);
+	buspirate_reset(0, 0);
+
+	return ERROR_OK;
+}
+
+static int buspirate_quit(void)
+{
+	LOG_INFO("Shuting down buspirate ");
+	buspirate_jtag_set_mode(buspirate_fd, MODE_HIZ);
+
+	buspirate_jtag_set_speed(buspirate_fd, SERIAL_NORMAL);
+	buspirate_jtag_reset(buspirate_fd);
+	if (buspirate_port) {
+		free(buspirate_port);
+		buspirate_port = NULL;
+	}
+	return ERROR_OK;
+}
+
+/* openocd command interface */
+COMMAND_HANDLER(buspirate_handle_adc_command) {
+	if (CMD_ARGC != 0) {
+		LOG_ERROR("usage: buspirate_adc");
+		return ERROR_OK;
+	}
+
+	if (buspirate_fd == -1)
+		return ERROR_OK;
+
+	/* send the command */
+	buspirate_jtag_get_adcs(buspirate_fd);
+
+	return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_vreg_command) {
+	if (CMD_ARGC != 1) {
+		LOG_ERROR("usage: buspirate_vreg <1|0>");
+		return ERROR_OK;
+	}
+
+	if (atoi(CMD_ARGV[0]) == 1)
+		buspirate_vreg = 1;
+	else
+		buspirate_vreg = 0;
+
+	return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_pullup_command) {
+	if (CMD_ARGC != 1) {
+		LOG_ERROR("usage: buspirate_pullup <1|0>");
+		return ERROR_OK;
+	}
+
+	if (atoi(CMD_ARGV[0]) == 1)
+		buspirate_pullup = 1;
+	else
+		buspirate_pullup = 0;
+
+	return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_led_command) {
+	if (CMD_ARGC != 1) {
+		LOG_ERROR("usage: buspirate_led <1|0>");
+		return ERROR_OK;
+	}
+
+	if (atoi(CMD_ARGV[0]) == 1) {
+		/* enable led */
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED,
+				ACTION_ENABLE);
+	} else {
+		/* disable led */
+		buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED,
+				ACTION_DISABLE);
+	}
+
+	return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_mode_command) {
+	if (CMD_ARGC != 1) {
+		LOG_ERROR("usage: buspirate_mode <normal|open-drain>");
+		return ERROR_OK;
+	}
+
+	if (CMD_ARGV[0][0] == 'n')
+		buspirate_pinmode = MODE_JTAG;
+	else if (CMD_ARGV[0][0] == 'o')
+		buspirate_pinmode = MODE_JTAG_OD;
+	else
+		LOG_ERROR("usage: buspirate_mode <normal|open-drain>");
+
+	return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_speed_command) {
+	if (CMD_ARGC != 1) {
+		LOG_ERROR("usage: buspirate_speed <normal|fast>");
+		return ERROR_OK;
+	}
+
+	if (CMD_ARGV[0][0] == 'n')
+		buspirate_baudrate = SERIAL_NORMAL;
+	else if (CMD_ARGV[0][0] == 'f')
+		buspirate_baudrate = SERIAL_FAST;
+	else
+		LOG_ERROR("usage: buspirate_speed <normal|fast>");
+
+	return ERROR_OK;
+
+}
+
+COMMAND_HANDLER(buspirate_handle_port_command) {
+	if (CMD_ARGC != 1) {
+		LOG_ERROR("usage: buspirate_port /dev/ttyUSB0");
+		return ERROR_OK;
+	}
+
+	if (buspirate_port == 0)
+		buspirate_port = strdup(CMD_ARGV[0]);
+
+	return ERROR_OK;
+
+}
+
+static const struct command_registration buspirate_command_handlers[] = {
+	{
+		.name = "buspirate_adc",
+		.handler = &buspirate_handle_adc_command,
+		.mode = COMMAND_EXEC,
+		.help = "reads voltages on adc pins",
+	},
+	{
+		.name = "buspirate_vreg",
+		.handler = &buspirate_handle_vreg_command,
+		.mode = COMMAND_CONFIG,
+		.help = "changes the state of voltage regulators",
+	},
+	{
+		.name = "buspirate_pullup",
+		.handler = &buspirate_handle_pullup_command,
+		.mode = COMMAND_CONFIG,
+		.help = "changes the state of pullup",
+	},
+	{
+		.name = "buspirate_led",
+		.handler = &buspirate_handle_led_command,
+		.mode = COMMAND_EXEC,
+		.help = "changes the state of led",
+	},
+	{
+		.name = "buspirate_speed",
+		.handler = &buspirate_handle_speed_command,
+		.mode = COMMAND_CONFIG,
+		.help = "speed of the interface",
+	},
+	{
+		.name = "buspirate_mode",
+		.handler = &buspirate_handle_mode_command,
+		.mode = COMMAND_CONFIG,
+		.help = "pin mode of the interface",
+	},
+	{
+		.name = "buspirate_port",
+		.handler = &buspirate_handle_port_command,
+		.mode =	COMMAND_CONFIG,
+		.help = "name of the serial port to open",
+	},
+	COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface buspirate_interface = {
+	.name = "buspirate",
+	.execute_queue = buspirate_execute_queue,
+	.speed = buspirate_speed,
+	.khz = buspirate_khz,
+	.commands = buspirate_command_handlers,
+	.init = buspirate_init,
+	.quit = buspirate_quit
+};
+
+/*************** jtag execute commands **********************/
+static void buspirate_end_state(tap_state_t state)
+{
+	if (tap_is_state_stable(state))
+		tap_set_end_state(state);
+	else {
+		LOG_ERROR("BUG: %i is not a valid end state", state);
+		exit(-1);
+	}
+}
+
+static void buspirate_state_move(void)
+{
+	int i = 0, tms = 0;
+	uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
+			tap_get_end_state());
+	int tms_count = tap_get_tms_path_len(tap_get_state(),
+			tap_get_end_state());
+
+	for (i = 0; i < tms_count; i++) {
+		tms = (tms_scan >> i) & 1;
+		buspirate_tap_append(tms, 0);
+	}
+
+	tap_set_state(tap_get_end_state());
+}
+
+static void buspirate_path_move(int num_states, tap_state_t *path)
+{
+	int i;
+
+	for (i = 0; i < num_states; i++) {
+		if (tap_state_transition(tap_get_state(), false) == path[i]) {
+			/* LOG_INFO("1"); */
+			buspirate_tap_append(0, 0);
+		} else if (tap_state_transition(tap_get_state(), true)
+				== path[i]) {
+			/* LOG_INFO("2"); */
+			buspirate_tap_append(1, 0);
+		} else {
+			LOG_ERROR("BUG: %s -> %s isn't a valid "
+				"TAP transition",
+				tap_state_name(tap_get_state()),
+				tap_state_name(path[i]));
+			exit(-1);
+		}
+
+		tap_set_state(path[i]);
+	}
+
+	tap_set_end_state(tap_get_state());
+}
+
+static void buspirate_runtest(int num_cycles)
+{
+	int i;
+
+	tap_state_t saved_end_state = tap_get_end_state();
+
+	/* only do a state_move when we're not already in IDLE */
+	if (tap_get_state() != TAP_IDLE) {
+		buspirate_end_state(TAP_IDLE);
+		buspirate_state_move();
+	}
+
+	for (i = 0; i < num_cycles; i++)
+		buspirate_tap_append(0, 0);
+
+#ifdef _DEBUG_JTAG_IO_
+	LOG_DEBUG("runtest: cur_state %s end_state %s",
+			tap_state_name(tap_get_state()),
+			tap_state_name(tap_get_end_state()));
+#endif
+
+	/* finish in end_state */
+	buspirate_end_state(saved_end_state);
+	if (tap_get_state() != tap_get_end_state())
+		buspirate_state_move();
+}
+
+static void buspirate_scan(bool ir_scan, enum scan_type type,
+	uint8_t *buffer, int scan_size, struct scan_command *command)
+{
+	tap_state_t saved_end_state;
+
+	buspirate_tap_make_space(1, scan_size+8);
+	/* is 8 correct ? (2 moves = 16) */
+
+	saved_end_state = tap_get_end_state();
+
+	buspirate_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
+	buspirate_state_move();
+
+
+	/* The adapter does the transition to PAUSE internally */
+	if (ir_scan)
+		tap_set_state(TAP_IRPAUSE);
+	else
+		tap_set_state(TAP_DRPAUSE);
+
+	buspirate_tap_append_scan(scan_size, buffer, command);
+
+	/* move to PAUSE */
+	buspirate_tap_append(0, 0);
+
+	/* restore the saved state */
+	buspirate_end_state(saved_end_state);
+	tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
+
+	if (tap_get_state() != tap_get_end_state())
+		buspirate_state_move();
+}
+
+
+/************************* TAP related stuff **********/
+
+#define BUSPIRATE_BUFFER_SIZE 1024
+#define BUSPIRATE_MAX_PENDING_SCANS 32
+
+static char tms_chain[BUSPIRATE_BUFFER_SIZE]; /* send */
+static char tdi_chain[BUSPIRATE_BUFFER_SIZE]; /* send */
+/*static char tdo_chain[BUSPIRATE_BUFFER_SIZE]; // recv */
+static int tap_chain_index;
+
+struct pending_scan_result /* this was stolen from arm-jtag-ew */
+{
+	int first; /* First bit position in tdo_buffer to read */
+	int length; /* Number of bits to read */
+	struct scan_command *command; /* Corresponding scan command */
+	uint8_t *buffer;
+};
+
+static struct pending_scan_result
+tap_pending_scans[BUSPIRATE_MAX_PENDING_SCANS];
+static int tap_pending_scans_num;
+
+static void buspirate_tap_init(void)
+{
+	tap_chain_index = 0;
+	tap_pending_scans_num = 0;
+}
+
+static int buspirate_tap_execute(void)
+{
+	char tmp[4096];
+	uint8_t *in_buf;
+	int i;
+	int fill_index = 0;
+	int ret;
+	int bytes_to_send;
+
+	if (tap_chain_index <= 0)
+		return ERROR_OK;
+	LOG_DEBUG("executing tap num bits = %i scans = %i",
+			tap_chain_index, tap_pending_scans_num);
+
+	bytes_to_send = (tap_chain_index+7) / 8;
+
+	tmp[0] = CMD_TAP_SHIFT; /* this command expects number of bits */
+	tmp[1] = (char)(tap_chain_index >> 8);  /* high */
+	tmp[2] = (char)(tap_chain_index);  /* low */
+
+	fill_index = 3;
+	for (i = 0; i < bytes_to_send; i++) {
+		tmp[fill_index] = tdi_chain[i];
+		fill_index++;
+		tmp[fill_index] = tms_chain[i];
+		fill_index++;
+	}
+
+	ret = buspirate_serial_write(buspirate_fd, tmp, 3 + bytes_to_send*2);
+	if (ret != bytes_to_send*2+3) {
+		LOG_ERROR("error writing :(");
+		return ERROR_JTAG_DEVICE_ERROR;
+	}
+#ifdef DEBUG_SERIAL
+fprintf(stderr, "bytes writen %i:\n", ret);
+buspirate_print_buffer(tmp, bytes_to_send*2+3);
+#endif
+
+	ret = buspirate_serial_read(buspirate_fd, tmp, bytes_to_send + 3);
+#ifdef DEBUG_SERIAL
+fprintf(stderr, "bytes read %i should have read %i:\n",
+	ret, bytes_to_send + 3);
+buspirate_print_buffer(tmp, bytes_to_send+3);
+#endif
+	in_buf = (uint8_t *)(&tmp[3]);
+	/* parse the scans */
+	for (i = 0; i < tap_pending_scans_num; i++) {
+		uint8_t *buffer = tap_pending_scans[i].buffer;
+		int length = tap_pending_scans[i].length;
+		int first = tap_pending_scans[i].first;
+		struct scan_command *command = tap_pending_scans[i].command;
+/*LOG_INFO("Parsing scan result [%i] len = %i first = %i bytes:",
+ i, length, first); */
+
+		/* copy bits from buffer */
+		buf_set_buf(in_buf, first, buffer, 0, length);
+	/*buspirate_print_buffer((char*)buffer, (length+7)/8); */
+
+		/* return buffer to higher level */
+		if (jtag_read_buffer(buffer, command) != ERROR_OK) {
+			buspirate_tap_init();
+			return ERROR_JTAG_QUEUE_FAILED;
+		}
+
+		free(buffer);
+	}
+	tap_pending_scans_num = 0;
+	tap_chain_index = 0;
+	return ERROR_OK;
+}
+
+static void buspirate_tap_make_space(int scans, int bits)
+{
+	int have_scans = BUSPIRATE_MAX_PENDING_SCANS - tap_pending_scans_num;
+	int have_bits = BUSPIRATE_BUFFER_SIZE * 8 - tap_chain_index;
+
+	if ((have_scans < scans) || (have_bits < bits))
+		buspirate_tap_execute();
+}
+
+static void buspirate_tap_append(int tms, int tdi)
+{
+	int index = tap_chain_index / 8;
+
+	if (index < BUSPIRATE_BUFFER_SIZE) {
+		int bit_index = tap_chain_index % 8;
+		uint8_t bit = 1 << bit_index;
+
+		if (tms)
+			tms_chain[index] |= bit;
+		else
+			tms_chain[index] &= ~bit;
+
+		if (tdi)
+			tdi_chain[index] |= bit;
+		else
+			tdi_chain[index] &= ~bit;
+
+		tap_chain_index++;
+	} else
+		LOG_ERROR("tap_chain overflow, Bad things will happen");
+
+}
+
+static void buspirate_tap_append_scan(int length, uint8_t *buffer,
+		struct scan_command *command)
+{
+	int i;
+	tap_pending_scans[tap_pending_scans_num].length = length;
+	tap_pending_scans[tap_pending_scans_num].buffer = buffer;
+	tap_pending_scans[tap_pending_scans_num].command = command;
+	tap_pending_scans[tap_pending_scans_num].first = tap_chain_index;
+/*fprintf(stderr,"adding scan\n"); */
+	for (i = 0; i < length; i++) {
+		int tms = (i < length-1 ? 0 : 1);
+		int tdi = (buffer[i/8] >> (i%8)) & 1;
+		buspirate_tap_append(tms, tdi);
+	}
+	tap_pending_scans_num++;
+}
+
+/*************** jtag wrapper functions *********************/
+
+/* (1) assert or (0) deassert reset lines */
+static void buspirate_reset(int trst, int srst)
+{
+	LOG_DEBUG("trst: %i, srst: %i", trst, srst);
+
+	if (trst)
+		buspirate_jtag_set_feature(buspirate_fd,
+				FEATURE_TRST, ACTION_DISABLE);
+	else
+		buspirate_jtag_set_feature(buspirate_fd,
+				FEATURE_TRST, ACTION_ENABLE);
+
+	if (srst)
+		buspirate_jtag_set_feature(buspirate_fd,
+				FEATURE_SRST, ACTION_DISABLE);
+	else
+		buspirate_jtag_set_feature(buspirate_fd,
+				FEATURE_SRST, ACTION_ENABLE);
+}
+
+/*************** jtag lowlevel functions ********************/
+static void buspirate_jtag_enable(int fd)
+{
+	int ret;
+	char tmp[21] = { [0 ... 20] = 0x00 };
+	int done = 0;
+	int cmd_sent = 0;
+
+	buspirate_serial_write(fd, tmp, 20);
+	usleep(10000);
+
+	/* reads 1 to x "BBIO1" and one "OCD1" */
+	while (!done) {
+		ret = buspirate_serial_read(fd, tmp, 4);
+#ifdef DEBUG_SERIAL
+fprintf(stderr, "bytes read %i:\n", ret);
+buspirate_print_buffer(tmp, ret);
+#endif
+		if (ret != 4) {
+			LOG_ERROR("Buspirate did not respond : "
+				"( restart everything");
+			exit(-1);
+		}
+		if (strncmp(tmp, "BBIO", 4) == 0) {
+			ret = buspirate_serial_read(fd, tmp, 1);
+#ifdef DEBUG_SERIAL
+fprintf(stderr, "bytes read %i:\n", ret);
+buspirate_print_buffer(tmp, ret);
+#endif
+			if (ret != 1) {
+				LOG_ERROR("Buspirate did not respond well : "
+					"( restart everything");
+				exit(-1);
+			}
+			if (tmp[0] != '1') {
+				LOG_ERROR("Unsupported binary protocol ");
+				exit(-1);
+			}
+			if (cmd_sent == 0) {
+				cmd_sent = 1;
+				tmp[0] = CMD_ENTER_OOCD;
+				ret = buspirate_serial_write(fd, tmp, 1);
+#ifdef DEBUG_SERIAL
+fprintf(stderr, "bytes written %i:\n", ret);
+#endif
+			}
+		} else if (strncmp(tmp, "OCD1", 4) == 0)
+			done = 1;
+		else {
+			LOG_ERROR("Buspirate did not respond : "
+				"( restart everything");
+			exit(-1);
+		}
+	}
+
+}
+
+static void buspirate_jtag_reset(int fd)
+{
+	int ret;
+	char tmp[5];
+
+	tmp[0] = 0x00; /* exit OCD1 mode */
+	buspirate_serial_write(fd, tmp, 1);
+	usleep(10000);
+	ret = buspirate_serial_read(fd, tmp, 5);
+	if (strncmp(tmp, "BBIO1", 5) == 0) {
+		tmp[0] = 0x0F; /*  reset BP */
+		buspirate_serial_write(fd, tmp, 1);
+	} else
+		LOG_ERROR("Bad reply :( Please restart manually");
+}
+
+static void buspirate_jtag_set_speed(int fd, char speed)
+{
+	int ret;
+	char tmp[2];
+	char ack[2];
+	speed_t baudrate = B115200;
+
+	ack[0] = 0xAA;
+	ack[1] = 0x55;
+
+	tmp[0] = CMD_UART_SPEED;
+	tmp[1] = speed;
+	buspirate_jtag_command(fd, tmp, 2);
+
+	/* here the adapter changes speed, we need follow */
+	if (speed == SERIAL_FAST)
+		baudrate = B1000000;
+
+	buspirate_serial_setspeed(fd, baudrate);
+
+	buspirate_serial_write(fd, ack, 2);
+	ret = buspirate_serial_read(fd, tmp, 2);
+	if (ret != 2) {
+		LOG_ERROR("Buspirate did not respond :"
+			" ( restart everything");
+		exit(-1);
+	}
+	if ((tmp[0] != CMD_UART_SPEED) || (tmp[1] != speed)) {
+		LOG_ERROR("Buspirate didn't reply as expected :"
+			" ( restart everything");
+		exit(-1);
+	}
+	LOG_INFO("Buspirate switched to %s mode",
+		(speed == SERIAL_NORMAL) ? "normal" : "FAST");
+}
+
+
+static void buspirate_jtag_set_mode(int fd, char mode)
+{
+	char tmp[2];
+	tmp[0] = CMD_PORT_MODE;
+	tmp[1] = mode;
+	buspirate_jtag_command(fd, tmp, 2);
+}
+
+static void buspirate_jtag_set_feature(int fd, char feat, char action)
+{
+	char tmp[3];
+	tmp[0] = CMD_FEATURE;
+	tmp[1] = feat;   /* what */
+	tmp[2] = action; /* action */
+	buspirate_jtag_command(fd, tmp, 3);
+}
+
+static void buspirate_jtag_get_adcs(int fd)
+{
+	uint8_t tmp[10];
+	uint16_t a, b, c, d;
+	tmp[0] = CMD_READ_ADCS;
+	buspirate_jtag_command(fd, (char *)tmp, 1);
+	a = tmp[2] << 8 | tmp[3];
+	b = tmp[4] << 8 | tmp[5];
+	c = tmp[6] << 8 | tmp[7];
+	d = tmp[8] << 8 | tmp[9];
+
+	LOG_INFO("ADC: ADC_Pin = %.02f VPullup = %.02f V33 = %.02f "
+		"V50 = %.02f",
+		((float)a)/155.1515, ((float)b)/155.1515,
+		((float)c)/155.1515, ((float)d)/155.1515);
+}
+
+static unsigned char buspirate_jtag_command(int buspirate_fd,
+		char *cmd, int cmdlen)
+{
+	int res;
+	int len = 0;
+
+	res = buspirate_serial_write(buspirate_fd, cmd, cmdlen);
+#ifdef DEBUG_SERIAL
+/*LOG_INFO("jtag_message  %i",(int)cmd[0]); */
+LOG_INFO("write cmd = %i bytes %i", cmd[0], res);
+buspirate_print_buffer(cmd, cmdlen);
+#endif
+	if ((cmd[0] == CMD_UART_SPEED)
+				|| (cmd[0] == CMD_PORT_MODE)
+				|| (cmd[0] == CMD_FEATURE)
+				|| (cmd[0] == CMD_JTAG_SPEED))
+		return 1;
+
+	if (res == cmdlen) {
+		/* LOG_DEBUG("waiting jtag_message response %i",
+		 * 	(int)msg[0]); */
+		switch (cmd[0]) {
+		case CMD_READ_ADCS:
+			len = 10; /* 2+2*4 */
+			break;
+		case CMD_TAP_SHIFT:
+			len = cmdlen;
+			break;
+		default:
+			LOG_INFO("Wrong !");
+		}
+		res =  buspirate_serial_read(buspirate_fd, cmd, len);
+#ifdef DEBUG_SERIAL
+LOG_INFO("read bytes  %i should have read  %i", res, len);
+buspirate_print_buffer(cmd, len);
+#endif
+		if (res > 0)
+			return (unsigned char)cmd[1];
+		else
+			return -1;
+	} else
+		return -1;
+	return 0;
+}
+
+/* low level serial port */
+static int buspirate_serial_setspeed(int fd, speed_t speed)
+{
+	struct termios t_opt;
+
+	/* set the serial port parameters */
+	fcntl(buspirate_fd, F_SETFL, 0);
+	tcgetattr(buspirate_fd, &t_opt);
+	cfsetispeed(&t_opt, speed);
+	cfsetospeed(&t_opt, speed);
+	t_opt.c_cflag |= (CLOCAL | CREAD);
+	t_opt.c_cflag &= ~PARENB;
+	t_opt.c_cflag &= ~CSTOPB;
+	t_opt.c_cflag &= ~CSIZE;
+	t_opt.c_cflag |= CS8;
+	t_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+	t_opt.c_iflag &= ~(IXON | IXOFF | IXANY);
+	t_opt.c_oflag &= ~OPOST;
+	t_opt.c_cc[VMIN] = 0;
+	t_opt.c_cc[VTIME] = 10;
+	tcflush(buspirate_fd, TCIFLUSH);
+	tcsetattr(buspirate_fd, TCSANOW, &t_opt);
+
+	return 0;
+}
+
+static int buspirate_serial_write(int fd, char *buf, int size)
+{
+	int ret = 0;
+
+	ret = write(fd, buf, size);
+
+	if (ret != size)
+		LOG_ERROR("Error sending data");
+
+	return ret;
+}
+
+static int buspirate_serial_read(int fd, char *buf, int size)
+{
+	int len = 0;
+	int ret = 0;
+	int timeout = 0;
+
+	while (len < size) {
+		ret = read(fd, buf+len, size-len);
+		if (ret == -1)
+			return -1;
+
+		if (ret == 0) {
+			timeout++;
+
+			if (timeout >= 10)
+				return len;
+
+			continue;
+		}
+
+		len += ret;
+	}
+
+	return len;
+}
+
+static void buspirate_print_buffer(char *buf, int size)
+{
+	int i;
+
+	for (i = 0 ; i < size; i++)
+		fprintf(stderr, "%02X ", ((unsigned char)buf[i]) & 0xff);
+	fprintf(stderr, "\n");
+}
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -91,6 +91,9 @@ extern struct jtag_interface rlink_inter
 #if BUILD_ARMJTAGEW == 1
 extern struct jtag_interface armjtagew_interface;
 #endif
+#if BUILD_BUSPIRATE == 1
+extern struct jtag_interface buspirate_interface;
+#endif
 #endif // standard drivers
 
 /**
@@ -151,6 +154,9 @@ struct jtag_interface *jtag_interfaces[]
 #if BUILD_ARMJTAGEW == 1
 		&armjtagew_interface,
 #endif
+#if BUILD_BUSPIRATE == 1
+		&buspirate_interface,
+#endif
 #endif // standard drivers
 		NULL,
 	};
--- /dev/null
+++ b/tcl/interface/buspirate.cfg
@@ -0,0 +1,16 @@
+#
+# Buspirate with OpenOCD support
+#
+# http://dangerousprototypes.com/bus-pirate-manual/
+#
+
+interface buspirate
+buspirate_port /dev/ttyUSB0 # adjust to your needs
+buspirate_speed normal # or fast
+#buspirate_vreg 0 # or 1
+#buspirate_mode normal # or open-drain
+#buspirate_pullup 0 # or 1
+
+# this depends on the cable, you are safe with this option
+reset_config srst_only
+
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to