This is an automated email from Gerrit.

Philipp Guehring ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/4158

-- gerrit

commit 3dafb49f23248c944e74ed8079731de5db69dae3
Author: Philipp Guehring <[email protected]>
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 <[email protected]>

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,

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to