gerrit
2017-06-10 20:18:36 UTC
This is an automated email from Gerrit.
Philipp Guehring (***@futureware.at) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4158
-- gerrit
commit 3dafb49f23248c944e74ed8079731de5db69dae3
Author: Philipp Guehring <***@futureware.at>
Date: Sat Jun 10 21:48:52 2017 +0200
drivers: Adding toggle support to all bitbang drivers to speed up JTAG
This adds a toggle function to all the bitbang drivers which can toggles TCK multiple times.
It speeds up e.g. imx_gpio from 8KB/s to 13KB/s
Change-Id: Ibb7cbef0899d7b29211a1567f1c43e3c0ec61412
Signed-off-by: Philipp Guehring <***@futureware.at>
diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c
index 8f65413..e0a49cf 100644
--- a/src/jtag/drivers/at91rm9200.c
+++ b/src/jtag/drivers/at91rm9200.c
@@ -111,6 +111,7 @@ static uint32_t *pio_base;
*/
static int at91rm9200_read(void);
static void at91rm9200_write(int tck, int tms, int tdi);
+static void at91rm9200_toggle(unsigned int num_cycles, int tms, int tdi);
static void at91rm9200_reset(int trst, int srst);
static int at91rm9200_init(void);
@@ -119,6 +120,7 @@ static int at91rm9200_quit(void);
static struct bitbang_interface at91rm9200_bitbang = {
.read = at91rm9200_read,
.write = at91rm9200_write,
+ .toggle = at91rm9200_toggle,
.reset = at91rm9200_reset,
.blink = 0
};
@@ -146,6 +148,25 @@ static void at91rm9200_write(int tck, int tms, int tdi)
pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
}
+static void at91rm9200_toggle(int num_cycles, int tms, int tdi)
+{
+ if (tms)
+ pio_base[device->TMS_PIO + PIO_SODR] = device->TMS_MASK;
+ else
+ pio_base[device->TMS_PIO + PIO_CODR] = device->TMS_MASK;
+
+ if (tdi)
+ pio_base[device->TDI_PIO + PIO_SODR] = device->TDI_MASK;
+ else
+ pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
+
+ for (unsigned int i = 0; i < num_cycles ; i++) {
+ pio_base[device->TCK_PIO + PIO_CODR] = device->TCK_MASK;
+ pio_base[device->TCK_PIO + PIO_SODR] = device->TCK_MASK;
+ }
+}
+
+
/* (1) assert or (0) deassert reset lines */
static void at91rm9200_reset(int trst, int srst)
{
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
index a41caf0..8a40d85 100644
--- a/src/jtag/drivers/bcm2835gpio.c
+++ b/src/jtag/drivers/bcm2835gpio.c
@@ -51,6 +51,8 @@ static volatile uint32_t *pio_base;
static int bcm2835gpio_read(void);
static void bcm2835gpio_write(int tck, int tms, int tdi);
+static void bcm2835gpio_toggle(unsigned int num_cycles, int tms, int tdi);
+
static void bcm2835gpio_reset(int trst, int srst);
static int bcm2835_swdio_read(void);
@@ -62,6 +64,7 @@ static int bcm2835gpio_quit(void);
static struct bitbang_interface bcm2835gpio_bitbang = {
.read = bcm2835gpio_read,
.write = bcm2835gpio_write,
+ .toggle = bcm2835gpio_toggle,
.reset = bcm2835gpio_reset,
.swdio_read = bcm2835_swdio_read,
.swdio_drive = bcm2835_swdio_drive,
@@ -108,6 +111,26 @@ static void bcm2835gpio_write(int tck, int tms, int tdi)
asm volatile ("");
}
+static void bcm2835gpio_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ uint32_t set0 = 0<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
+ uint32_t clear0 = 1<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
+ uint32_t set1 = 1<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
+ uint32_t clear1 = 0<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
+
+ for (unsigned int j = 0; j < num_cycles; j++) {
+ GPIO_SET = set0;
+ GPIO_CLR = clear0;
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ GPIO_SET = set0;
+ GPIO_CLR = clear0;
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ }
+}
+
+
static void bcm2835gpio_swd_write(int tck, int tms, int tdi)
{
uint32_t set = tck<<swclk_gpio | tdi<<swdio_gpio;
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index c9ec9c9..6abd6e9 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -67,6 +67,8 @@ struct bitbang_interface *bitbang_interface;
*/
#define CLOCK_IDLE() 0
+#define TOGGLE 1
+
/* The bitbang driver leaves the TCK 0 when in idle */
static void bitbang_end_state(tap_state_t state)
{
@@ -86,8 +88,12 @@ static void bitbang_state_move(int skip)
for (i = skip; i < tms_count; i++) {
tms = (tms_scan >> i) & 1;
+#ifdef TOGGLE
+ bitbang_interface->toggle(1, tms, 0);
+#else
bitbang_interface->write(0, tms, 0);
bitbang_interface->write(1, tms, 0);
+#endif
}
bitbang_interface->write(CLOCK_IDLE(), tms, 0);
@@ -108,8 +114,12 @@ static int bitbang_execute_tms(struct jtag_command *cmd)
int tms = 0;
for (unsigned i = 0; i < num_bits; i++) {
tms = ((bits[i/8] >> (i % 8)) & 1);
+#ifdef TOGGLE
+ bitbang_interface->toggle(1, tms, 0);
+#else
bitbang_interface->write(0, tms, 0);
bitbang_interface->write(1, tms, 0);
+#endif
}
bitbang_interface->write(CLOCK_IDLE(), tms, 0);
@@ -134,10 +144,12 @@ static void bitbang_path_move(struct pathmove_command *cmd)
tap_state_name(cmd->path[state_count]));
exit(-1);
}
-
+#ifdef TOGGLE
+ bitbang_interface->toggle(1, tms, 0);
+#else
bitbang_interface->write(0, tms, 0);
bitbang_interface->write(1, tms, 0);
-
+#endif
tap_set_state(cmd->path[state_count]);
state_count++;
num_states--;
@@ -150,7 +162,9 @@ static void bitbang_path_move(struct pathmove_command *cmd)
static void bitbang_runtest(int num_cycles)
{
+#ifndef TOGGLE
int i;
+#endif
tap_state_t saved_end_state = tap_get_end_state();
@@ -161,10 +175,15 @@ static void bitbang_runtest(int num_cycles)
}
/* execute num_cycles */
+#ifdef TOGGLE
+ bitbang_interface->toggle(num_cycles, 0, 0);
+#else
for (i = 0; i < num_cycles; i++) {
bitbang_interface->write(0, 0, 0);
bitbang_interface->write(1, 0, 0);
}
+#endif
+
bitbang_interface->write(CLOCK_IDLE(), 0, 0);
/* finish in end_state */
@@ -176,13 +195,19 @@ static void bitbang_runtest(int num_cycles)
static void bitbang_stableclocks(int num_cycles)
{
int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
+#ifndef TOGGLE
int i;
+#endif
/* send num_cycles clocks onto the cable */
+#ifdef TOGGLE
+ bitbang_interface->write(num_cycles, tms, 0);
+#else
for (i = 0; i < num_cycles; i++) {
bitbang_interface->write(1, tms, 0);
bitbang_interface->write(0, tms, 0);
}
+#endif
}
static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h
index c5b44bf..6ddfdb4 100644
--- a/src/jtag/drivers/bitbang.h
+++ b/src/jtag/drivers/bitbang.h
@@ -33,6 +33,7 @@ struct bitbang_interface {
void (*blink)(int on);
int (*swdio_read)(void);
void (*swdio_drive)(bool on);
+ void (*toggle)(unsigned int num_cycles, int tms, int tdi);
};
const struct swd_driver bitbang_swd;
diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c
index 0f7c12d..31a6e38 100644
--- a/src/jtag/drivers/dummy.c
+++ b/src/jtag/drivers/dummy.c
@@ -71,6 +71,14 @@ static void dummy_write(int tck, int tms, int tdi)
}
}
+static void dummy_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ dummy_write(0, tms, tdi);
+ dummy_write(1, tms, tdi);
+ }
+}
+
static void dummy_reset(int trst, int srst)
{
dummy_clock = 0;
@@ -88,6 +96,7 @@ static void dummy_led(int on)
static struct bitbang_interface dummy_bitbang = {
.read = &dummy_read,
.write = &dummy_write,
+ .toggle = &dummy_toggle,
.reset = &dummy_reset,
.blink = &dummy_led,
};
diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c
index ccd9795..9b0a4ff 100644
--- a/src/jtag/drivers/ep93xx.c
+++ b/src/jtag/drivers/ep93xx.c
@@ -34,6 +34,8 @@
#include <sys/mman.h>
static uint8_t output_value;
+static uint8_t output_value1;
+
static int dev_mem_fd;
static void *gpio_controller;
static volatile uint8_t *gpio_data_register;
@@ -43,6 +45,7 @@ static volatile uint8_t *gpio_data_direction_register;
*/
static int ep93xx_read(void);
static void ep93xx_write(int tck, int tms, int tdi);
+static void ep93xx_toggle(unsigned int num_cycles, int tms, int tdi);
static void ep93xx_reset(int trst, int srst);
static int ep93xx_init(void);
@@ -63,6 +66,7 @@ struct jtag_interface ep93xx_interface = {
static struct bitbang_interface ep93xx_bitbang = {
.read = ep93xx_read,
.write = ep93xx_write,
+ .toggle = ep93xx_toggle,
.reset = ep93xx_reset,
.blink = 0,
};
@@ -93,6 +97,37 @@ static void ep93xx_write(int tck, int tms, int tdi)
nanosleep(&ep93xx_zzzz, NULL);
}
+static void ep93xx_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ output_value1 = output_value;
+ output_value1 |= TCK_BIT;
+ output_value &= ~TCK_BIT;
+
+ if (tms) {
+ output_value |= TMS_BIT;
+ output_value1 |= TMS_BIT;
+ } else {
+ output_value &= ~TMS_BIT;
+ output_value1 &= ~TMS_BIT;
+ }
+
+ if (tdi) {
+ output_value |= TDI_BIT;
+ output_value1 |= TDI_BIT;
+ } else {
+ output_value &= ~TDI_BIT;
+ output_value1 &= ~TDI_BIT;
+ }
+
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ *gpio_data_register = output_value;
+ nanosleep(&ep93xx_zzzz, NULL);
+ *gpio_data_register = output_value1;
+ nanosleep(&ep93xx_zzzz, NULL);
+ }
+}
+
+
/* (1) assert or (0) deassert reset lines */
static void ep93xx_reset(int trst, int srst)
{
diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c
index f33d109..bff51d6 100644
--- a/src/jtag/drivers/imx_gpio.c
+++ b/src/jtag/drivers/imx_gpio.c
@@ -84,6 +84,7 @@ static inline bool gpio_level(int g)
static int imx_gpio_read(void);
static void imx_gpio_write(int tck, int tms, int tdi);
+static void imx_gpio_toggle(unsigned int num_cycles, int tms, int tdi);
static void imx_gpio_reset(int trst, int srst);
static int imx_gpio_swdio_read(void);
@@ -96,6 +97,7 @@ static struct bitbang_interface imx_gpio_bitbang = {
.read = imx_gpio_read,
.write = imx_gpio_write,
.reset = imx_gpio_reset,
+ .toggle = imx_gpio_toggle,
.swdio_read = imx_gpio_swdio_read,
.swdio_drive = imx_gpio_swdio_drive,
.blink = NULL
@@ -133,6 +135,29 @@ static int imx_gpio_read(void)
return gpio_level(tdo_gpio);
}
+static void imx_gpio_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
+ tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio);
+
+ if (jtag_delay) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ gpio_clear(tck_gpio);
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ gpio_set(tck_gpio);
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ }
+ } else {
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ gpio_clear(tck_gpio);
+ gpio_set(tck_gpio);
+ }
+ }
+}
+
+
static void imx_gpio_write(int tck, int tms, int tdi)
{
tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
@@ -468,7 +493,7 @@ static int imx_gpio_init(void)
}
- LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
+ LOG_INFO("imx_gpio mmap: pagesize: %lu, regionsize: %u",
sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE);
pio_base = mmap(NULL, IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE,
PROT_READ | PROT_WRITE,
diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c
index c9e3316..0cbaf37 100644
--- a/src/jtag/drivers/parport.c
+++ b/src/jtag/drivers/parport.c
@@ -148,6 +148,7 @@ static inline void parport_write_data(void)
#endif
}
+
static void parport_write(int tck, int tms, int tdi)
{
int i = wait_states + 1;
@@ -171,6 +172,15 @@ static void parport_write(int tck, int tms, int tdi)
parport_write_data();
}
+static void parport_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ parport_write(0, tms, tdi);
+ parport_write(1, tms, tdi);
+ }
+}
+
+
/* (1) assert or (0) deassert reset lines */
static void parport_reset(int trst, int srst)
{
@@ -254,6 +264,7 @@ static int parport_get_giveio_access(void)
static struct bitbang_interface parport_bitbang = {
.read = &parport_read,
.write = &parport_write,
+ .toggle = &parport_toggle,
.reset = &parport_reset,
.blink = &parport_led,
};
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index c8d0136..ebaf704 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -108,6 +108,17 @@ static void remote_bitbang_write(int tck, int tms, int tdi)
remote_bitbang_putc(c);
}
+static void remote_bitbang_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ char c0 = '0' + (0x0 | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
+ char c1 = '0' + (0x4 | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
+
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ remote_bitbang_putc(c0);
+ remote_bitbang_putc(c1);
+ }
+}
+
static void remote_bitbang_reset(int trst, int srst)
{
char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
@@ -123,6 +134,7 @@ static void remote_bitbang_blink(int on)
static struct bitbang_interface remote_bitbang_bitbang = {
.read = &remote_bitbang_read,
.write = &remote_bitbang_write,
+ .toggle = &remote_bitbang_toggle,
.reset = &remote_bitbang_reset,
.blink = &remote_bitbang_blink,
};
diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c
index 77b727c..b607f08 100644
--- a/src/jtag/drivers/sysfsgpio.c
+++ b/src/jtag/drivers/sysfsgpio.c
@@ -260,6 +260,15 @@ static int sysfsgpio_read(void)
return buf[0] != '0';
}
+/* This cache needs to be global since we have 2 different functions using it: */
+/* We can cache the old value to avoid needlessly writing it. */
+
+static int sysfsgpio_first_time;
+static int sysfsgpio_last_tck;
+static int sysfsgpio_last_tms;
+static int sysfsgpio_last_tdi;
+
+
/*
* Bitbang interface write of TCK, TMS, TDI
*
@@ -276,44 +285,94 @@ static void sysfsgpio_write(int tck, int tms, int tdi)
const char one[] = "1";
const char zero[] = "0";
- static int last_tck;
- static int last_tms;
- static int last_tdi;
-
- static int first_time;
size_t bytes_written;
- if (!first_time) {
- last_tck = !tck;
- last_tms = !tms;
- last_tdi = !tdi;
- first_time = 1;
+ if (!sysfsgpio_first_time) {
+ sysfsgpio_last_tck = !tck;
+ sysfsgpio_last_tms = !tms;
+ sysfsgpio_last_tdi = !tdi;
+ sysfsgpio_first_time = 1;
}
- if (tdi != last_tdi) {
+ if (tdi != sysfsgpio_last_tdi) {
bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
if (bytes_written != 1)
LOG_WARNING("writing tdi failed");
}
- if (tms != last_tms) {
+ if (tms != sysfsgpio_last_tms) {
bytes_written = write(tms_fd, tms ? &one : &zero, 1);
if (bytes_written != 1)
LOG_WARNING("writing tms failed");
}
/* write clk last */
- if (tck != last_tck) {
+ if (tck != sysfsgpio_last_tck) {
bytes_written = write(tck_fd, tck ? &one : &zero, 1);
if (bytes_written != 1)
LOG_WARNING("writing tck failed");
}
- last_tdi = tdi;
- last_tms = tms;
- last_tck = tck;
+ sysfsgpio_last_tdi = tdi;
+ sysfsgpio_last_tms = tms;
+ sysfsgpio_last_tck = tck;
+}
+
+/*
+ * Bitbang interface toggle several times with TMS, TDI
+ *
+ * Seeing as this is the only function where the outputs are changed,
+ * we can cache the old value to avoid needlessly writing it.
+ */
+static void sysfsgpio_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ if (swd_mode) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ sysfsgpio_swdio_write(0, tdi);
+ sysfsgpio_swdio_write(1, tdi);
+ }
+ return;
+ }
+
+ const char one[] = "1";
+ const char zero[] = "0";
+
+ size_t bytes_written;
+
+ if (!sysfsgpio_first_time) {
+ sysfsgpio_last_tms = !tms;
+ sysfsgpio_last_tdi = !tdi;
+ sysfsgpio_first_time = 1;
+ }
+
+ if (tdi != sysfsgpio_last_tdi) {
+ bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tdi failed");
+ }
+
+ if (tms != sysfsgpio_last_tms) {
+ bytes_written = write(tms_fd, tms ? &one : &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tms failed");
+ }
+
+ /* write clk last */
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ bytes_written = write(tck_fd, &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tck failed");
+ bytes_written = write(tck_fd, &one, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tck failed");
+ }
+
+ sysfsgpio_last_tdi = tdi;
+ sysfsgpio_last_tms = tms;
+ sysfsgpio_last_tck = 1;
}
+
/*
* Bitbang interface to manipulate reset lines SRST and TRST
*
@@ -532,6 +591,7 @@ struct jtag_interface sysfsgpio_interface = {
static struct bitbang_interface sysfsgpio_bitbang = {
.read = sysfsgpio_read,
.write = sysfsgpio_write,
+ .toggle = sysfsgpio_toggle,
.reset = sysfsgpio_reset,
.swdio_read = sysfsgpio_swdio_read,
.swdio_drive = sysfsgpio_swdio_drive,
--
Philipp Guehring (***@futureware.at) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4158
-- gerrit
commit 3dafb49f23248c944e74ed8079731de5db69dae3
Author: Philipp Guehring <***@futureware.at>
Date: Sat Jun 10 21:48:52 2017 +0200
drivers: Adding toggle support to all bitbang drivers to speed up JTAG
This adds a toggle function to all the bitbang drivers which can toggles TCK multiple times.
It speeds up e.g. imx_gpio from 8KB/s to 13KB/s
Change-Id: Ibb7cbef0899d7b29211a1567f1c43e3c0ec61412
Signed-off-by: Philipp Guehring <***@futureware.at>
diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c
index 8f65413..e0a49cf 100644
--- a/src/jtag/drivers/at91rm9200.c
+++ b/src/jtag/drivers/at91rm9200.c
@@ -111,6 +111,7 @@ static uint32_t *pio_base;
*/
static int at91rm9200_read(void);
static void at91rm9200_write(int tck, int tms, int tdi);
+static void at91rm9200_toggle(unsigned int num_cycles, int tms, int tdi);
static void at91rm9200_reset(int trst, int srst);
static int at91rm9200_init(void);
@@ -119,6 +120,7 @@ static int at91rm9200_quit(void);
static struct bitbang_interface at91rm9200_bitbang = {
.read = at91rm9200_read,
.write = at91rm9200_write,
+ .toggle = at91rm9200_toggle,
.reset = at91rm9200_reset,
.blink = 0
};
@@ -146,6 +148,25 @@ static void at91rm9200_write(int tck, int tms, int tdi)
pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
}
+static void at91rm9200_toggle(int num_cycles, int tms, int tdi)
+{
+ if (tms)
+ pio_base[device->TMS_PIO + PIO_SODR] = device->TMS_MASK;
+ else
+ pio_base[device->TMS_PIO + PIO_CODR] = device->TMS_MASK;
+
+ if (tdi)
+ pio_base[device->TDI_PIO + PIO_SODR] = device->TDI_MASK;
+ else
+ pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
+
+ for (unsigned int i = 0; i < num_cycles ; i++) {
+ pio_base[device->TCK_PIO + PIO_CODR] = device->TCK_MASK;
+ pio_base[device->TCK_PIO + PIO_SODR] = device->TCK_MASK;
+ }
+}
+
+
/* (1) assert or (0) deassert reset lines */
static void at91rm9200_reset(int trst, int srst)
{
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
index a41caf0..8a40d85 100644
--- a/src/jtag/drivers/bcm2835gpio.c
+++ b/src/jtag/drivers/bcm2835gpio.c
@@ -51,6 +51,8 @@ static volatile uint32_t *pio_base;
static int bcm2835gpio_read(void);
static void bcm2835gpio_write(int tck, int tms, int tdi);
+static void bcm2835gpio_toggle(unsigned int num_cycles, int tms, int tdi);
+
static void bcm2835gpio_reset(int trst, int srst);
static int bcm2835_swdio_read(void);
@@ -62,6 +64,7 @@ static int bcm2835gpio_quit(void);
static struct bitbang_interface bcm2835gpio_bitbang = {
.read = bcm2835gpio_read,
.write = bcm2835gpio_write,
+ .toggle = bcm2835gpio_toggle,
.reset = bcm2835gpio_reset,
.swdio_read = bcm2835_swdio_read,
.swdio_drive = bcm2835_swdio_drive,
@@ -108,6 +111,26 @@ static void bcm2835gpio_write(int tck, int tms, int tdi)
asm volatile ("");
}
+static void bcm2835gpio_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ uint32_t set0 = 0<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
+ uint32_t clear0 = 1<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
+ uint32_t set1 = 1<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
+ uint32_t clear1 = 0<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
+
+ for (unsigned int j = 0; j < num_cycles; j++) {
+ GPIO_SET = set0;
+ GPIO_CLR = clear0;
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ GPIO_SET = set0;
+ GPIO_CLR = clear0;
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ }
+}
+
+
static void bcm2835gpio_swd_write(int tck, int tms, int tdi)
{
uint32_t set = tck<<swclk_gpio | tdi<<swdio_gpio;
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index c9ec9c9..6abd6e9 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -67,6 +67,8 @@ struct bitbang_interface *bitbang_interface;
*/
#define CLOCK_IDLE() 0
+#define TOGGLE 1
+
/* The bitbang driver leaves the TCK 0 when in idle */
static void bitbang_end_state(tap_state_t state)
{
@@ -86,8 +88,12 @@ static void bitbang_state_move(int skip)
for (i = skip; i < tms_count; i++) {
tms = (tms_scan >> i) & 1;
+#ifdef TOGGLE
+ bitbang_interface->toggle(1, tms, 0);
+#else
bitbang_interface->write(0, tms, 0);
bitbang_interface->write(1, tms, 0);
+#endif
}
bitbang_interface->write(CLOCK_IDLE(), tms, 0);
@@ -108,8 +114,12 @@ static int bitbang_execute_tms(struct jtag_command *cmd)
int tms = 0;
for (unsigned i = 0; i < num_bits; i++) {
tms = ((bits[i/8] >> (i % 8)) & 1);
+#ifdef TOGGLE
+ bitbang_interface->toggle(1, tms, 0);
+#else
bitbang_interface->write(0, tms, 0);
bitbang_interface->write(1, tms, 0);
+#endif
}
bitbang_interface->write(CLOCK_IDLE(), tms, 0);
@@ -134,10 +144,12 @@ static void bitbang_path_move(struct pathmove_command *cmd)
tap_state_name(cmd->path[state_count]));
exit(-1);
}
-
+#ifdef TOGGLE
+ bitbang_interface->toggle(1, tms, 0);
+#else
bitbang_interface->write(0, tms, 0);
bitbang_interface->write(1, tms, 0);
-
+#endif
tap_set_state(cmd->path[state_count]);
state_count++;
num_states--;
@@ -150,7 +162,9 @@ static void bitbang_path_move(struct pathmove_command *cmd)
static void bitbang_runtest(int num_cycles)
{
+#ifndef TOGGLE
int i;
+#endif
tap_state_t saved_end_state = tap_get_end_state();
@@ -161,10 +175,15 @@ static void bitbang_runtest(int num_cycles)
}
/* execute num_cycles */
+#ifdef TOGGLE
+ bitbang_interface->toggle(num_cycles, 0, 0);
+#else
for (i = 0; i < num_cycles; i++) {
bitbang_interface->write(0, 0, 0);
bitbang_interface->write(1, 0, 0);
}
+#endif
+
bitbang_interface->write(CLOCK_IDLE(), 0, 0);
/* finish in end_state */
@@ -176,13 +195,19 @@ static void bitbang_runtest(int num_cycles)
static void bitbang_stableclocks(int num_cycles)
{
int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
+#ifndef TOGGLE
int i;
+#endif
/* send num_cycles clocks onto the cable */
+#ifdef TOGGLE
+ bitbang_interface->write(num_cycles, tms, 0);
+#else
for (i = 0; i < num_cycles; i++) {
bitbang_interface->write(1, tms, 0);
bitbang_interface->write(0, tms, 0);
}
+#endif
}
static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h
index c5b44bf..6ddfdb4 100644
--- a/src/jtag/drivers/bitbang.h
+++ b/src/jtag/drivers/bitbang.h
@@ -33,6 +33,7 @@ struct bitbang_interface {
void (*blink)(int on);
int (*swdio_read)(void);
void (*swdio_drive)(bool on);
+ void (*toggle)(unsigned int num_cycles, int tms, int tdi);
};
const struct swd_driver bitbang_swd;
diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c
index 0f7c12d..31a6e38 100644
--- a/src/jtag/drivers/dummy.c
+++ b/src/jtag/drivers/dummy.c
@@ -71,6 +71,14 @@ static void dummy_write(int tck, int tms, int tdi)
}
}
+static void dummy_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ dummy_write(0, tms, tdi);
+ dummy_write(1, tms, tdi);
+ }
+}
+
static void dummy_reset(int trst, int srst)
{
dummy_clock = 0;
@@ -88,6 +96,7 @@ static void dummy_led(int on)
static struct bitbang_interface dummy_bitbang = {
.read = &dummy_read,
.write = &dummy_write,
+ .toggle = &dummy_toggle,
.reset = &dummy_reset,
.blink = &dummy_led,
};
diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c
index ccd9795..9b0a4ff 100644
--- a/src/jtag/drivers/ep93xx.c
+++ b/src/jtag/drivers/ep93xx.c
@@ -34,6 +34,8 @@
#include <sys/mman.h>
static uint8_t output_value;
+static uint8_t output_value1;
+
static int dev_mem_fd;
static void *gpio_controller;
static volatile uint8_t *gpio_data_register;
@@ -43,6 +45,7 @@ static volatile uint8_t *gpio_data_direction_register;
*/
static int ep93xx_read(void);
static void ep93xx_write(int tck, int tms, int tdi);
+static void ep93xx_toggle(unsigned int num_cycles, int tms, int tdi);
static void ep93xx_reset(int trst, int srst);
static int ep93xx_init(void);
@@ -63,6 +66,7 @@ struct jtag_interface ep93xx_interface = {
static struct bitbang_interface ep93xx_bitbang = {
.read = ep93xx_read,
.write = ep93xx_write,
+ .toggle = ep93xx_toggle,
.reset = ep93xx_reset,
.blink = 0,
};
@@ -93,6 +97,37 @@ static void ep93xx_write(int tck, int tms, int tdi)
nanosleep(&ep93xx_zzzz, NULL);
}
+static void ep93xx_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ output_value1 = output_value;
+ output_value1 |= TCK_BIT;
+ output_value &= ~TCK_BIT;
+
+ if (tms) {
+ output_value |= TMS_BIT;
+ output_value1 |= TMS_BIT;
+ } else {
+ output_value &= ~TMS_BIT;
+ output_value1 &= ~TMS_BIT;
+ }
+
+ if (tdi) {
+ output_value |= TDI_BIT;
+ output_value1 |= TDI_BIT;
+ } else {
+ output_value &= ~TDI_BIT;
+ output_value1 &= ~TDI_BIT;
+ }
+
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ *gpio_data_register = output_value;
+ nanosleep(&ep93xx_zzzz, NULL);
+ *gpio_data_register = output_value1;
+ nanosleep(&ep93xx_zzzz, NULL);
+ }
+}
+
+
/* (1) assert or (0) deassert reset lines */
static void ep93xx_reset(int trst, int srst)
{
diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c
index f33d109..bff51d6 100644
--- a/src/jtag/drivers/imx_gpio.c
+++ b/src/jtag/drivers/imx_gpio.c
@@ -84,6 +84,7 @@ static inline bool gpio_level(int g)
static int imx_gpio_read(void);
static void imx_gpio_write(int tck, int tms, int tdi);
+static void imx_gpio_toggle(unsigned int num_cycles, int tms, int tdi);
static void imx_gpio_reset(int trst, int srst);
static int imx_gpio_swdio_read(void);
@@ -96,6 +97,7 @@ static struct bitbang_interface imx_gpio_bitbang = {
.read = imx_gpio_read,
.write = imx_gpio_write,
.reset = imx_gpio_reset,
+ .toggle = imx_gpio_toggle,
.swdio_read = imx_gpio_swdio_read,
.swdio_drive = imx_gpio_swdio_drive,
.blink = NULL
@@ -133,6 +135,29 @@ static int imx_gpio_read(void)
return gpio_level(tdo_gpio);
}
+static void imx_gpio_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
+ tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio);
+
+ if (jtag_delay) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ gpio_clear(tck_gpio);
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ gpio_set(tck_gpio);
+ for (unsigned int i = 0; i < jtag_delay; i++)
+ asm volatile ("");
+ }
+ } else {
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ gpio_clear(tck_gpio);
+ gpio_set(tck_gpio);
+ }
+ }
+}
+
+
static void imx_gpio_write(int tck, int tms, int tdi)
{
tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
@@ -468,7 +493,7 @@ static int imx_gpio_init(void)
}
- LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
+ LOG_INFO("imx_gpio mmap: pagesize: %lu, regionsize: %u",
sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE);
pio_base = mmap(NULL, IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE,
PROT_READ | PROT_WRITE,
diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c
index c9e3316..0cbaf37 100644
--- a/src/jtag/drivers/parport.c
+++ b/src/jtag/drivers/parport.c
@@ -148,6 +148,7 @@ static inline void parport_write_data(void)
#endif
}
+
static void parport_write(int tck, int tms, int tdi)
{
int i = wait_states + 1;
@@ -171,6 +172,15 @@ static void parport_write(int tck, int tms, int tdi)
parport_write_data();
}
+static void parport_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ parport_write(0, tms, tdi);
+ parport_write(1, tms, tdi);
+ }
+}
+
+
/* (1) assert or (0) deassert reset lines */
static void parport_reset(int trst, int srst)
{
@@ -254,6 +264,7 @@ static int parport_get_giveio_access(void)
static struct bitbang_interface parport_bitbang = {
.read = &parport_read,
.write = &parport_write,
+ .toggle = &parport_toggle,
.reset = &parport_reset,
.blink = &parport_led,
};
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index c8d0136..ebaf704 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -108,6 +108,17 @@ static void remote_bitbang_write(int tck, int tms, int tdi)
remote_bitbang_putc(c);
}
+static void remote_bitbang_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ char c0 = '0' + (0x0 | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
+ char c1 = '0' + (0x4 | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
+
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ remote_bitbang_putc(c0);
+ remote_bitbang_putc(c1);
+ }
+}
+
static void remote_bitbang_reset(int trst, int srst)
{
char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
@@ -123,6 +134,7 @@ static void remote_bitbang_blink(int on)
static struct bitbang_interface remote_bitbang_bitbang = {
.read = &remote_bitbang_read,
.write = &remote_bitbang_write,
+ .toggle = &remote_bitbang_toggle,
.reset = &remote_bitbang_reset,
.blink = &remote_bitbang_blink,
};
diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c
index 77b727c..b607f08 100644
--- a/src/jtag/drivers/sysfsgpio.c
+++ b/src/jtag/drivers/sysfsgpio.c
@@ -260,6 +260,15 @@ static int sysfsgpio_read(void)
return buf[0] != '0';
}
+/* This cache needs to be global since we have 2 different functions using it: */
+/* We can cache the old value to avoid needlessly writing it. */
+
+static int sysfsgpio_first_time;
+static int sysfsgpio_last_tck;
+static int sysfsgpio_last_tms;
+static int sysfsgpio_last_tdi;
+
+
/*
* Bitbang interface write of TCK, TMS, TDI
*
@@ -276,44 +285,94 @@ static void sysfsgpio_write(int tck, int tms, int tdi)
const char one[] = "1";
const char zero[] = "0";
- static int last_tck;
- static int last_tms;
- static int last_tdi;
-
- static int first_time;
size_t bytes_written;
- if (!first_time) {
- last_tck = !tck;
- last_tms = !tms;
- last_tdi = !tdi;
- first_time = 1;
+ if (!sysfsgpio_first_time) {
+ sysfsgpio_last_tck = !tck;
+ sysfsgpio_last_tms = !tms;
+ sysfsgpio_last_tdi = !tdi;
+ sysfsgpio_first_time = 1;
}
- if (tdi != last_tdi) {
+ if (tdi != sysfsgpio_last_tdi) {
bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
if (bytes_written != 1)
LOG_WARNING("writing tdi failed");
}
- if (tms != last_tms) {
+ if (tms != sysfsgpio_last_tms) {
bytes_written = write(tms_fd, tms ? &one : &zero, 1);
if (bytes_written != 1)
LOG_WARNING("writing tms failed");
}
/* write clk last */
- if (tck != last_tck) {
+ if (tck != sysfsgpio_last_tck) {
bytes_written = write(tck_fd, tck ? &one : &zero, 1);
if (bytes_written != 1)
LOG_WARNING("writing tck failed");
}
- last_tdi = tdi;
- last_tms = tms;
- last_tck = tck;
+ sysfsgpio_last_tdi = tdi;
+ sysfsgpio_last_tms = tms;
+ sysfsgpio_last_tck = tck;
+}
+
+/*
+ * Bitbang interface toggle several times with TMS, TDI
+ *
+ * Seeing as this is the only function where the outputs are changed,
+ * we can cache the old value to avoid needlessly writing it.
+ */
+static void sysfsgpio_toggle(unsigned int num_cycles, int tms, int tdi)
+{
+ if (swd_mode) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ sysfsgpio_swdio_write(0, tdi);
+ sysfsgpio_swdio_write(1, tdi);
+ }
+ return;
+ }
+
+ const char one[] = "1";
+ const char zero[] = "0";
+
+ size_t bytes_written;
+
+ if (!sysfsgpio_first_time) {
+ sysfsgpio_last_tms = !tms;
+ sysfsgpio_last_tdi = !tdi;
+ sysfsgpio_first_time = 1;
+ }
+
+ if (tdi != sysfsgpio_last_tdi) {
+ bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tdi failed");
+ }
+
+ if (tms != sysfsgpio_last_tms) {
+ bytes_written = write(tms_fd, tms ? &one : &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tms failed");
+ }
+
+ /* write clk last */
+ for (unsigned int i = 0; i < num_cycles; i++) {
+ bytes_written = write(tck_fd, &zero, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tck failed");
+ bytes_written = write(tck_fd, &one, 1);
+ if (bytes_written != 1)
+ LOG_WARNING("writing tck failed");
+ }
+
+ sysfsgpio_last_tdi = tdi;
+ sysfsgpio_last_tms = tms;
+ sysfsgpio_last_tck = 1;
}
+
/*
* Bitbang interface to manipulate reset lines SRST and TRST
*
@@ -532,6 +591,7 @@ struct jtag_interface sysfsgpio_interface = {
static struct bitbang_interface sysfsgpio_bitbang = {
.read = sysfsgpio_read,
.write = sysfsgpio_write,
+ .toggle = sysfsgpio_toggle,
.reset = sysfsgpio_reset,
.swdio_read = sysfsgpio_swdio_read,
.swdio_drive = sysfsgpio_swdio_drive,
--