From b50e1f74202e18ea10f1f2cd46e9e02a9d4f0e65 Mon Sep 17 00:00:00 2001 From: Thomas Albers Date: Sun, 6 Aug 2023 10:01:18 +0200 Subject: Rewrite for new serial protocol --- upload.c | 315 --------------------------------------------------------------- 1 file changed, 315 deletions(-) delete mode 100644 upload.c (limited to 'upload.c') diff --git a/upload.c b/upload.c deleted file mode 100644 index 36434ac..0000000 --- a/upload.c +++ /dev/null @@ -1,315 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define PACKET_SIZE 8 - -#define LEN(x) (sizeof(x) / sizeof(x[0])) - -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long long ulonglong; - -enum verbose_level { - NONE, - DEBUG, - WARNING, - ERROR -}; - -// in bootloader spam \n or anything? until some buffer is full - -speed_t baud = 0; -char port[32] = {0}; -int serial_fd = -1; -FILE *file = NULL; -const char *flush = "aaaaaaaaaaaaa\n"; -int verbose = 0; - -void help() -{ - puts("help"); - exit(EXIT_SUCCESS); -} - -void die() -{ - if (file) - fclose(file); - if (serial_fd < 0) - close(serial_fd); - exit(EXIT_FAILURE); -} - -int log_msg(int lvl, const char *fmt, ...) -{ - int ret = 0; - va_list args; - if (verbose >= lvl) { - va_start(args, fmt); - ret = vprintf(fmt, args); - fflush(stdout); - va_end(args); - } - return ret; -} - -struct baud_pair { - const char *b; - speed_t c; -}; - -// Conversion table for baud rates -const struct baud_pair baud_rates[] = { - {"1200", B1200}, - {"2400", B2400}, - {"4800", B4800}, - {"9600", B9600}, - {"19200", B19200}, -}; - -int parse_argv(int argc, char *const argv[]) -{ - struct option long_opts[] = { - { "baud", required_argument, 0, 'b'}, - { "verbose", no_argument, 0, 'v'}, - { "port", required_argument, 0, 'p'}, - { "help", no_argument, 0, 'h'}, - { 0, 0, 0, 0 } - }; - - int long_index = 0; - int c; - - while ((c = getopt_long(argc, argv, "b:p:h", - long_opts, &long_index)) != -1) { - switch (c) { - case 'b': - for (int i = 0; i < LEN(baud_rates); i++) { - if (!strcmp(baud_rates[i].b, optarg)) { - baud = baud_rates[i].c; - break; - } - } - - if (baud == 0) { - fprintf(stderr, "Error: Invalid baud rate '%s'\n", optarg); - exit(EXIT_FAILURE); - } - break; - - case 'v': - verbose = 1; - break; - - case 'p': - strncpy(port, optarg, LEN(port)); - break; - - case 'h': - help(); - break; - - case '?': - help(); - break; - - default: - break; - } - } - - if (argc <= optind) { - fprintf(stderr, "Error: No file was provided to upload\n\n"); - help(); - } - - return optind; -} - -int open_tty(const char *port) -{ - int fd = open(port, O_RDWR); - - if (fd < 0) { - fprintf(stderr, "Error: Port '%s' could not be opened\n", port); - exit(EXIT_FAILURE); - } - - struct termios term; - tcgetattr(fd, &term); - - cfmakeraw(&term); - term.c_cc[VTIME] = 1; - term.c_cc[VMIN] = 0; - term.c_lflag &= ~OCRNL; - cfsetspeed(&term, baud); - - tcsetattr(fd, TCSANOW, &term); - - return fd; -} - -ssize_t read_line(int fd, uchar *buf, size_t len) -{ - int ret = 0; - ssize_t bytes_read = 0; - - // The Serial port runs at ~9600 baud. This loop, as inefficient as it is, - // won' t ever be a bottleneck - for (int i = 0; bytes_read < len; i++) { - ssize_t rd = read(fd, &buf[bytes_read], 1); - if (rd < 0) { - fprintf(stderr, "Error: read from port failed\n%s\n", - strerror(errno)); - die(); - } - - if (rd == 0) - return -1; - - bytes_read += rd; - if (buf[bytes_read - 1] == '\n') - break; - } - - buf[bytes_read] = 0; - return bytes_read; -} - -void flush_bootloader(int serial_fd) -{ - /* Clean up */ - // tcflush(serial_fd, TCIOFLUSH); - /* Send empty line to get a ready prompt from bootloader */ - write(serial_fd, flush, strlen(flush)); - tcdrain(serial_fd); -} - -/* - * Get the bootloader in a ready state, cleaning up any previous errors - */ -void begin_command(int serial_fd) -{ - char buf[32]; - int timeout = 1; - - buf[0] = 0; - - while (timeout) { - /* Comparing should stop after \n even if buf is undefined */ - while (strcmp("ready\r\n", buf) != 0) { - if (read_line(serial_fd, buf, LEN(buf)) < 0) { - timeout = 1; - log_msg(DEBUG, "timeout\n%32s\n", buf); - flush_bootloader(serial_fd); - break; - } else { - timeout = 0; - } - } - } -} - -void send_packet(int index, uint address, int plen, const uchar *packet) -{ - char obuf[128]; - int len = sprintf(obuf, "W %04X %02X ", address, plen); - - for (int i = 0; i < plen; i++) - len += sprintf(&obuf[len], "%02X", packet[i]); - - obuf[len++] = '\r'; - obuf[len++] = '\n'; - obuf[len] = '\0'; - - int cmp = 1; - char ibuf[128]; - char ebuf[128]; - - for (int attempt = 1; cmp != 0; attempt++) { - log_msg(DEBUG, "Sending packet %d, attempt %d\n", index, attempt); - - begin_command(serial_fd); - write(serial_fd, obuf, len); - - if((read_line(serial_fd, ibuf, LEN(ibuf)) == -1) - || (read_line(serial_fd, ebuf, LEN(ebuf)) == -1)) { - continue; - } - - log_msg(DEBUG, "sent: %s", obuf); - log_msg(DEBUG, "recv: %s", ibuf); - log_msg(DEBUG, "ebuf: %s", ebuf); - - cmp = strncmp(ibuf, obuf, LEN(ibuf)); - if (cmp != 0) { - usleep(100); - } - } -} - -int upload_file(FILE *file, int serial_fd) -{ - int file_size = 0; - fseek(file, 0, SEEK_END); - file_size = ftell(file); - fseek(file, 0, SEEK_SET); - - int total = (file_size / PACKET_SIZE - + ((file_size % PACKET_SIZE) == 0 ? 0 : 1)); - - printf("Sending %d bytes\n", file_size); - printf("Progress: [ %3d%% ]", 0); - fflush(stdout); - - uint address = 0x4000; - uchar packet[PACKET_SIZE]; - - for (int i = 1; !feof(file); i++) { - size_t n = fread(packet, sizeof(uchar), LEN(packet), file); - if (n > 0) { - send_packet(i, address, n, packet); - address += n; - } - printf("\rProgress: [ %3d%% ]", 100 * i / total); - fflush(stdout); - } - return 0; -} - -int main(int argc, char *argv[]) -{ - int ind = parse_argv(argc, argv); - serial_fd = open_tty(port); - FILE *file = fopen(argv[ind], "r"); - - if (!file) { - fprintf(stderr, "Error: File '%s' could not be opened\n", argv[ind]); - close(serial_fd); - exit(EXIT_FAILURE); - } - - tcflush(serial_fd, TCIOFLUSH); - flush_bootloader(serial_fd); - - upload_file(file, serial_fd); - puts("\ndone"); - - fclose(file); - close(serial_fd); - - exit(EXIT_SUCCESS); -} -- cgit v1.2.3