diff options
Diffstat (limited to 'util')
| -rw-r--r-- | util/Makefile | 25 | ||||
| -rw-r--r-- | util/prog.c | 79 | ||||
| -rw-r--r-- | util/switch.c | 65 | ||||
| -rw-r--r-- | util/term.c | 40 | ||||
| -rw-r--r-- | util/tty.c | 48 | ||||
| -rw-r--r-- | util/tty.h | 1 | ||||
| -rw-r--r-- | util/upload.c | 123 | 
7 files changed, 381 insertions, 0 deletions
| 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ftdi.h> + +#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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ftdi.h> + +#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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include "tty.h" + +void usage(char *p) { +    fprintf(stderr, "Usage: %s <tty>\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 <stdlib.h> + +#include <fcntl.h> +#include <termios.h> +#include <unistd.h> + +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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#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 <tty> <firmware>\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; +} | 
