Package: openocd
Version: 0.9.0-1+b1
Severity: wishlist
Tags: patch

Please consider applying the attached patch, which is taken from
upstream's gerrit instance and adds support for Serial Wire Debugging
(SWD) to the Bus Pirate driver. I have successfully used this to program
an FST-01 device, as described at:

http://www.earth.li/~noodles/blog/2015/08/program-fst01-with-buspirate.html


-- System Information:
Debian Release: stretch/sid
  APT prefers testing
  APT policy: (900, 'testing'), (800, 'unstable'), (500, 'testing-updates'), 
(500, 'testing-proposed-updates'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.2.0-rc6 (SMP w/4 CPU cores)
Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages openocd depends on:
ii  libc6              2.19-19
ii  libhidapi-hidraw0  0.8.0~rc1+git20140201.3a66d4e+dfsg-3
ii  libjim0.76         0.76-1
ii  libusb-0.1-4       2:0.1.12-25
ii  libusb-1.0-0       2:1.0.19-1

openocd recommends no packages.

openocd suggests no packages.

-- no debconf information
>From 21889ee0a21f3d5a8fdf016795d9a40e3c64f471 Mon Sep 17 00:00:00 2001
From: Jonathan McDowell <nood...@earth.li>
Date: Sat, 15 Aug 2015 09:27:08 +0100
Subject: [PATCH] Add Serial Wire Debugging (SWD) support to Bus Pirate driver

Patch taken from upstream gerrit.

Signed-off-by: Jonathan McDowell <nood...@earth.li>
---
 debian/changelog                         |   6 +
 debian/patches/01-add-buspirate-swd.diff | 668 +++++++++++++++++++++++++++++++
 debian/patches/series                    |   1 +
 3 files changed, 675 insertions(+)
 create mode 100644 debian/patches/01-add-buspirate-swd.diff

diff --git a/debian/changelog b/debian/changelog
index 8474b78..fa6b028 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+openocd (0.9.0-2) unstable; urgency=medium
+
+  * Add Serial Wire Debugging (SWD) support to Bus Pirate driver.
+
+ -- Jonathan McDowell <nood...@earth.li>  Sat, 15 Aug 2015 09:26:39 +0100
+
 openocd (0.9.0-1) unstable; urgency=medium
 
   * new upstream stable release
diff --git a/debian/patches/01-add-buspirate-swd.diff b/debian/patches/01-add-buspirate-swd.diff
new file mode 100644
index 0000000..259c261
--- /dev/null
+++ b/debian/patches/01-add-buspirate-swd.diff
@@ -0,0 +1,668 @@
+Description: Add support for Serial Wire Debuggging to the Bus Pirate driver
+Origin: http://openocd.zylin.com/#/c/2444/
+Author: Mateusz Manowiecki <segmentat...@fault.pl>
+
+diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
+index 554d3e0..f40abdf 100644
+--- a/src/jtag/drivers/buspirate.c
++++ b/src/jtag/drivers/buspirate.c
+@@ -24,6 +24,7 @@
+ #endif
+ 
+ #include <jtag/interface.h>
++#include <jtag/swd.h>
+ #include <jtag/commands.h>
+ 
+ #include <termios.h>
+@@ -43,6 +44,8 @@ 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);
+ static void buspirate_stableclocks(int num_cycles);
++static int buspirate_swd_switch_seq(struct adiv5_dap *dap,
++	enum swd_special_seq seq);
+ 
+ #define CMD_UNKNOWN       0x00
+ #define CMD_PORT_MODE     0x01
+@@ -50,9 +53,21 @@ static void buspirate_stableclocks(int num_cycles);
+ #define CMD_READ_ADCS     0x03
+ /*#define CMD_TAP_SHIFT     0x04 // old protocol */
+ #define CMD_TAP_SHIFT     0x05
++#define CMD_ENTER_RWIRE   0x05
+ #define CMD_ENTER_OOCD    0x06
+ #define CMD_UART_SPEED    0x07
+ #define CMD_JTAG_SPEED    0x08
++#define CMD_RAW_SPEED     0x60
++#define CMD_RAW_CONFIG    0x80
++#define CMD_RAW_FEATURE   0x40
++
++/* raw-wire mode configuration */
++#define CMD_RAW_CONFIG_HIZ 0x00
++#define CMD_RAW_CONFIG_3V3 0x08
++#define CMD_RAW_CONFIG_2W  0x00
++#define CMD_RAW_CONFIG_3W  0x04
++#define CMD_RAW_CONFIG_MSB 0x00
++#define CMD_RAW_CONFIG_LSB 0x02
+ 
+ /* Not all OSes have this speed defined */
+ #if !defined(B1000000)
+@@ -66,23 +81,55 @@ enum {
+ };
+ 
+ enum {
+-	FEATURE_LED = 0x01,
+-	FEATURE_VREG = 0x02,
+-	FEATURE_TRST = 0x04,
+-	FEATURE_SRST = 0x08,
++	FEATURE_LED    = 0x01,
++	FEATURE_VREG   = 0x02,
++	FEATURE_TRST   = 0x04,
++	FEATURE_SRST   = 0x08,
+ 	FEATURE_PULLUP = 0x10
+ };
+ 
++/* feature codes available in SWD mode */
++enum {
++	SWD_FEATURE_VREG   = 0x08,
++	SWD_FEATURE_PULLUP = 0x04,
++	SWD_FEATURE_SRST   = 0x02
++};
++
+ enum {
+ 	ACTION_DISABLE = 0,
+-	ACTION_ENABLE = 1
++	ACTION_ENABLE  = 1
+ };
+ 
+ enum {
+ 	SERIAL_NORMAL = 0,
+-	SERIAL_FAST = 1
++	SERIAL_FAST   = 1
++};
++
++enum {
++	SPEED_RAW_5_KHZ   = 0x0,
++	SPEED_RAW_50_KHZ  = 0x1,
++	SPEED_RAW_100_KHZ = 0x2,
++	SPEED_RAW_400_KHZ = 0x3
+ };
+ 
++static uint8_t swd_feature_config;
++
++/* SWD mode specific */
++static bool swd_mode;
++
++/* FIXME: Where to store per-instance data? We need an SWD context. */
++/*        copied from ftdi.c driver */
++static struct swd_cmd_queue_entry {
++	uint8_t cmd;
++	uint32_t *dst;
++	uint32_t data;
++	uint8_t parity;
++	uint8_t ack;
++} *swd_cmd_queue;
++static size_t swd_cmd_queue_length;
++static size_t swd_cmd_queue_alloced;
++static int    queued_retval;
++
+ static const cc_t SHORT_TIMEOUT  = 1; /* Must be at least 1. */
+ static const cc_t NORMAL_TIMEOUT = 10;
+ 
+@@ -95,6 +142,8 @@ static char *buspirate_port;
+ 
+ static enum tap_state last_tap_state = TAP_RESET;
+ 
++/* SWD interface */
++static int buspirate_swd_run_queue(struct adiv5_dap *dap);
+ 
+ /* TAP interface */
+ static void buspirate_tap_init(void);
+@@ -107,14 +156,18 @@ static void buspirate_tap_make_space(int scan, int bits);
+ static void buspirate_reset(int trst, int srst);
+ 
+ /* low level interface */
++static void buspirate_bbio_enable(int);
+ 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 two-wire interface */
++static void buspirate_swd_set_params(int);
++static void buspirate_swd_set_feature(int, char, char);
++
+ /* low level HW communication interface */
+ static int buspirate_serial_open(char *port);
+ static int buspirate_serial_setspeed(int fd, char speed, cc_t timeout);
+@@ -297,15 +350,20 @@ static int buspirate_init(void)
+ 		return ERROR_JTAG_INIT_FAILED;
+ 	}
+ 
+-	buspirate_jtag_enable(buspirate_fd);
++	buspirate_bbio_enable(buspirate_fd);
+ 
+-	if (buspirate_baudrate != SERIAL_NORMAL)
++	if (swd_mode)
++		buspirate_swd_set_params(buspirate_fd);
++	else if (buspirate_baudrate != SERIAL_NORMAL)
+ 		buspirate_jtag_set_speed(buspirate_fd, SERIAL_FAST);
+ 
+-	LOG_INFO("Buspirate Interface ready!");
++	LOG_INFO("Buspirate %s Interface ready!", swd_mode ? "SWD" : "JTAG");
++
++	if (!swd_mode) {
++		buspirate_tap_init();
++		buspirate_jtag_set_mode(buspirate_fd, buspirate_pinmode);
++	}
+ 
+-	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,
+@@ -318,9 +376,11 @@ static int buspirate_init(void)
+ static int buspirate_quit(void)
+ {
+ 	LOG_INFO("Shutting down buspirate.");
+-	buspirate_jtag_set_mode(buspirate_fd, MODE_HIZ);
++	if (!swd_mode) {
++		buspirate_jtag_set_mode(buspirate_fd, MODE_HIZ);
++		buspirate_jtag_set_speed(buspirate_fd, SERIAL_NORMAL);
++	}
+ 
+-	buspirate_jtag_set_speed(buspirate_fd, SERIAL_NORMAL);
+ 	buspirate_jtag_reset(buspirate_fd);
+ 
+ 	buspirate_serial_close(buspirate_fd);
+@@ -329,6 +389,10 @@ static int buspirate_quit(void)
+ 		free(buspirate_port);
+ 		buspirate_port = NULL;
+ 	}
++
++	if (NULL != swd_cmd_queue)
++		free(swd_cmd_queue);
++
+ 	return ERROR_OK;
+ }
+ 
+@@ -442,6 +506,7 @@ COMMAND_HANDLER(buspirate_handle_port_command)
+ 
+ }
+ 
++/* all commands except buspirate_port won't work in SWD mode */
+ static const struct command_registration buspirate_command_handlers[] = {
+ 	{
+ 		.name = "buspirate_adc",
+@@ -494,10 +559,240 @@ static const struct command_registration buspirate_command_handlers[] = {
+ 	COMMAND_REGISTRATION_DONE
+ };
+ 
++static int buspirate_swd_init(void)
++{
++	LOG_INFO("Buspirate SWD mode enabled");
++	swd_mode = true;
++
++	swd_cmd_queue_alloced = 10;
++	swd_cmd_queue = malloc(swd_cmd_queue_alloced * sizeof(*swd_cmd_queue));
++
++	return swd_cmd_queue != NULL ? ERROR_OK : ERROR_FAIL;
++}
++
++static int buspirate_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq)
++{
++	const uint8_t *sequence;
++	int sequence_len;
++	char tmp[64];
++
++	switch (seq) {
++	case LINE_RESET:
++		LOG_DEBUG("SWD line reset");
++		sequence = swd_seq_line_reset;
++		sequence_len = DIV_ROUND_UP(swd_seq_line_reset_len, 8);
++		break;
++	case JTAG_TO_SWD:
++		LOG_DEBUG("JTAG-to-SWD");
++		sequence = swd_seq_jtag_to_swd;
++		sequence_len = DIV_ROUND_UP(swd_seq_jtag_to_swd_len, 8);
++		break;
++	case SWD_TO_JTAG:
++		LOG_DEBUG("SWD-to-JTAG");
++		sequence = swd_seq_swd_to_jtag;
++		sequence_len = DIV_ROUND_UP(swd_seq_swd_to_jtag_len, 8);
++		break;
++	default:
++		LOG_ERROR("Sequence %d not supported", seq);
++		return ERROR_FAIL;
++	}
++
++	/* FIXME: all above sequences fit into one pirate command for now
++	 *        but it may cause trouble later
++	 */
++
++	tmp[0] = 0x10 + ((sequence_len - 1) & 0x0F);
++	memcpy(tmp + 1, sequence, sequence_len);
++
++	buspirate_serial_write(buspirate_fd, tmp, sequence_len + 1);
++	buspirate_serial_read(buspirate_fd, tmp, sequence_len + 1);
++
++	return ERROR_OK;
++}
++
++static void buspirate_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data)
++{
++	if (swd_cmd_queue_length >= swd_cmd_queue_alloced) {
++		/* Not enough room in the queue. Run the queue and increase its size for next time.
++		 * Note that it's not possible to avoid running the queue here, because mpsse contains
++		 * pointers into the queue which may be invalid after the realloc. */
++		queued_retval = buspirate_swd_run_queue(dap);
++		struct swd_cmd_queue_entry *q = realloc(swd_cmd_queue, swd_cmd_queue_alloced * 2 * sizeof(*swd_cmd_queue));
++		if (q != NULL) {
++			swd_cmd_queue = q;
++			swd_cmd_queue_alloced *= 2;
++			LOG_DEBUG("Increased SWD command queue to %zu elements", swd_cmd_queue_alloced);
++		}
++	}
++
++	if (queued_retval != ERROR_OK)
++		return;
++
++	size_t i = swd_cmd_queue_length++;
++	swd_cmd_queue[i].cmd = cmd | SWD_CMD_START | SWD_CMD_PARK;
++
++	if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) {
++		/* Queue a read transaction */
++		swd_cmd_queue[i].dst = dst;
++	} else {
++		/* Queue a write transaction */
++		swd_cmd_queue[i].data = data;
++		swd_cmd_queue[i].parity = parity_u32(data) ? 0x01 : 0x00;
++	}
++}
++
++static void buspirate_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value)
++{
++	assert(cmd & SWD_CMD_RnW);
++	buspirate_swd_queue_cmd(dap, cmd, value, 0);
++}
++
++static void buspirate_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value)
++{
++	assert(!(cmd & SWD_CMD_RnW));
++	buspirate_swd_queue_cmd(dap, cmd, NULL, value);
++}
++
++static void buspirate_swd_idle_bytes(uint8_t count)
++{
++	char tmp[20];
++
++	tmp[0] = 0x10 + ((count - 1) & 0x0F);
++	memset(tmp + 1, 0x00, sizeof(tmp) - 1);
++
++	buspirate_serial_write(buspirate_fd, tmp, count + 1);
++	buspirate_serial_read(buspirate_fd, tmp, count + 1);
++}
++
++static int buspirate_run_cmd(struct adiv5_dap *dap, size_t queue_item)
++{
++	char tmp[16];
++	int  to_send;
++
++	tmp[0] = 0x10; /* bus pirate: send 1 byte */
++	tmp[1] = swd_cmd_queue[queue_item].cmd; /* swd cmd */
++	tmp[2] = 0x07; /* ack __x */
++	tmp[3] = 0x07; /* ack _x_ */
++	tmp[4] = 0x07; /* ack x__ */
++	tmp[5] = 0x07; /* write mode trn_1 */
++	tmp[6] = 0x07; /* write mode trn_2 */
++
++	to_send = (((swd_cmd_queue[queue_item].cmd & SWD_CMD_RnW) == 0) ? 7 : 5);
++	buspirate_serial_write(buspirate_fd, tmp, to_send);
++
++	/* read ack */
++	buspirate_serial_read(buspirate_fd, tmp, 2); /* drop pirate command ret vals */
++	buspirate_serial_read(buspirate_fd, tmp, to_send - 2); /* ack bits */
++
++	swd_cmd_queue[queue_item].ack = tmp[2] << 2 | tmp[1] << 1 | tmp[0];
++
++	if (swd_cmd_queue[queue_item].cmd & SWD_CMD_RnW) {
++		/* do a read transaction */
++		tmp[0] = 0x06; /* 4 data bytes */
++		tmp[1] = 0x06;
++		tmp[2] = 0x06;
++		tmp[3] = 0x06;
++		tmp[4] = 0x07; /* parity bit */
++		tmp[5] = 0x21; /* 2 turnaround clocks */
++
++		buspirate_serial_write(buspirate_fd, tmp, 6);
++		buspirate_serial_read(buspirate_fd, tmp, 6);
++
++		/* store the data and parity */
++		swd_cmd_queue[queue_item].data = (uint8_t) tmp[0];
++		swd_cmd_queue[queue_item].data |= (uint8_t) tmp[1] << 8;
++		swd_cmd_queue[queue_item].data |= (uint8_t) tmp[2] << 16;
++		swd_cmd_queue[queue_item].data |= (uint8_t) tmp[3] << 24;
++		swd_cmd_queue[queue_item].parity = tmp[4] ? 0x01 : 0x00;
++	} else {
++		/* do a write transaction */
++		tmp[0] = 0x10 + ((4 + 1 - 1) & 0xF); /* bus pirate: send 4+1 bytes */
++		buf_set_u32((uint8_t *) tmp + 1, 0, 32, swd_cmd_queue[queue_item].data);
++		/* write sequence ends with parity bit and 7 idle ticks */
++		tmp[5] = swd_cmd_queue[queue_item].parity;
++
++		buspirate_serial_write(buspirate_fd, tmp, 6);
++		buspirate_serial_read(buspirate_fd, tmp, 6);
++	}
++
++	/* Insert idle cycles after AP accesses to avoid WAIT */
++	if (swd_cmd_queue[queue_item].cmd & SWD_CMD_APnDP)
++		buspirate_swd_idle_bytes(1);
++
++	return 0;
++}
++
++static int buspirate_swd_run_queue(struct adiv5_dap *dap)
++{
++	LOG_DEBUG("Executing %zu queued transactions", swd_cmd_queue_length);
++	int retval;
++
++	if (queued_retval != ERROR_OK) {
++		LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
++		goto skip;
++	}
++
++	/* A transaction must be followed by another transaction or at least 8 idle cycles to
++	 * ensure that data is clocked through the AP. */
++	buspirate_swd_idle_bytes(1);
++
++	for (size_t i = 0; i < swd_cmd_queue_length; i++)
++		buspirate_run_cmd(dap, i);
++
++	for (size_t i = 0; i < swd_cmd_queue_length; i++) {
++		int ack = swd_cmd_queue[i].ack;
++
++		LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
++				ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
++				swd_cmd_queue[i].cmd & SWD_CMD_APnDP ? "AP" : "DP",
++				swd_cmd_queue[i].cmd & SWD_CMD_RnW ? "read" : "write",
++				(swd_cmd_queue[i].cmd & SWD_CMD_A32) >> 1,
++				swd_cmd_queue[i].data);
++
++		if (ack != SWD_ACK_OK) {
++			queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
++			goto skip;
++
++		} else if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) {
++			uint32_t data = swd_cmd_queue[i].data;
++			int parity = swd_cmd_queue[i].parity;
++
++			if (parity != parity_u32(data)) {
++				LOG_ERROR("SWD Read data parity mismatch %x %x", parity, parity_u32(data));
++				queued_retval = ERROR_FAIL;
++				goto skip;
++			}
++
++			if (swd_cmd_queue[i].dst != NULL)
++				*swd_cmd_queue[i].dst = data;
++		}
++	}
++
++skip:
++	swd_cmd_queue_length = 0;
++	retval = queued_retval;
++	queued_retval = ERROR_OK;
++
++	return retval;
++}
++
++static const struct swd_driver buspirate_swd = {
++	.init = buspirate_swd_init,
++	.switch_seq = buspirate_swd_switch_seq,
++	.read_reg = buspirate_swd_read_reg,
++	.write_reg = buspirate_swd_write_reg,
++	.run = buspirate_swd_run_queue,
++};
++
++static const char * const buspirate_transports[] = { "jtag", "swd", NULL };
++
+ struct jtag_interface buspirate_interface = {
+ 	.name = "buspirate",
+ 	.execute_queue = buspirate_execute_queue,
+ 	.commands = buspirate_command_handlers,
++	.transports = buspirate_transports,
++	.swd = &buspirate_swd,
++
+ 	.init = buspirate_init,
+ 	.quit = buspirate_quit
+ };
+@@ -808,12 +1103,15 @@ 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);
++	/* trst is not available in SWD mode */
++	if (!swd_mode) {
++		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,
+@@ -824,18 +1122,29 @@ static void buspirate_reset(int trst, int srst)
+ }
+ 
+ /*************** jtag lowlevel functions ********************/
+-static void buspirate_jtag_enable(int fd)
++static void buspirate_bbio_enable(int fd)
+ {
+ 	int ret;
++	char command;
++	const char *mode_answers[2] = { "OCD1", "RAW1" };
++	const char *correct_ans     = NULL;
+ 	char tmp[21] = { [0 ... 20] = 0x00 };
+ 	int done = 0;
+ 	int cmd_sent = 0;
+ 
+-	LOG_DEBUG("Entering binary mode");
++	if (swd_mode) {
++		command     = CMD_ENTER_RWIRE;
++		correct_ans = mode_answers[1];
++	} else {
++		command     = CMD_ENTER_OOCD;
++		correct_ans = mode_answers[0];
++	}
++
++	LOG_DEBUG("Entering binary mode, that is %s", correct_ans);
+ 	buspirate_serial_write(fd, tmp, 20);
+ 	usleep(10000);
+ 
+-	/* reads 1 to n "BBIO1"s and one "OCD1" */
++	/* reads 1 to n "BBIO1"s and one "OCD1" or "RAW1" */
+ 	while (!done) {
+ 		ret = buspirate_serial_read(fd, tmp, 4);
+ 		if (ret != 4) {
+@@ -856,14 +1165,14 @@ static void buspirate_jtag_enable(int fd)
+ 			}
+ 			if (cmd_sent == 0) {
+ 				cmd_sent = 1;
+-				tmp[0] = CMD_ENTER_OOCD;
++				tmp[0] = command;
+ 				ret = buspirate_serial_write(fd, tmp, 1);
+ 				if (ret != 1) {
+ 					LOG_ERROR("error reading");
+ 					exit(-1);
+ 				}
+ 			}
+-		} else if (strncmp(tmp, "OCD1", 4) == 0)
++		} else if (strncmp(tmp, correct_ans, 4) == 0)
+ 			done = 1;
+ 		else {
+ 			LOG_ERROR("Buspirate did not answer correctly! "
+@@ -878,7 +1187,7 @@ static void buspirate_jtag_reset(int fd)
+ {
+ 	char tmp[5];
+ 
+-	tmp[0] = 0x00; /* exit OCD1 mode */
++	tmp[0] = 0x00; /* exit binary mode */
+ 	buspirate_serial_write(fd, tmp, 1);
+ 	usleep(10000);
+ 	/* We ignore the return value here purposly, nothing we can do */
+@@ -890,6 +1199,104 @@ static void buspirate_jtag_reset(int fd)
+ 		LOG_ERROR("Unable to restart buspirate!");
+ }
+ 
++static void buspirate_swd_set_params(int fd)
++{
++	int  ret;
++	char tmp[1];
++
++	/* raw-wire mode configuration */
++	tmp[0] = CMD_RAW_CONFIG | CMD_RAW_CONFIG_3V3 | CMD_RAW_CONFIG_LSB;
++	buspirate_serial_write(fd, tmp, 1);
++	ret = buspirate_serial_read(fd, tmp, 1);
++	if (ret != 1) {
++		LOG_ERROR("Buspirate did not answer correctly");
++		exit(-1);
++	}
++	if (tmp[0] != 1) {
++		LOG_ERROR("Buspirate did not reply as expected to the configure command");
++		exit(-1);
++	}
++
++	/* speed settings */
++	tmp[0] = CMD_RAW_SPEED | SPEED_RAW_400_KHZ;
++	buspirate_serial_write(fd, tmp, 1);
++	ret = buspirate_serial_read(fd, tmp, 1);
++	if (ret != 1) {
++		LOG_ERROR("Buspirate did not answer correctly");
++		exit(-1);
++	}
++	if (tmp[0] != 1) {
++		LOG_ERROR("Buspirate did not reply as expected to the speed change command");
++		exit(-1);
++	}
++	LOG_INFO("Buspirate two-wire mode configured correctly");
++}
++
++static char *buspirate_feature_to_txt(char feat)
++{
++	/* simple enum to human-readable text converter */
++	switch (feat) {
++	case FEATURE_LED:
++		return "buspirate_led";
++	case FEATURE_SRST:
++		return "SRST";
++	case FEATURE_TRST:
++		return "TRST";
++	case FEATURE_VREG:
++		return "buspirate_vreg";
++	case FEATURE_PULLUP:
++		return "buspirate_pullup";
++	default:
++		return "<unrecognized>";
++	}
++}
++
++static void buspirate_swd_set_feature(int fd, char feat, char action)
++{
++	uint8_t new_config;
++	bool f_enable = (action == ACTION_ENABLE) ? true : false;
++	char tmp[1];
++
++	new_config = swd_feature_config;
++
++	switch (feat) {
++	case FEATURE_VREG:
++		if (f_enable)
++			new_config |= SWD_FEATURE_VREG;
++		else
++			new_config &= ~SWD_FEATURE_VREG;
++		break;
++	case FEATURE_SRST:
++		if (f_enable)
++			new_config |= SWD_FEATURE_SRST;
++		else
++			new_config &= ~SWD_FEATURE_SRST;
++		break;
++	case FEATURE_PULLUP:
++		if (f_enable)
++			new_config |= SWD_FEATURE_PULLUP;
++		else
++			new_config &= ~SWD_FEATURE_PULLUP;
++		break;
++	default:
++		LOG_ERROR("Buspirate feature %s is not available in SWD mode",
++				buspirate_feature_to_txt(feat));
++		return;
++	}
++
++	tmp[0] = CMD_RAW_FEATURE | new_config;
++	buspirate_serial_write(fd, tmp, 1);
++	buspirate_serial_read(fd, tmp, 1);
++
++	if (0x01 != tmp[0]) {
++		LOG_ERROR("Buspirate was unable to set feature %s",
++				buspirate_feature_to_txt(feat));
++		return;
++	}
++
++	swd_feature_config = new_config;
++}
++
+ static void buspirate_jtag_set_speed(int fd, char speed)
+ {
+ 	int ret;
+@@ -935,6 +1342,12 @@ static void buspirate_jtag_set_mode(int fd, char mode)
+ static void buspirate_jtag_set_feature(int fd, char feat, char action)
+ {
+ 	char tmp[3];
++
++	if (swd_mode) {
++		buspirate_swd_set_feature(fd, feat, action);
++		return;
++	}
++
+ 	tmp[0] = CMD_FEATURE;
+ 	tmp[1] = feat;   /* what */
+ 	tmp[2] = action; /* action */
+diff --git a/tcl/interface/buspirate.cfg b/tcl/interface/buspirate.cfg
+index 2b68538..eea4be0 100644
+--- a/tcl/interface/buspirate.cfg
++++ b/tcl/interface/buspirate.cfg
+@@ -9,18 +9,18 @@ interface buspirate
+ # you need to specify port on which BP lives
+ #buspirate_port /dev/ttyUSB0
+ 
+-# communication speed setting
+-buspirate_speed normal ;# or fast
+-
+ # voltage regulator Enabled = 1 Disabled = 0
+ #buspirate_vreg 0
+ 
+-# pin mode normal or open-drain
+-#buspirate_mode normal
+-
+ # pullup state Enabled = 1 Disabled = 0
+ #buspirate_pullup 0
+ 
+-# this depends on the cable, you are safe with this option
+-reset_config srst_only
++
++# the following settings do not affect SWD mode
++
++# communication speed setting
++buspirate_speed normal ;# or fast
++
++# pin mode normal or open-drain
++#buspirate_mode normal
+ 
diff --git a/debian/patches/series b/debian/patches/series
index cfb54ad..7b76121 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
 #Patch-file list
+01-add-buspirate-swd.diff
-- 
2.5.0

Reply via email to