From 28eb10f43d513770224967fe7a73e98b498aa1a9 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 4 Oct 2017 15:23:14 -0700 Subject: Ensure the buffer doesn't overflow. Tested with a variety of prime buffer sizes. Change-Id: I2b4835d46adf4c971111da88e8de4b46eb8dad41 --- src/jtag/drivers/bitbang.c | 36 ++++++++++++++++++++---------------- src/jtag/drivers/bitbang.h | 3 +++ src/jtag/drivers/remote_bitbang.c | 26 +++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 19 deletions(-) (limited to 'src/jtag') diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index bde48e0..4fdca79 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -185,10 +185,11 @@ static void bitbang_stableclocks(int num_cycles) } } -static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) +static void 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)) || @@ -202,6 +203,7 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int bitbang_end_state(saved_end_state); } + size_t buffered = 0; for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { int tms = (bit_cnt == scan_size-1) ? 1 : 0; int tdi; @@ -219,8 +221,9 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int bitbang_interface->write(0, tms, tdi); if (type != SCAN_OUT) { - if (bitbang_interface->sample) { + if (bitbang_interface->buf_size) { bitbang_interface->sample(); + buffered++; } else { int val = bitbang_interface->read(); if (val) @@ -231,17 +234,17 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int } bitbang_interface->write(1, tms, tdi); - } - if (type != SCAN_OUT && bitbang_interface->sample) { - for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { - int bytec = bit_cnt/8; - int bcval = 1 << (bit_cnt % 8); - int val = bitbang_interface->read_sample(); - if (val) - buffer[bytec] |= bcval; - else - buffer[bytec] &= ~bcval; + 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)); + } + buffered = 0; } } @@ -322,13 +325,14 @@ int bitbang_execute_queue(void) bitbang_path_move(cmd->cmd.pathmove); 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 (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 563ea10..f0b9263 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -36,6 +36,9 @@ struct bitbang_interface { /* 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. */ + /* 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); /* Return the next unread value from the buffer. */ diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 3907a07..5e78ccb 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -44,18 +44,36 @@ static FILE *remote_bitbang_in; static FILE *remote_bitbang_out; 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)); +} + /* Read any incoming data, placing it into the buffer. */ static void remote_bitbang_fill_buf(void) { fcntl(remote_bitbang_fd, F_SETFL, O_NONBLOCK); - while (1) { + 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, - sizeof(remote_bitbang_buf) - remote_bitbang_end); + contiguous_available_space); if (count > 0) { remote_bitbang_end += count; // TODO: check for overflow. @@ -77,7 +95,6 @@ static void remote_bitbang_fill_buf(void) static void remote_bitbang_putc(int c) { - remote_bitbang_fill_buf(); if (EOF == fputc(c, remote_bitbang_out)) REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno)); } @@ -145,6 +162,8 @@ static int remote_bitbang_rread(void) static void remote_bitbang_sample(void) { + remote_bitbang_fill_buf(); + assert(!remote_bitbang_buf_full()); remote_bitbang_putc('R'); } @@ -178,6 +197,7 @@ static void remote_bitbang_blink(int on) } static struct bitbang_interface remote_bitbang_bitbang = { + .buf_size = sizeof(remote_bitbang_buf) - 1, .sample = &remote_bitbang_sample, .read_sample = &remote_bitbang_read_sample, .write = &remote_bitbang_write, -- cgit v1.1