From f30abc1f75f483ffe78d92d5109b6c1d700925a3 Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Fri, 23 Sep 2022 20:20:38 +0200 Subject: added x230x programming and switching utility; fe310 flash utility; --- util/Makefile | 25 ++++++++++++ util/prog.c | 79 +++++++++++++++++++++++++++++++++++++ util/switch.c | 65 +++++++++++++++++++++++++++++++ util/term.c | 40 +++++++++++++++++++ util/tty.c | 48 +++++++++++++++++++++++ util/tty.h | 1 + util/upload.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 381 insertions(+) create mode 100644 util/Makefile create mode 100644 util/prog.c create mode 100644 util/switch.c create mode 100644 util/term.c create mode 100644 util/tty.c create mode 100644 util/tty.h create mode 100644 util/upload.c (limited to 'util') diff --git a/util/Makefile b/util/Makefile new file mode 100644 index 0000000..f40aac2 --- /dev/null +++ b/util/Makefile @@ -0,0 +1,25 @@ +CFLAGS = -I/usr/local/include/libftdi1 +LDFLAGS = -lftdi1 +TARGETS = prog switch upload term + + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +all: $(TARGETS) + +prog: prog.o + $(CC) -o $@ $< $(LDFLAGS) + +switch: switch.o + $(CC) -o $@ $< $(LDFLAGS) + +term: term.o tty.o + $(CC) -o $@ $^ $(LDFLAGS) + +upload: upload.o tty.o + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -f *.o + rm -f $(TARGETS) diff --git a/util/prog.c b/util/prog.c new file mode 100644 index 0000000..0227682 --- /dev/null +++ b/util/prog.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +#define FTDI_MAX_EEPROM_SIZE 256 + +int main(int argc, char *argv[]) { + int ret; + int val; + struct ftdi_context *ftdi; + struct ftdi_version_info version; + unsigned char buf[FTDI_MAX_EEPROM_SIZE]; + + if ((ftdi = ftdi_new()) == 0) { + fprintf(stderr, "ftdi_new failed\n"); + return EXIT_FAILURE; + } + + version = ftdi_get_library_version(); + printf("Initialized libftdi %s (major: %d, minor: %d, micro: %d, snapshot ver: %s)\n", + version.version_str, version.major, version.minor, version.micro, + version.snapshot_str); + + if ((ret = ftdi_usb_open(ftdi, 0x0403, 0x6015)) < 0) { + fprintf(stderr, "Unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); + ftdi_free(ftdi); + return EXIT_FAILURE; + } + + ret = ftdi_read_eeprom(ftdi); + if (ret < 0) goto ftdi_fin; + + ret = ftdi_eeprom_decode(ftdi, 1); + if (ret < 0) goto ftdi_fin; + + ftdi_get_eeprom_value(ftdi, SELF_POWERED, &val); + printf("POWER: %x\n", val); + ftdi_get_eeprom_value(ftdi, CBUS_FUNCTION_0, &val); + printf("CBUS0: %d\n", val); + ftdi_get_eeprom_value(ftdi, CBUS_FUNCTION_1, &val); + printf("CBUS1: %d\n", val); + ftdi_get_eeprom_value(ftdi, CBUS_FUNCTION_2, &val); + printf("CBUS2: %d\n", val); + ftdi_get_eeprom_value(ftdi, CBUS_FUNCTION_3, &val); + printf("CBUS3: %d\n", val); + + ftdi_set_eeprom_value(ftdi, SELF_POWERED, 1); + ftdi_set_eeprom_value(ftdi, CBUS_FUNCTION_0, CBUSX_PWREN); + ftdi_set_eeprom_value(ftdi, CBUS_FUNCTION_1, CBUSX_IOMODE); + /* next rev hw + ftdi_set_eeprom_value(ftdi, CBUS_FUNCTION_3, CBUSX_VBUS_SENSE); + */ + ftdi_set_eeprom_value(ftdi, CBUS_FUNCTION_2, CBUSX_TRISTATE); + ftdi_set_eeprom_value(ftdi, CBUS_FUNCTION_3, CBUSX_TRISTATE); + + ret = ftdi_eeprom_build(ftdi); + if (ret < 0) goto ftdi_fin; + + ret = ftdi_get_eeprom_buf(ftdi, buf, FTDI_MAX_EEPROM_SIZE); + if (ret < 0) goto ftdi_fin; + + printf("MISC: %x\n", *buf); + + if ((argc > 1) && (strcmp(argv[1], "do") == 0)) { + ret = ftdi_write_eeprom(ftdi); + if (ret < 0) goto ftdi_fin; + } + + ret = ftdi_usb_close(ftdi); + +ftdi_fin: + if (ret < 0) { + fprintf(stderr, "ERR: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); + } + ftdi_free(ftdi); + + return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/util/switch.c b/util/switch.c new file mode 100644 index 0000000..2fc0eb6 --- /dev/null +++ b/util/switch.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#define DEV_FE310 1 +#define DEV_ESP32 2 + +void usage(char *p) { + fprintf(stderr, "Usage: %s fe310|esp32\n", p); + exit(1); +} + +int main(int argc, char *argv[]) { + int dev; + int ret; + struct ftdi_context *ftdi; + + if (argc != 2) { + usage(argv[0]); + } + if (strcmp(argv[1], "fe310") == 0) { + dev = DEV_FE310; + } else if (strcmp(argv[1], "esp32") == 0) { + dev = DEV_ESP32; + } else { + usage(argv[0]); + } + + if ((ftdi = ftdi_new()) == 0) { + fprintf(stderr, "ftdi_new failed\n"); + return EXIT_FAILURE; + } + + if ((ret = ftdi_usb_open(ftdi, 0x0403, 0x6015)) < 0) { + fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); + ftdi_free(ftdi); + return EXIT_FAILURE; + } + + switch (dev) { + case DEV_FE310: { + printf("Switch to fe310\n"); + ret = ftdi_set_bitmode(ftdi, 0x20, BITMODE_CBUS); + break; + } + + case DEV_ESP32: { + printf("Switch to esp32\n"); + ret = ftdi_set_bitmode(ftdi, 0x00, BITMODE_CBUS); + break; + } + } + if (ret < 0) goto ftdi_fin; + + ret = ftdi_usb_close(ftdi); + +ftdi_fin: + if (ret < 0) { + fprintf(stderr, "ERR: %d (%s)\n", ret, ftdi_get_error_string(ftdi)); + } + ftdi_free(ftdi); + + return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/util/term.c b/util/term.c new file mode 100644 index 0000000..a9861d5 --- /dev/null +++ b/util/term.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "tty.h" + +void usage(char *p) { + fprintf(stderr, "Usage: %s \n", p); + exit(1); +} + +int main(int argc, char *argv[]) { + int tty_fd; + + if (argc != 2) { + usage(argv[0]); + } + + tty_fd = tty_open(argv[1]); + if (tty_fd < 0) { + fprintf(stderr, "ERROR %i: %s\n", errno, strerror(errno)); + return 1; + } + + while (1) { + char buf[256]; + int rv; + + rv = read(tty_fd, buf, sizeof(buf)); + if (rv < 0) continue; + + write(STDOUT_FILENO, buf, rv); + fflush(stdout); + } +} diff --git a/util/tty.c b/util/tty.c new file mode 100644 index 0000000..be56b44 --- /dev/null +++ b/util/tty.c @@ -0,0 +1,48 @@ +#include + +#include +#include +#include + +int tty_open(char *tty_fn) { + struct termios tty; + int tty_fd; + int rv; + + tty_fd = open(tty_fn, O_RDWR); + if (tty_fd < 0) return tty_fd; + + rv = tcgetattr(tty_fd, &tty); + if (rv) return -1; + + tty.c_cflag &= ~PARENB; // No parity + tty.c_cflag &= ~CSTOPB; // One stop bit + tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size + tty.c_cflag |= CS8; // 8 bits per byte + tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hw flow control + tty.c_cflag |= (CREAD | CLOCAL); // Turn on READ & ignore ctrl lines (CLOCAL = 1) + + tty.c_lflag &= ~ICANON; + tty.c_lflag &= ~(ECHO | ECHOE |ECHONL); // Disable echo + tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP signals + tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off sw flow ctrl + tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes + + tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) + tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed +#ifndef __linux__ + tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX) + tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX) +#endif + + tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received. + tty.c_cc[VMIN] = 0; + + cfsetispeed(&tty, B115200); + cfsetospeed(&tty, B115200); + + rv = tcsetattr(tty_fd, TCSANOW, &tty); + if (rv) return -1; + + return tty_fd; +}; diff --git a/util/tty.h b/util/tty.h new file mode 100644 index 0000000..4216c4d --- /dev/null +++ b/util/tty.h @@ -0,0 +1 @@ +int tty_open(char *tty_fn); diff --git a/util/upload.c b/util/upload.c new file mode 100644 index 0000000..5eb5d81 --- /dev/null +++ b/util/upload.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "tty.h" + +static const uint8_t magic[] = + {0x2D, 0xC0, 0x3B, 0x5F, 0xEA, 0xE3, 0x1A, 0x3A, 0x83, 0x11, 0x6A, 0x33, 0x98, 0x46, 0x1C, 0x47}; + +#define ACK 0x05 +#define NACK 0x0A +#define BLK_SIZE 256 + +void usage(char *p) { + fprintf(stderr, "Usage: %s \n", p); + exit(1); +} + +uint32_t crc32x(unsigned char *buf, size_t len, uint32_t crc) { + int i; + + crc = ~crc; + while (len--) { + crc ^= *buf++; + for (i=0; i<8; i++) { + uint32_t t = ~((crc & 1) - 1); + crc = (crc >> 1) ^ (0xEDB88320 & t); + } + } + + return ~crc; +} + +void set_buffer(uint32_t addr, uint8_t *buf) { + uint32_t crc32; + + buf[0] = addr >> 24; + buf[1] = addr >> 16; + buf[2] = addr >> 8; + buf[3] = addr; + crc32 = crc32x(buf, BLK_SIZE + sizeof(uint32_t), 0xffffffff); + buf[BLK_SIZE + 4] = crc32 >> 24; + buf[BLK_SIZE + 5] = crc32 >> 16; + buf[BLK_SIZE + 6] = crc32 >> 8; + buf[BLK_SIZE + 7] = crc32; +} + +static void _write(int fd, const uint8_t *buf, size_t size) { + int rv = 0; + + do { + rv += write(fd, buf + rv, size - rv); + } while (rv != size); +} + +int main(int argc, char *argv[]) { + int tty_fd, fw_fd; + uint8_t buf[BLK_SIZE + 2 * sizeof(uint32_t)]; + uint32_t addr; + int rv; + + if (argc != 3) { + usage(argv[0]); + } + + tty_fd = tty_open(argv[1]); + if (tty_fd < 0) { + fprintf(stderr, "TTY OPEN ERROR %i: %s\n", errno, strerror(errno)); + return 1; + } + + fw_fd = open(argv[2], O_RDONLY); + if (fw_fd < 0) { + fprintf(stderr, "FW OPEN ERROR %i: %s\n", errno, strerror(errno)); + return 1; + } + + while ((rv = read(tty_fd, buf, sizeof(buf)))); + + _write(tty_fd, magic, sizeof(magic)); + *buf = NACK; + read(tty_fd, buf, 1); + if (*buf != ACK) { + fprintf(stderr, "CONNECT ERROR: %x\n", *buf); + return 1; + } + printf("CONNECTED\n"); + + addr = 0; + memset(buf, 0xff, sizeof(buf)); + do { + rv = read(fw_fd, buf + sizeof(uint32_t), BLK_SIZE); + if (rv < 0) { + fprintf(stderr, "FW READ ERROR %i: %s\n", errno, strerror(errno)); + return 1; + } + if (rv == 0) { + addr = -1; + } + + set_buffer(addr, buf); + do { + _write(tty_fd, buf, sizeof(buf)); + *buf = NACK; + read(tty_fd, buf, 1); + if (*buf == NACK) { + fprintf(stderr, "NACK...\n"); + } + } while (*buf != ACK); + addr += BLK_SIZE; + memset(buf, 0xff, sizeof(buf)); + } while (rv); + + close(tty_fd); + close(fw_fd); + + return 0; +} -- cgit v1.2.3