Add read buffer to bitbang, improving performance. 12/4312/9
authorTim Newsome <tim@sifive.com>
Wed, 13 Dec 2017 21:13:22 +0000 (13:13 -0800)
committerFreddie Chopin <freddie.chopin@gmail.com>
Thu, 25 Jan 2018 16:44:06 +0000 (16:44 +0000)
Previously for every bit scanned OpenOCD would write the bit, wait for
that bit to be scanned, and then read the result. This involves at least
2 context switches. Most of the time the next bit scanned does not
depend on the last bit we read, so with a buffer we now write a bunch of
bits to be scanned all at once, and then we wait for them all to be
scanned and have a result.

This reduces the time for one testcase where OpenOCD connects to a
simulator from 12.30s to 5.35s!

Running all our tests went from 13m13s to 3m55s.

Change-Id: Ie9fcea043ac1d7877a521125334ed47d4b3e1615
Signed-off-by: Tim Newsome <tim@sifive.com>
Reviewed-on: http://openocd.zylin.com/4312
Tested-by: jenkins
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
src/helper/replacements.h
src/jtag/drivers/at91rm9200.c
src/jtag/drivers/bcm2835gpio.c
src/jtag/drivers/bitbang.c
src/jtag/drivers/bitbang.h
src/jtag/drivers/dummy.c
src/jtag/drivers/ep93xx.c
src/jtag/drivers/imx_gpio.c
src/jtag/drivers/parport.c
src/jtag/drivers/remote_bitbang.c
src/jtag/drivers/sysfsgpio.c

index 1e2fbf20f9ef349484cd48dde2aefcc12aede0cd..f43b7e0f3c1a8b2cea969baa59c14933bd46dfdf 100644 (file)
@@ -199,6 +199,17 @@ static inline int close_socket(int sock)
 #endif
 }
 
+static inline void socket_block(int fd)
+{
+#ifdef _WIN32
+       unsigned long nonblock = 0;
+       ioctlsocket(fd, FIONBIO, &nonblock);
+#else
+       int oldopts = fcntl(fd, F_GETFL, 0);
+       fcntl(fd, F_SETFL, oldopts & ~O_NONBLOCK);
+#endif
+}
+
 static inline void socket_nonblock(int fd)
 {
 #ifdef _WIN32
index 8f65413a2b4ebbf8d8e286262bb47d7b42512633..0015da06b0f9273f75d280c7db5eafa002103aec 100644 (file)
@@ -109,9 +109,9 @@ static uint32_t *pio_base;
 
 /* low level command set
  */
-static int at91rm9200_read(void);
-static void at91rm9200_write(int tck, int tms, int tdi);
-static void at91rm9200_reset(int trst, int srst);
+static bb_value_t at91rm9200_read(void);
+static int at91rm9200_write(int tck, int tms, int tdi);
+static int at91rm9200_reset(int trst, int srst);
 
 static int at91rm9200_init(void);
 static int at91rm9200_quit(void);
@@ -123,12 +123,12 @@ static struct bitbang_interface at91rm9200_bitbang = {
        .blink = 0
 };
 
-static int at91rm9200_read(void)
+static bb_value_t at91rm9200_read(void)
 {
-       return (pio_base[device->TDO_PIO + PIO_PDSR] & device->TDO_MASK) != 0;
+       return (pio_base[device->TDO_PIO + PIO_PDSR] & device->TDO_MASK) ? BB_HIGH : BB_LOW;
 }
 
-static void at91rm9200_write(int tck, int tms, int tdi)
+static int at91rm9200_write(int tck, int tms, int tdi)
 {
        if (tck)
                pio_base[device->TCK_PIO + PIO_SODR] = device->TCK_MASK;
@@ -144,10 +144,12 @@ static void at91rm9200_write(int tck, int tms, int tdi)
                pio_base[device->TDI_PIO + PIO_SODR] = device->TDI_MASK;
        else
                pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
+
+       return ERROR_OK;
 }
 
 /* (1) assert or (0) deassert reset lines */
-static void at91rm9200_reset(int trst, int srst)
+static int at91rm9200_reset(int trst, int srst)
 {
        if (trst == 0)
                pio_base[device->TRST_PIO + PIO_SODR] = device->TRST_MASK;
@@ -158,6 +160,8 @@ static void at91rm9200_reset(int trst, int srst)
                pio_base[device->SRST_PIO + PIO_SODR] = device->SRST_MASK;
        else if (srst == 1)
                pio_base[device->SRST_PIO + PIO_CODR] = device->SRST_MASK;
+
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(at91rm9200_handle_device_command)
index a4d0a1c8e7e04a93b2f19c2079649975084e4f47..38ef163fab53fdf0da378491bce801769b89d1a2 100644 (file)
@@ -49,9 +49,9 @@ uint32_t bcm2835_peri_base = 0x20000000;
 static int dev_mem_fd;
 static volatile uint32_t *pio_base;
 
-static int bcm2835gpio_read(void);
-static void bcm2835gpio_write(int tck, int tms, int tdi);
-static void bcm2835gpio_reset(int trst, int srst);
+static bb_value_t bcm2835gpio_read(void);
+static int bcm2835gpio_write(int tck, int tms, int tdi);
+static int bcm2835gpio_reset(int trst, int srst);
 
 static int bcm2835_swdio_read(void);
 static void bcm2835_swdio_drive(bool is_output);
@@ -91,12 +91,12 @@ static int speed_coeff = 113714;
 static int speed_offset = 28;
 static unsigned int jtag_delay;
 
-static int bcm2835gpio_read(void)
+static bb_value_t bcm2835gpio_read(void)
 {
-       return !!(GPIO_LEV & 1<<tdo_gpio);
+       return (GPIO_LEV & 1<<tdo_gpio) ? BB_HIGH : BB_LOW;
 }
 
-static void bcm2835gpio_write(int tck, int tms, int tdi)
+static int bcm2835gpio_write(int tck, int tms, int tdi)
 {
        uint32_t set = tck<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
        uint32_t clear = !tck<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
@@ -106,9 +106,11 @@ static void bcm2835gpio_write(int tck, int tms, int tdi)
 
        for (unsigned int i = 0; i < jtag_delay; i++)
                asm volatile ("");
+
+       return ERROR_OK;
 }
 
-static void bcm2835gpio_swd_write(int tck, int tms, int tdi)
+static int bcm2835gpio_swd_write(int tck, int tms, int tdi)
 {
        uint32_t set = tck<<swclk_gpio | tdi<<swdio_gpio;
        uint32_t clear = !tck<<swclk_gpio | !tdi<<swdio_gpio;
@@ -118,10 +120,12 @@ static void bcm2835gpio_swd_write(int tck, int tms, int tdi)
 
        for (unsigned int i = 0; i < jtag_delay; i++)
                asm volatile ("");
+
+       return ERROR_OK;
 }
 
 /* (1) assert or (0) deassert reset lines */
-static void bcm2835gpio_reset(int trst, int srst)
+static int bcm2835gpio_reset(int trst, int srst)
 {
        uint32_t set = 0;
        uint32_t clear = 0;
@@ -138,6 +142,8 @@ static void bcm2835gpio_reset(int trst, int srst)
 
        GPIO_SET = set;
        GPIO_CLR = clear;
+
+       return ERROR_OK;
 }
 
 static void bcm2835_swdio_drive(bool is_output)
index c9ec9c9d6fa33b4b2ede7d329a8c276e3c696209..722a5f2ac930b7a837b1350b5fe1c9f4cfe22183 100644 (file)
@@ -41,7 +41,7 @@ extern struct jtag_interface *jtag_interface;
  * this function checks the current stable state to decide on the value of TMS
  * to use.
  */
-static void bitbang_stableclocks(int num_cycles);
+static int bitbang_stableclocks(int num_cycles);
 
 static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
 
@@ -70,15 +70,11 @@ struct bitbang_interface *bitbang_interface;
 /* The bitbang driver leaves the TCK 0 when in idle */
 static void bitbang_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);
-       }
+       assert(tap_is_state_stable(state));
+       tap_set_end_state(state);
 }
 
-static void bitbang_state_move(int skip)
+static int bitbang_state_move(int skip)
 {
        int i = 0, tms = 0;
        uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
@@ -86,12 +82,16 @@ static void bitbang_state_move(int skip)
 
        for (i = skip; i < tms_count; i++) {
                tms = (tms_scan >> i) & 1;
-               bitbang_interface->write(0, tms, 0);
-               bitbang_interface->write(1, tms, 0);
+               if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
+               if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
        }
-       bitbang_interface->write(CLOCK_IDLE(), tms, 0);
+       if (bitbang_interface->write(CLOCK_IDLE(), tms, 0) != ERROR_OK)
+               return ERROR_FAIL;
 
        tap_set_state(tap_get_end_state());
+       return ERROR_OK;
 }
 
 /**
@@ -108,15 +108,18 @@ 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);
-               bitbang_interface->write(0, tms, 0);
-               bitbang_interface->write(1, tms, 0);
+               if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
+               if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
        }
-       bitbang_interface->write(CLOCK_IDLE(), tms, 0);
+       if (bitbang_interface->write(CLOCK_IDLE(), tms, 0) != ERROR_OK)
+               return ERROR_FAIL;
 
        return ERROR_OK;
 }
 
-static void bitbang_path_move(struct pathmove_command *cmd)
+static int bitbang_path_move(struct pathmove_command *cmd)
 {
        int num_states = cmd->num_states;
        int state_count;
@@ -135,20 +138,24 @@ static void bitbang_path_move(struct pathmove_command *cmd)
                        exit(-1);
                }
 
-               bitbang_interface->write(0, tms, 0);
-               bitbang_interface->write(1, tms, 0);
+               if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
+               if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
 
                tap_set_state(cmd->path[state_count]);
                state_count++;
                num_states--;
        }
 
-       bitbang_interface->write(CLOCK_IDLE(), tms, 0);
+       if (bitbang_interface->write(CLOCK_IDLE(), tms, 0) != ERROR_OK)
+               return ERROR_FAIL;
 
        tap_set_end_state(tap_get_state());
+       return ERROR_OK;
 }
 
-static void bitbang_runtest(int num_cycles)
+static int bitbang_runtest(int num_cycles)
 {
        int i;
 
@@ -157,38 +164,50 @@ static void bitbang_runtest(int num_cycles)
        /* only do a state_move when we're not already in IDLE */
        if (tap_get_state() != TAP_IDLE) {
                bitbang_end_state(TAP_IDLE);
-               bitbang_state_move(0);
+               if (bitbang_state_move(0) != ERROR_OK)
+                       return ERROR_FAIL;
        }
 
        /* execute num_cycles */
        for (i = 0; i < num_cycles; i++) {
-               bitbang_interface->write(0, 0, 0);
-               bitbang_interface->write(1, 0, 0);
+               if (bitbang_interface->write(0, 0, 0) != ERROR_OK)
+                       return ERROR_FAIL;
+               if (bitbang_interface->write(1, 0, 0) != ERROR_OK)
+                       return ERROR_FAIL;
        }
-       bitbang_interface->write(CLOCK_IDLE(), 0, 0);
+       if (bitbang_interface->write(CLOCK_IDLE(), 0, 0) != ERROR_OK)
+               return ERROR_FAIL;
 
        /* finish in end_state */
        bitbang_end_state(saved_end_state);
        if (tap_get_state() != tap_get_end_state())
-               bitbang_state_move(0);
+               if (bitbang_state_move(0) != ERROR_OK)
+                       return ERROR_FAIL;
+
+       return ERROR_OK;
 }
 
-static void bitbang_stableclocks(int num_cycles)
+static int bitbang_stableclocks(int num_cycles)
 {
        int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
        int i;
 
        /* send num_cycles clocks onto the cable */
        for (i = 0; i < num_cycles; i++) {
-               bitbang_interface->write(1, tms, 0);
-               bitbang_interface->write(0, tms, 0);
+               if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
+               if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
+                       return ERROR_FAIL;
        }
+
+       return ERROR_OK;
 }
 
-static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
+static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
+               unsigned scan_size)
 {
        tap_state_t saved_end_state = tap_get_end_state();
-       int bit_cnt;
+       unsigned bit_cnt;
 
        if (!((!ir_scan &&
                        (tap_get_state() == TAP_DRSHIFT)) ||
@@ -198,12 +217,13 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
                else
                        bitbang_end_state(TAP_DRSHIFT);
 
-               bitbang_state_move(0);
+               if (bitbang_state_move(0) != ERROR_OK)
+                       return ERROR_FAIL;
                bitbang_end_state(saved_end_state);
        }
 
+       size_t buffered = 0;
        for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
-               int val = 0;
                int tms = (bit_cnt == scan_size-1) ? 1 : 0;
                int tdi;
                int bytec = bit_cnt/8;
@@ -217,18 +237,47 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
                if ((type != SCAN_IN) && (buffer[bytec] & bcval))
                        tdi = 1;
 
-               bitbang_interface->write(0, tms, tdi);
-
-               if (type != SCAN_OUT)
-                       val = bitbang_interface->read();
-
-               bitbang_interface->write(1, tms, tdi);
+               if (bitbang_interface->write(0, tms, tdi) != ERROR_OK)
+                       return ERROR_FAIL;
 
                if (type != SCAN_OUT) {
-                       if (val)
-                               buffer[bytec] |= bcval;
-                       else
-                               buffer[bytec] &= ~bcval;
+                       if (bitbang_interface->buf_size) {
+                               if (bitbang_interface->sample() != ERROR_OK)
+                                       return ERROR_FAIL;
+                               buffered++;
+                       } else {
+                               switch (bitbang_interface->read()) {
+                                       case BB_LOW:
+                                               buffer[bytec] &= ~bcval;
+                                               break;
+                                       case BB_HIGH:
+                                               buffer[bytec] |= bcval;
+                                               break;
+                                       default:
+                                               return ERROR_FAIL;
+                               }
+                       }
+               }
+
+               if (bitbang_interface->write(1, tms, tdi) != ERROR_OK)
+                       return ERROR_FAIL;
+
+               if (type != SCAN_OUT && bitbang_interface->buf_size &&
+                               (buffered == bitbang_interface->buf_size ||
+                                bit_cnt == scan_size - 1)) {
+                       for (unsigned i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) {
+                               switch (bitbang_interface->read_sample()) {
+                                       case BB_LOW:
+                                               buffer[i/8] &= ~(1 << (i % 8));
+                                               break;
+                                       case BB_HIGH:
+                                               buffer[i/8] |= 1 << (i % 8);
+                                               break;
+                                       default:
+                                               return ERROR_FAIL;
+                               }
+                       }
+                       buffered = 0;
                }
        }
 
@@ -237,8 +286,10 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
                 * the shift state, so we skip the first state
                 * and move directly to the end state.
                 */
-               bitbang_state_move(1);
+               if (bitbang_state_move(1) != ERROR_OK)
+                       return ERROR_FAIL;
        }
+       return ERROR_OK;
 }
 
 int bitbang_execute_queue(void)
@@ -259,8 +310,10 @@ int bitbang_execute_queue(void)
         */
        retval = ERROR_OK;
 
-       if (bitbang_interface->blink)
-               bitbang_interface->blink(1);
+       if (bitbang_interface->blink) {
+               if (bitbang_interface->blink(1) != ERROR_OK)
+                       return ERROR_FAIL;
+       }
 
        while (cmd) {
                switch (cmd->type) {
@@ -273,7 +326,9 @@ int bitbang_execute_queue(void)
                                if ((cmd->cmd.reset->trst == 1) ||
                                                (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
                                        tap_set_state(TAP_RESET);
-                               bitbang_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               if (bitbang_interface->reset(cmd->cmd.reset->trst,
+                                                       cmd->cmd.reset->srst) != ERROR_OK)
+                                       return ERROR_FAIL;
                                break;
                        case JTAG_RUNTEST:
 #ifdef _DEBUG_JTAG_IO_
@@ -282,14 +337,16 @@ int bitbang_execute_queue(void)
                                                tap_state_name(cmd->cmd.runtest->end_state));
 #endif
                                bitbang_end_state(cmd->cmd.runtest->end_state);
-                               bitbang_runtest(cmd->cmd.runtest->num_cycles);
+                               if (bitbang_runtest(cmd->cmd.runtest->num_cycles) != ERROR_OK)
+                                       return ERROR_FAIL;
                                break;
 
                        case JTAG_STABLECLOCKS:
                                /* this is only allowed while in a stable state.  A check for a stable
                                 * state was done in jtag_add_clocks()
                                 */
-                               bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles);
+                               if (bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles) != ERROR_OK)
+                                       return ERROR_FAIL;
                                break;
 
                        case JTAG_TLR_RESET:
@@ -298,7 +355,8 @@ int bitbang_execute_queue(void)
                                                tap_state_name(cmd->cmd.statemove->end_state));
 #endif
                                bitbang_end_state(cmd->cmd.statemove->end_state);
-                               bitbang_state_move(0);
+                               if (bitbang_state_move(0) != ERROR_OK)
+                                       return ERROR_FAIL;
                                break;
                        case JTAG_PATHMOVE:
 #ifdef _DEBUG_JTAG_IO_
@@ -306,18 +364,22 @@ int bitbang_execute_queue(void)
                                                cmd->cmd.pathmove->num_states,
                                                tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
 #endif
-                               bitbang_path_move(cmd->cmd.pathmove);
+                               if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK)
+                                       return ERROR_FAIL;
                                break;
                        case JTAG_SCAN:
+                               bitbang_end_state(cmd->cmd.scan->end_state);
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
 #ifdef _DEBUG_JTAG_IO_
-                               LOG_DEBUG("%s scan end in %s",
+                               LOG_DEBUG("%s scan %d bits; end in %s",
                                                (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
+                                               scan_size,
                                        tap_state_name(cmd->cmd.scan->end_state));
 #endif
-                               bitbang_end_state(cmd->cmd.scan->end_state);
-                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
                                type = jtag_scan_type(cmd->cmd.scan);
-                               bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+                               if (bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer,
+                                                       scan_size) != ERROR_OK)
+                                       return ERROR_FAIL;
                                if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
                                        retval = ERROR_JTAG_QUEUE_FAILED;
                                if (buffer)
@@ -338,8 +400,10 @@ int bitbang_execute_queue(void)
                }
                cmd = cmd->next;
        }
-       if (bitbang_interface->blink)
-               bitbang_interface->blink(0);
+       if (bitbang_interface->blink) {
+               if (bitbang_interface->blink(0) != ERROR_OK)
+                       return ERROR_FAIL;
+       }
 
        return retval;
 }
index c5b44bfd54d16fa333f281dc5a5f76a5f6d0d855..577717ebd241a6ba8e1ab83e6d2fd0e453ffafd4 100644 (file)
 
 #include <jtag/swd.h>
 
+typedef enum {
+       BB_LOW,
+       BB_HIGH,
+       BB_ERROR
+} bb_value_t;
+
+/** Low level callbacks (for bitbang).
+ *
+ * Either read(), or sample() and read_sample() must be implemented.
+ *
+ * The sample functions allow an interface to batch a number of writes and
+ * sample requests together. Not waiting for a value to come back can greatly
+ * increase throughput. */
 struct bitbang_interface {
-       /* low level callbacks (for bitbang)
-        */
-       int (*read)(void);
-       void (*write)(int tck, int tms, int tdi);
-       void (*reset)(int trst, int srst);
-       void (*blink)(int on);
+       /** Sample TDO. */
+       bb_value_t (*read)(void);
+
+       /** The number of TDO samples that can be buffered up before the caller has
+        * to call read_sample. */
+       size_t buf_size;
+       /** Sample TDO and put the result in a buffer. */
+       int (*sample)(void);
+       /** Return the next unread value from the buffer. */
+       bb_value_t (*read_sample)(void);
+
+       /** Set TCK, TMS, and TDI to the given values. */
+       int (*write)(int tck, int tms, int tdi);
+       int (*reset)(int trst, int srst);
+       int (*blink)(int on);
        int (*swdio_read)(void);
        void (*swdio_drive)(bool on);
 };
index 0f7c12dd49cae13f6bf42b24db0e0473947108b5..db1ba13a49f0870805a9afe467a693b6b31d5c32 100644 (file)
@@ -33,14 +33,14 @@ static int clock_count;             /* count clocks in any stable state, only stable states
 
 static uint32_t dummy_data;
 
-static int dummy_read(void)
+static bb_value_t dummy_read(void)
 {
        int data = 1 & dummy_data;
        dummy_data = (dummy_data >> 1) | (1 << 31);
-       return data;
+       return data ? BB_HIGH : BB_LOW;
 }
 
-static void dummy_write(int tck, int tms, int tdi)
+static int dummy_write(int tck, int tms, int tdi)
 {
        /* TAP standard: "state transitions occur on rising edge of clock" */
        if (tck != dummy_clock) {
@@ -69,9 +69,10 @@ static void dummy_write(int tck, int tms, int tdi)
                }
                dummy_clock = tck;
        }
+       return ERROR_OK;
 }
 
-static void dummy_reset(int trst, int srst)
+static int dummy_reset(int trst, int srst)
 {
        dummy_clock = 0;
 
@@ -79,10 +80,12 @@ static void dummy_reset(int trst, int srst)
                dummy_state = TAP_RESET;
 
        LOG_DEBUG("reset to: %s", tap_state_name(dummy_state));
+       return ERROR_OK;
 }
 
-static void dummy_led(int on)
+static int dummy_led(int on)
 {
+       return ERROR_OK;
 }
 
 static struct bitbang_interface dummy_bitbang = {
index ccd979502e0122c3e9153e04123502331286fc18..36fc7774717a8fd949bf494082b87c0ae484e5af 100644 (file)
@@ -41,9 +41,9 @@ static volatile uint8_t *gpio_data_direction_register;
 
 /* low level command set
  */
-static int ep93xx_read(void);
-static void ep93xx_write(int tck, int tms, int tdi);
-static void ep93xx_reset(int trst, int srst);
+static bb_value_t ep93xx_read(void);
+static int ep93xx_write(int tck, int tms, int tdi);
+static int ep93xx_reset(int trst, int srst);
 
 static int ep93xx_init(void);
 static int ep93xx_quit(void);
@@ -67,12 +67,12 @@ static struct bitbang_interface ep93xx_bitbang = {
        .blink = 0,
 };
 
-static int ep93xx_read(void)
+static bb_value_t ep93xx_read(void)
 {
-       return !!(*gpio_data_register & TDO_BIT);
+       return (*gpio_data_register & TDO_BIT) ? BB_HIGH : BB_LOW;
 }
 
-static void ep93xx_write(int tck, int tms, int tdi)
+static int ep93xx_write(int tck, int tms, int tdi)
 {
        if (tck)
                output_value |= TCK_BIT;
@@ -91,10 +91,12 @@ static void ep93xx_write(int tck, int tms, int tdi)
 
        *gpio_data_register = output_value;
        nanosleep(&ep93xx_zzzz, NULL);
+
+       return ERROR_OK;
 }
 
 /* (1) assert or (0) deassert reset lines */
-static void ep93xx_reset(int trst, int srst)
+static int ep93xx_reset(int trst, int srst)
 {
        if (trst == 0)
                output_value |= TRST_BIT;
@@ -108,6 +110,8 @@ static void ep93xx_reset(int trst, int srst)
 
        *gpio_data_register = output_value;
        nanosleep(&ep93xx_zzzz, NULL);
+
+       return ERROR_OK;
 }
 
 static int set_gonk_mode(void)
index f33d10976246f1352131df3d630ae653190cb620..2a822afe97598495b6c7e3dd35d8abedfb9ab2b4 100644 (file)
@@ -82,9 +82,9 @@ static inline bool gpio_level(int g)
        return pio_base[g / 32].dr >> (g & 0x1F) & 1;
 }
 
-static int imx_gpio_read(void);
-static void imx_gpio_write(int tck, int tms, int tdi);
-static void imx_gpio_reset(int trst, int srst);
+static bb_value_t imx_gpio_read(void);
+static int imx_gpio_write(int tck, int tms, int tdi);
+static int imx_gpio_reset(int trst, int srst);
 
 static int imx_gpio_swdio_read(void);
 static void imx_gpio_swdio_drive(bool is_output);
@@ -128,12 +128,12 @@ static int speed_coeff = 50000;
 static int speed_offset = 100;
 static unsigned int jtag_delay;
 
-static int imx_gpio_read(void)
+static bb_value_t imx_gpio_read(void)
 {
-       return gpio_level(tdo_gpio);
+       return gpio_level(tdo_gpio) ? BB_HIGH : BB_LOW;
 }
 
-static void imx_gpio_write(int tck, int tms, int tdi)
+static int imx_gpio_write(int tck, int tms, int tdi)
 {
        tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
        tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio);
@@ -141,25 +141,31 @@ static void imx_gpio_write(int tck, int tms, int tdi)
 
        for (unsigned int i = 0; i < jtag_delay; i++)
                asm volatile ("");
+
+       return ERROR_OK;
 }
 
-static void imx_gpio_swd_write(int tck, int tms, int tdi)
+static int imx_gpio_swd_write(int tck, int tms, int tdi)
 {
        tdi ? gpio_set(swdio_gpio) : gpio_clear(swdio_gpio);
        tck ? gpio_set(swclk_gpio) : gpio_clear(swclk_gpio);
 
        for (unsigned int i = 0; i < jtag_delay; i++)
                asm volatile ("");
+
+       return ERROR_OK;
 }
 
 /* (1) assert or (0) deassert reset lines */
-static void imx_gpio_reset(int trst, int srst)
+static int imx_gpio_reset(int trst, int srst)
 {
        if (trst_gpio != -1)
                trst ? gpio_set(trst_gpio) : gpio_clear(trst_gpio);
 
        if (srst_gpio != -1)
                srst ? gpio_set(srst_gpio) : gpio_clear(srst_gpio);
+
+       return ERROR_OK;
 }
 
 static void imx_gpio_swdio_drive(bool is_output)
@@ -469,7 +475,7 @@ static int imx_gpio_init(void)
 
 
        LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
-                       sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE);
+                       (unsigned int) 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,
                                MAP_SHARED, dev_mem_fd, imx_gpio_peri_base);
index c9e331644fa8884f22aea2c3e6fc08e6e883a7c3..14fa9df9f7fdee1da797408bc6f697cdc0f45c0a 100644 (file)
@@ -116,7 +116,7 @@ static unsigned long dataport;
 static unsigned long statusport;
 #endif
 
-static int parport_read(void)
+static bb_value_t parport_read(void)
 {
        int data = 0;
 
@@ -127,9 +127,9 @@ static int parport_read(void)
 #endif
 
        if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK)
-               return 1;
+               return BB_HIGH;
        else
-               return 0;
+               return BB_LOW;
 }
 
 static inline void parport_write_data(void)
@@ -148,7 +148,7 @@ static inline void parport_write_data(void)
 #endif
 }
 
-static void parport_write(int tck, int tms, int tdi)
+static int parport_write(int tck, int tms, int tdi)
 {
        int i = wait_states + 1;
 
@@ -169,10 +169,12 @@ static void parport_write(int tck, int tms, int tdi)
 
        while (i-- > 0)
                parport_write_data();
+
+       return ERROR_OK;
 }
 
 /* (1) assert or (0) deassert reset lines */
-static void parport_reset(int trst, int srst)
+static int parport_reset(int trst, int srst)
 {
        LOG_DEBUG("trst: %i, srst: %i", trst, srst);
 
@@ -187,10 +189,12 @@ static void parport_reset(int trst, int srst)
                dataport_value &= ~cable->SRST_MASK;
 
        parport_write_data();
+
+       return ERROR_OK;
 }
 
 /* turn LED on parport adapter on (1) or off (0) */
-static void parport_led(int on)
+static int parport_led(int on)
 {
        if (on)
                dataport_value |= cable->LED_MASK;
@@ -198,6 +202,8 @@ static void parport_led(int on)
                dataport_value &= ~cable->LED_MASK;
 
        parport_write_data();
+
+       return ERROR_OK;
 }
 
 static int parport_speed(int speed)
@@ -365,9 +371,12 @@ static int parport_init(void)
 
 #endif /* PARPORT_USE_PPDEV */
 
-       parport_reset(0, 0);
-       parport_write(0, 0, 0);
-       parport_led(1);
+       if (parport_reset(0, 0) != ERROR_OK)
+               return ERROR_FAIL;
+       if (parport_write(0, 0, 0) != ERROR_OK)
+               return ERROR_FAIL;
+       if (parport_led(1) != ERROR_OK)
+               return ERROR_FAIL;
 
        bitbang_interface = &parport_bitbang;
 
@@ -376,7 +385,8 @@ static int parport_init(void)
 
 static int parport_quit(void)
 {
-       parport_led(0);
+       if (parport_led(0) != ERROR_OK)
+               return ERROR_FAIL;
 
        if (parport_exit) {
                dataport_value = cable->PORT_EXIT;
index c8d013666be188557fb2b334ff4dbb447b35517f..1f8fc1a11e68ccc2ccef2a33b9ac3e118be8b6dd 100644 (file)
 /* arbitrary limit on host name length: */
 #define REMOTE_BITBANG_HOST_MAX 255
 
-#define REMOTE_BITBANG_RAISE_ERROR(expr ...) \
-       do { \
-               LOG_ERROR(expr); \
-               LOG_ERROR("Terminating openocd."); \
-               exit(-1); \
-       } while (0)
-
 static char *remote_bitbang_host;
 static char *remote_bitbang_port;
 
-FILE *remote_bitbang_in;
-FILE *remote_bitbang_out;
+static FILE *remote_bitbang_file;
+static int remote_bitbang_fd;
+
+/* Circular buffer. When start == end, the buffer is empty. */
+static char remote_bitbang_buf[64];
+static unsigned remote_bitbang_start;
+static unsigned remote_bitbang_end;
+
+static int remote_bitbang_buf_full(void)
+{
+       return remote_bitbang_end ==
+               ((remote_bitbang_start + sizeof(remote_bitbang_buf) - 1) %
+                sizeof(remote_bitbang_buf));
+}
 
-static void remote_bitbang_putc(int c)
+/* Read any incoming data, placing it into the buffer. */
+static int remote_bitbang_fill_buf(void)
 {
-       if (EOF == fputc(c, remote_bitbang_out))
-               REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
+       socket_nonblock(remote_bitbang_fd);
+       while (!remote_bitbang_buf_full()) {
+               unsigned contiguous_available_space;
+               if (remote_bitbang_end >= remote_bitbang_start) {
+                       contiguous_available_space = sizeof(remote_bitbang_buf) -
+                               remote_bitbang_end;
+                       if (remote_bitbang_start == 0)
+                               contiguous_available_space -= 1;
+               } else {
+                       contiguous_available_space = remote_bitbang_start -
+                               remote_bitbang_end - 1;
+               }
+               ssize_t count = read(remote_bitbang_fd,
+                               remote_bitbang_buf + remote_bitbang_end,
+                               contiguous_available_space);
+               if (count > 0) {
+                       remote_bitbang_end += count;
+                       if (remote_bitbang_end == sizeof(remote_bitbang_buf))
+                               remote_bitbang_end = 0;
+               } else if (count == 0) {
+                       return ERROR_OK;
+               } else if (count < 0) {
+                       if (errno == EAGAIN) {
+                               return ERROR_OK;
+                       } else {
+                               LOG_ERROR("remote_bitbang_fill_buf: %s (%d)",
+                                               strerror(errno), errno);
+                               return ERROR_FAIL;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int remote_bitbang_putc(int c)
+{
+       if (EOF == fputc(c, remote_bitbang_file)) {
+               LOG_ERROR("remote_bitbang_putc: %s", strerror(errno));
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
 }
 
 static int remote_bitbang_quit(void)
 {
-       if (EOF == fputc('Q', remote_bitbang_out)) {
+       if (EOF == fputc('Q', remote_bitbang_file)) {
                LOG_ERROR("fputs: %s", strerror(errno));
                return ERROR_FAIL;
        }
 
-       if (EOF == fflush(remote_bitbang_out)) {
+       if (EOF == fflush(remote_bitbang_file)) {
                LOG_ERROR("fflush: %s", strerror(errno));
                return ERROR_FAIL;
        }
 
        /* We only need to close one of the FILE*s, because they both use the same */
        /* underlying file descriptor. */
-       if (EOF == fclose(remote_bitbang_out)) {
+       if (EOF == fclose(remote_bitbang_file)) {
                LOG_ERROR("fclose: %s", strerror(errno));
                return ERROR_FAIL;
        }
@@ -75,53 +121,83 @@ static int remote_bitbang_quit(void)
        return ERROR_OK;
 }
 
-/* Get the next read response. */
-static int remote_bitbang_rread(void)
+static bb_value_t char_to_int(int c)
 {
-       if (EOF == fflush(remote_bitbang_out)) {
-               remote_bitbang_quit();
-               REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
-       }
-
-       int c = fgetc(remote_bitbang_in);
        switch (c) {
                case '0':
-                       return 0;
+                       return BB_LOW;
                case '1':
-                       return 1;
+                       return BB_HIGH;
                default:
                        remote_bitbang_quit();
-                       REMOTE_BITBANG_RAISE_ERROR(
-                                       "remote_bitbang: invalid read response: %c(%i)", c, c);
+                       LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
+                       return BB_ERROR;
+       }
+}
+
+/* Get the next read response. */
+static bb_value_t remote_bitbang_rread(void)
+{
+       if (EOF == fflush(remote_bitbang_file)) {
+               remote_bitbang_quit();
+               LOG_ERROR("fflush: %s", strerror(errno));
+               return BB_ERROR;
+       }
+
+       /* Enable blocking access. */
+       socket_block(remote_bitbang_fd);
+       char c;
+       ssize_t count = read(remote_bitbang_fd, &c, 1);
+       if (count == 1) {
+               return char_to_int(c);
+       } else {
+               remote_bitbang_quit();
+               LOG_ERROR("read: count=%d, error=%s", (int) count, strerror(errno));
+               return BB_ERROR;
        }
 }
 
-static int remote_bitbang_read(void)
+static int remote_bitbang_sample(void)
 {
-       remote_bitbang_putc('R');
+       if (remote_bitbang_fill_buf() != ERROR_OK)
+               return ERROR_FAIL;
+       assert(!remote_bitbang_buf_full());
+       return remote_bitbang_putc('R');
+}
+
+static bb_value_t remote_bitbang_read_sample(void)
+{
+       if (remote_bitbang_start != remote_bitbang_end) {
+               int c = remote_bitbang_buf[remote_bitbang_start];
+               remote_bitbang_start =
+                       (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
+               return char_to_int(c);
+       }
        return remote_bitbang_rread();
 }
 
-static void remote_bitbang_write(int tck, int tms, int tdi)
+static int remote_bitbang_write(int tck, int tms, int tdi)
 {
        char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
-       remote_bitbang_putc(c);
+       return remote_bitbang_putc(c);
 }
 
-static void remote_bitbang_reset(int trst, int srst)
+static int remote_bitbang_reset(int trst, int srst)
 {
        char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
-       remote_bitbang_putc(c);
+       return remote_bitbang_putc(c);
 }
 
-static void remote_bitbang_blink(int on)
+static int remote_bitbang_blink(int on)
 {
        char c = on ? 'B' : 'b';
-       remote_bitbang_putc(c);
+       return remote_bitbang_putc(c);
 }
 
 static struct bitbang_interface remote_bitbang_bitbang = {
-       .read = &remote_bitbang_read,
+       .buf_size = sizeof(remote_bitbang_buf) - 1,
+       .sample = &remote_bitbang_sample,
+       .read_sample = &remote_bitbang_read_sample,
        .write = &remote_bitbang_write,
        .reset = &remote_bitbang_reset,
        .blink = &remote_bitbang_blink,
@@ -131,7 +207,7 @@ static int remote_bitbang_init_tcp(void)
 {
        struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
        struct addrinfo *result, *rp;
-       int fd;
+       int fd = 0;
 
        LOG_INFO("Connecting to %s:%s",
                        remote_bitbang_host ? remote_bitbang_host : "localhost",
@@ -199,29 +275,24 @@ static int remote_bitbang_init_unix(void)
 
 static int remote_bitbang_init(void)
 {
-       int fd;
        bitbang_interface = &remote_bitbang_bitbang;
 
+       remote_bitbang_start = 0;
+       remote_bitbang_end = 0;
+
        LOG_INFO("Initializing remote_bitbang driver");
        if (remote_bitbang_port == NULL)
-               fd = remote_bitbang_init_unix();
+               remote_bitbang_fd = remote_bitbang_init_unix();
        else
-               fd = remote_bitbang_init_tcp();
+               remote_bitbang_fd = remote_bitbang_init_tcp();
 
-       if (fd < 0)
-               return fd;
-
-       remote_bitbang_in = fdopen(fd, "r");
-       if (remote_bitbang_in == NULL) {
-               LOG_ERROR("fdopen: failed to open read stream");
-               close(fd);
-               return ERROR_FAIL;
-       }
+       if (remote_bitbang_fd < 0)
+               return remote_bitbang_fd;
 
-       remote_bitbang_out = fdopen(fd, "w");
-       if (remote_bitbang_out == NULL) {
+       remote_bitbang_file = fdopen(remote_bitbang_fd, "w+");
+       if (remote_bitbang_file == NULL) {
                LOG_ERROR("fdopen: failed to open write stream");
-               fclose(remote_bitbang_in);
+               close(remote_bitbang_fd);
                return ERROR_FAIL;
        }
 
index b8acfa2fc387ac92a5f6a5ac0cbfafa373595e53..5a4651df194b85f9a3e38ba714422b992678085a 100644 (file)
@@ -244,7 +244,7 @@ static void sysfsgpio_swdio_write(int swclk, int swdio)
  * The sysfs value will read back either '0' or '1'. The trick here is to call
  * lseek to bypass buffering in the sysfs kernel driver.
  */
-static int sysfsgpio_read(void)
+static bb_value_t sysfsgpio_read(void)
 {
        char buf[1];
 
@@ -257,7 +257,7 @@ static int sysfsgpio_read(void)
                return 0;
        }
 
-       return buf[0] != '0';
+       return buf[0] == '0' ? BB_LOW : BB_HIGH;
 }
 
 /*
@@ -266,11 +266,11 @@ static int sysfsgpio_read(void)
  * 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_write(int tck, int tms, int tdi)
+static int sysfsgpio_write(int tck, int tms, int tdi)
 {
        if (swd_mode) {
                sysfsgpio_swdio_write(tck, tdi);
-               return;
+               return ERROR_OK;
        }
 
        const char one[] = "1";
@@ -312,6 +312,8 @@ static void sysfsgpio_write(int tck, int tms, int tdi)
        last_tdi = tdi;
        last_tms = tms;
        last_tck = tck;
+
+       return ERROR_OK;
 }
 
 /*
@@ -319,7 +321,7 @@ static void sysfsgpio_write(int tck, int tms, int tdi)
  *
  * (1) assert or (0) deassert reset lines
  */
-static void sysfsgpio_reset(int trst, int srst)
+static int sysfsgpio_reset(int trst, int srst)
 {
        LOG_DEBUG("sysfsgpio_reset");
        const char one[] = "1";
@@ -339,6 +341,8 @@ static void sysfsgpio_reset(int trst, int srst)
                if (bytes_written != 1)
                        LOG_WARNING("writing trst failed");
        }
+
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums)

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)