diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jtag/drivers/bitbang.c | 151 | ||||
-rw-r--r-- | src/jtag/drivers/bitbang.h | 20 | ||||
-rw-r--r-- | src/jtag/drivers/remote_bitbang.c | 67 |
3 files changed, 146 insertions, 92 deletions
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 4fdca79..722a5f2 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -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,35 +164,46 @@ 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, +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(); @@ -199,7 +217,8 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, 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); } @@ -218,31 +237,45 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, if ((type != SCAN_IN) && (buffer[bytec] & bcval)) tdi = 1; - bitbang_interface->write(0, tms, tdi); + if (bitbang_interface->write(0, tms, tdi) != ERROR_OK) + return ERROR_FAIL; if (type != SCAN_OUT) { if (bitbang_interface->buf_size) { - bitbang_interface->sample(); + if (bitbang_interface->sample() != ERROR_OK) + return ERROR_FAIL; buffered++; } else { - int val = bitbang_interface->read(); - if (val) - buffer[bytec] |= bcval; - else - buffer[bytec] &= ~bcval; + switch (bitbang_interface->read()) { + case BB_LOW: + buffer[bytec] &= ~bcval; + break; + case BB_HIGH: + buffer[bytec] |= bcval; + break; + default: + return ERROR_FAIL; + } } } - bitbang_interface->write(1, tms, tdi); + 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++) { - if (bitbang_interface->read_sample()) - buffer[i/8] |= 1 << (i % 8); - else - buffer[i/8] &= ~(1 << (i % 8)); + 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; } @@ -253,8 +286,10 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, * 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) @@ -275,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) { @@ -289,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_ @@ -298,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: @@ -314,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_ @@ -322,7 +364,8 @@ 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); @@ -334,7 +377,9 @@ int bitbang_execute_queue(void) tap_state_name(cmd->cmd.scan->end_state)); #endif 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) @@ -355,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; } diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 8efdd2d..577717e 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -24,6 +24,12 @@ #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. @@ -32,21 +38,21 @@ * sample requests together. Not waiting for a value to come back can greatly * increase throughput. */ struct bitbang_interface { - /** Sample TDO and return 0 or 1. */ - int (*read)(void); + /** 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. */ - void (*sample)(void); + int (*sample)(void); /** Return the next unread value from the buffer. */ - int (*read_sample)(void); + bb_value_t (*read_sample)(void); /** Set TCK, TMS, and TDI to the given values. */ - void (*write)(int tck, int tms, int tdi); - void (*reset)(int trst, int srst); - void (*blink)(int on); + 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); }; diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 9812a7e..1f8fc1a 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -30,13 +30,6 @@ /* 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; @@ -56,7 +49,7 @@ static int remote_bitbang_buf_full(void) } /* Read any incoming data, placing it into the buffer. */ -static void remote_bitbang_fill_buf(void) +static int remote_bitbang_fill_buf(void) { socket_nonblock(remote_bitbang_fd); while (!remote_bitbang_buf_full()) { @@ -78,22 +71,28 @@ static void remote_bitbang_fill_buf(void) if (remote_bitbang_end == sizeof(remote_bitbang_buf)) remote_bitbang_end = 0; } else if (count == 0) { - return; + return ERROR_OK; } else if (count < 0) { if (errno == EAGAIN) { - return; + return ERROR_OK; } else { - REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_fill_buf: %s (%d)", + LOG_ERROR("remote_bitbang_fill_buf: %s (%d)", strerror(errno), errno); + return ERROR_FAIL; } } } + + return ERROR_OK; } -static void remote_bitbang_putc(int c) +static int remote_bitbang_putc(int c) { - if (EOF == fputc(c, remote_bitbang_file)) - REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno)); + 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) @@ -122,26 +121,27 @@ static int remote_bitbang_quit(void) return ERROR_OK; } -static int char_to_int(int c) +static bb_value_t char_to_int(int c) { 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 int remote_bitbang_rread(void) +static bb_value_t remote_bitbang_rread(void) { if (EOF == fflush(remote_bitbang_file)) { remote_bitbang_quit(); - REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno)); + LOG_ERROR("fflush: %s", strerror(errno)); + return BB_ERROR; } /* Enable blocking access. */ @@ -152,19 +152,20 @@ static int remote_bitbang_rread(void) return char_to_int(c); } else { remote_bitbang_quit(); - REMOTE_BITBANG_RAISE_ERROR("read: count=%d, error=%s", (int) count, - strerror(errno)); + LOG_ERROR("read: count=%d, error=%s", (int) count, strerror(errno)); + return BB_ERROR; } } -static void remote_bitbang_sample(void) +static int remote_bitbang_sample(void) { - remote_bitbang_fill_buf(); + if (remote_bitbang_fill_buf() != ERROR_OK) + return ERROR_FAIL; assert(!remote_bitbang_buf_full()); - remote_bitbang_putc('R'); + return remote_bitbang_putc('R'); } -static int remote_bitbang_read_sample(void) +static bb_value_t remote_bitbang_read_sample(void) { if (remote_bitbang_start != remote_bitbang_end) { int c = remote_bitbang_buf[remote_bitbang_start]; @@ -175,22 +176,22 @@ static int remote_bitbang_read_sample(void) 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 = { |