aboutsummaryrefslogtreecommitdiff
path: root/src/jtag
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-10-04 15:23:14 -0700
committerTim Newsome <tim@sifive.com>2017-10-04 15:23:38 -0700
commit28eb10f43d513770224967fe7a73e98b498aa1a9 (patch)
tree556a10f513487adcf762df8d017515496f32fb6b /src/jtag
parent1b11d579eab1eff6248dfc41416c6a5aeca34e39 (diff)
downloadriscv-openocd-28eb10f43d513770224967fe7a73e98b498aa1a9.zip
riscv-openocd-28eb10f43d513770224967fe7a73e98b498aa1a9.tar.gz
riscv-openocd-28eb10f43d513770224967fe7a73e98b498aa1a9.tar.bz2
Ensure the buffer doesn't overflow.
Tested with a variety of prime buffer sizes. Change-Id: I2b4835d46adf4c971111da88e8de4b46eb8dad41
Diffstat (limited to 'src/jtag')
-rw-r--r--src/jtag/drivers/bitbang.c36
-rw-r--r--src/jtag/drivers/bitbang.h3
-rw-r--r--src/jtag/drivers/remote_bitbang.c26
3 files changed, 46 insertions, 19 deletions
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,