Add read buffer to bitbang, improving performance.
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: I7dc774e1e0f5752905ac4318fd9b85b930374a05
This commit is contained in:
parent
e94c809ce4
commit
1b11d579ea
|
@ -203,7 +203,6 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
|
for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
|
||||||
int val = 0;
|
|
||||||
int tms = (bit_cnt == scan_size-1) ? 1 : 0;
|
int tms = (bit_cnt == scan_size-1) ? 1 : 0;
|
||||||
int tdi;
|
int tdi;
|
||||||
int bytec = bit_cnt/8;
|
int bytec = bit_cnt/8;
|
||||||
|
@ -219,12 +218,26 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
|
||||||
|
|
||||||
bitbang_interface->write(0, tms, tdi);
|
bitbang_interface->write(0, tms, tdi);
|
||||||
|
|
||||||
if (type != SCAN_OUT)
|
if (type != SCAN_OUT) {
|
||||||
val = bitbang_interface->read();
|
if (bitbang_interface->sample) {
|
||||||
|
bitbang_interface->sample();
|
||||||
|
} else {
|
||||||
|
int val = bitbang_interface->read();
|
||||||
|
if (val)
|
||||||
|
buffer[bytec] |= bcval;
|
||||||
|
else
|
||||||
|
buffer[bytec] &= ~bcval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitbang_interface->write(1, tms, tdi);
|
bitbang_interface->write(1, tms, tdi);
|
||||||
|
}
|
||||||
|
|
||||||
if (type != SCAN_OUT) {
|
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)
|
if (val)
|
||||||
buffer[bytec] |= bcval;
|
buffer[bytec] |= bcval;
|
||||||
else
|
else
|
||||||
|
|
|
@ -27,7 +27,21 @@
|
||||||
struct bitbang_interface {
|
struct bitbang_interface {
|
||||||
/* low level callbacks (for bitbang)
|
/* low level callbacks (for bitbang)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Either read() or sample()/read_sample() must be implemented. */
|
||||||
|
|
||||||
|
/* Sample TDO and return 0 or 1. */
|
||||||
int (*read)(void);
|
int (*read)(void);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
/* Sample TDO and put the result in a buffer. */
|
||||||
|
void (*sample)(void);
|
||||||
|
/* Return the next unread value from the buffer. */
|
||||||
|
int (*read_sample)(void);
|
||||||
|
|
||||||
|
/* Set TCK, TMS, and TDI to the given values. */
|
||||||
void (*write)(int tck, int tms, int tdi);
|
void (*write)(int tck, int tms, int tdi);
|
||||||
void (*reset)(int trst, int srst);
|
void (*reset)(int trst, int srst);
|
||||||
void (*blink)(int on);
|
void (*blink)(int on);
|
||||||
|
|
|
@ -40,11 +40,44 @@
|
||||||
static char *remote_bitbang_host;
|
static char *remote_bitbang_host;
|
||||||
static char *remote_bitbang_port;
|
static char *remote_bitbang_port;
|
||||||
|
|
||||||
FILE *remote_bitbang_in;
|
static FILE *remote_bitbang_in;
|
||||||
FILE *remote_bitbang_out;
|
static FILE *remote_bitbang_out;
|
||||||
|
static int remote_bitbang_fd;
|
||||||
|
|
||||||
|
static char remote_bitbang_buf[64];
|
||||||
|
static unsigned remote_bitbang_start;
|
||||||
|
static unsigned remote_bitbang_end;
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
ssize_t count = read(remote_bitbang_fd,
|
||||||
|
remote_bitbang_buf + remote_bitbang_end,
|
||||||
|
sizeof(remote_bitbang_buf) - remote_bitbang_end);
|
||||||
|
if (count > 0) {
|
||||||
|
remote_bitbang_end += count;
|
||||||
|
// TODO: check for overflow.
|
||||||
|
if (remote_bitbang_end == sizeof(remote_bitbang_buf)) {
|
||||||
|
remote_bitbang_end = 0;
|
||||||
|
}
|
||||||
|
} else if (count == 0) {
|
||||||
|
return;
|
||||||
|
} else if (count < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_fill_buf: %s (%d)",
|
||||||
|
strerror(errno), errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void remote_bitbang_putc(int c)
|
static void remote_bitbang_putc(int c)
|
||||||
{
|
{
|
||||||
|
remote_bitbang_fill_buf();
|
||||||
if (EOF == fputc(c, remote_bitbang_out))
|
if (EOF == fputc(c, remote_bitbang_out))
|
||||||
REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
|
REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -75,15 +108,8 @@ static int remote_bitbang_quit(void)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the next read response. */
|
static int char_to_int(int c)
|
||||||
static int remote_bitbang_rread(void)
|
|
||||||
{
|
{
|
||||||
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) {
|
switch (c) {
|
||||||
case '0':
|
case '0':
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -96,9 +122,40 @@ static int remote_bitbang_rread(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remote_bitbang_read(void)
|
/* Get the next read response. */
|
||||||
|
static int remote_bitbang_rread(void)
|
||||||
|
{
|
||||||
|
if (EOF == fflush(remote_bitbang_out)) {
|
||||||
|
remote_bitbang_quit();
|
||||||
|
REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable blocking access. */
|
||||||
|
fcntl(remote_bitbang_fd, F_SETFL, 0);
|
||||||
|
char c;
|
||||||
|
ssize_t count = read(remote_bitbang_fd, &c, 1);
|
||||||
|
if (count == 1) {
|
||||||
|
return char_to_int(c);
|
||||||
|
} else {
|
||||||
|
remote_bitbang_quit();
|
||||||
|
REMOTE_BITBANG_RAISE_ERROR("read: count=%d, error=%s", (int) count,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remote_bitbang_sample(void)
|
||||||
{
|
{
|
||||||
remote_bitbang_putc('R');
|
remote_bitbang_putc('R');
|
||||||
|
}
|
||||||
|
|
||||||
|
static int 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();
|
return remote_bitbang_rread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +178,8 @@ static void remote_bitbang_blink(int on)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bitbang_interface remote_bitbang_bitbang = {
|
static struct bitbang_interface remote_bitbang_bitbang = {
|
||||||
.read = &remote_bitbang_read,
|
.sample = &remote_bitbang_sample,
|
||||||
|
.read_sample = &remote_bitbang_read_sample,
|
||||||
.write = &remote_bitbang_write,
|
.write = &remote_bitbang_write,
|
||||||
.reset = &remote_bitbang_reset,
|
.reset = &remote_bitbang_reset,
|
||||||
.blink = &remote_bitbang_blink,
|
.blink = &remote_bitbang_blink,
|
||||||
|
@ -199,26 +257,28 @@ static int remote_bitbang_init_unix(void)
|
||||||
|
|
||||||
static int remote_bitbang_init(void)
|
static int remote_bitbang_init(void)
|
||||||
{
|
{
|
||||||
int fd;
|
|
||||||
bitbang_interface = &remote_bitbang_bitbang;
|
bitbang_interface = &remote_bitbang_bitbang;
|
||||||
|
|
||||||
|
remote_bitbang_start = 0;
|
||||||
|
remote_bitbang_end = 0;
|
||||||
|
|
||||||
LOG_INFO("Initializing remote_bitbang driver");
|
LOG_INFO("Initializing remote_bitbang driver");
|
||||||
if (remote_bitbang_port == NULL)
|
if (remote_bitbang_port == NULL)
|
||||||
fd = remote_bitbang_init_unix();
|
remote_bitbang_fd = remote_bitbang_init_unix();
|
||||||
else
|
else
|
||||||
fd = remote_bitbang_init_tcp();
|
remote_bitbang_fd = remote_bitbang_init_tcp();
|
||||||
|
|
||||||
if (fd < 0)
|
if (remote_bitbang_fd < 0)
|
||||||
return fd;
|
return remote_bitbang_fd;
|
||||||
|
|
||||||
remote_bitbang_in = fdopen(fd, "r");
|
remote_bitbang_in = fdopen(remote_bitbang_fd, "r");
|
||||||
if (remote_bitbang_in == NULL) {
|
if (remote_bitbang_in == NULL) {
|
||||||
LOG_ERROR("fdopen: failed to open read stream");
|
LOG_ERROR("fdopen: failed to open read stream");
|
||||||
close(fd);
|
close(remote_bitbang_fd);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
remote_bitbang_out = fdopen(fd, "w");
|
remote_bitbang_out = fdopen(remote_bitbang_fd, "w");
|
||||||
if (remote_bitbang_out == NULL) {
|
if (remote_bitbang_out == NULL) {
|
||||||
LOG_ERROR("fdopen: failed to open write stream");
|
LOG_ERROR("fdopen: failed to open write stream");
|
||||||
fclose(remote_bitbang_in);
|
fclose(remote_bitbang_in);
|
||||||
|
|
Loading…
Reference in New Issue