From 57640a10a66a97a07b954a25e976ff0d3a5d28b0 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 19 Oct 2017 17:56:29 +0200 Subject: Got a real rom programmer, this code is still broken but I don't care --- sw/programmer/linux/src/flash.c | 12 ++++++-- sw/programmer/linux/src/serial.c | 63 ++++++++++++++++++++++++++++++++++----- sw/programmer/linux/src/serial.h | 4 +++ sw/programmer/linux/src/z80prog | Bin 49856 -> 52072 bytes 4 files changed, 68 insertions(+), 11 deletions(-) (limited to 'sw/programmer/linux') diff --git a/sw/programmer/linux/src/flash.c b/sw/programmer/linux/src/flash.c index 24d5269..3527de8 100644 --- a/sw/programmer/linux/src/flash.c +++ b/sw/programmer/linux/src/flash.c @@ -15,6 +15,7 @@ int flash_open(const char *path, unsigned long baudrate) int flash_write(const char *romfile, void (*log)(const char *)) { int romfd; + int v; ssize_t written; struct stat romst; @@ -33,7 +34,11 @@ int flash_write(const char *romfile, void (*log)(const char *)) break; } - head.addr = (uint16_t) lseek(romfd, 0, SEEK_CUR); + head.addr = (uint16_t) lseek(romfd, 0, SEEK_CUR) - head.size; + + char logbuf[64]; + sprintf(logbuf, "[@] Writing a block of size %d at addr %d\n", head.size, head.addr); + log(logbuf); written = write(flash_serial_fd, &head, sizeof(struct flash_blk)); if (written != sizeof(struct flash_blk)) { @@ -45,8 +50,9 @@ int flash_write(const char *romfile, void (*log)(const char *)) log("[#] Some bytes might not have been written\n"); } - char logbuf[64]; - sprintf(logbuf, "[@] Written %d bytes at address %d\n", head.size, head.addr); + while (!read(flash_serial_fd, &v, 1)); + + sprintf(logbuf, "[@] Written %d bytes at address %d\n", head.size, head.addr); log(logbuf); } diff --git a/sw/programmer/linux/src/serial.c b/sw/programmer/linux/src/serial.c index e2544be..42f021e 100644 --- a/sw/programmer/linux/src/serial.c +++ b/sw/programmer/linux/src/serial.c @@ -1,9 +1,23 @@ #include "serial.h" +static int rate_to_constant(int baudrate) { +#define B(x) case x: return B##x + switch(baudrate) { + B(50); B(75); B(110); B(134); B(150); + B(200); B(300); B(600); B(1200); B(1800); + B(2400); B(4800); B(9600); B(19200); B(38400); + B(57600); B(115200); B(230400); B(460800); B(500000); + B(576000); B(921600); B(1000000);B(1152000);B(1500000); + default: return 0; + } +#undef B +} + int serial_open(const char *devpath, unsigned long baudrate) { - int fd; + int fd, speed; struct termios tty; + struct serial_struct serinfo; // struct termios tty_old; // open device @@ -11,14 +25,44 @@ int serial_open(const char *devpath, unsigned long baudrate) return -1; } + speed = rate_to_constant(baudrate); + if (speed == 0) { + /* custom divisor */ + serinfo.reserved_char[0] = 0; + if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) + return -1; + serinfo.flags &= ~ASYNC_SPD_MASK; + serinfo.flags |= ASYNC_SPD_CUST; + serinfo.custom_divisor = (serinfo.baud_base + (baudrate / 2)) / baudrate; + + if (serinfo.custom_divisor < 1) + serinfo.custom_divisor = 1; + if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) + return -1; + if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) + return -1; + if (serinfo.custom_divisor * baudrate != serinfo.baud_base) { + warnx("actual baudrate is %d / %d = %f", + serinfo.baud_base, serinfo.custom_divisor, + (float)serinfo.baud_base / serinfo.custom_divisor); + } + } + + // set custom baudrate + ioctl(fd, TIOCGSERIAL, &serinfo); + serinfo.flags = ASYNC_SPD_CUST | ASYNC_LOW_LATENCY; + serinfo.custom_divisor = serinfo.baud_base / baudrate; + ioctl(fd, TIOCSSERIAL, &serinfo); + // set parameters if (tcgetattr(fd, &tty) != 0) { + // perror("failed tcgetattr"); return -1; } - // TODO: update UI or add support for custom baudrate - // cfsetospeed(&tty, - // cfsetispeed(&tty, + cfsetispeed(&tty, speed ?: B38400); + cfsetospeed(&tty, speed ?: B38400); + cfmakeraw(&tty); tty.c_cflag &= ~PARENB; // no parity tty.c_cflag &= ~CSTOPB; // no stop bit @@ -28,16 +72,19 @@ int serial_open(const char *devpath, unsigned long baudrate) tty.c_lflag = 0; // no signaling chars, no echo, no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // no block read - tty.c_cc[VTIME] = .5; // .5 seconds read timeout + tty.c_cc[VTIME] = 5; // .5 seconds read timeout tty.c_cflag |= CREAD | CLOCAL; // turn on read and ignore ctrl lines tty.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw tty.c_oflag &= ~OPOST; // make raw - tcflush(fd , TCIFLUSH); - // if (tcsetaddr( + tcflush(fd , TCIFLUSH); // ? + + if (tcsetattr (fd, TCSANOW, &tty) != 0) { + // perror("failed tcsetattr to set serial port.\n"); + return -1; + } return fd; } - diff --git a/sw/programmer/linux/src/serial.h b/sw/programmer/linux/src/serial.h index fe21524..dd70756 100644 --- a/sw/programmer/linux/src/serial.h +++ b/sw/programmer/linux/src/serial.h @@ -7,6 +7,10 @@ #include #include #include +#include +#include +#include +#include int serial_open(const char *devpath, unsigned long baudrate); diff --git a/sw/programmer/linux/src/z80prog b/sw/programmer/linux/src/z80prog index 9787e67..e2876ee 100755 Binary files a/sw/programmer/linux/src/z80prog and b/sw/programmer/linux/src/z80prog differ -- cgit v1.2.1