commit 1f53c2014b2e532bddb6ae59b4c6d65668849cf0 from: Sven M. Hallberg date: Sun Jan 08 14:05:29 2023 UTC check/wait for reliable connection before programming commit - 3147034552a4049027533e2b70629bcb01d95af4 commit + 1f53c2014b2e532bddb6ae59b4c6d65668849cf0 blob - 5557490ae6ce6b86a9ad629f749e4aa2a8ce189b blob + bd78fb130c3d5a2fb0f3c64d73c53c8f146e91a5 --- mc5000.c +++ mc5000.c @@ -108,6 +108,8 @@ int line; /* current line number */ int status; /* exit code */ uint8_t cksum; +#define MAXRETRY 10 /* how many times to try connecting to the board */ + static const char *lbltab[256]; static const int maxlbl = sizeof lbltab / sizeof *lbltab; static int nlabel = 0; @@ -115,6 +117,7 @@ static int nlabel = 0; void write_byte(uint8_t, FILE *); void emit_op(int, const char *, const char *, const char *); void emit_op_lbl(const char *); +int get_report(int); int read_result(int); #define STR(X) matchstr(buf, rm, MATCH_ ## X) @@ -210,7 +213,18 @@ main(int argc, char *argv[]) t.c_cc[VTIME] = 1; /* ...no input after 100 ms */ if (tcsetattr(fileno(devf), TCSAFLUSH, &t) != 0) err(1, "tcsetattr"); + + /* check/wait for reliable connection */ + if (vflag) + printf("Checking connection...\n"); + for (r = 0; r < MAXRETRY; r++) + if (get_report(mcu) != -1) + break; + if (r == MAXRETRY) + errx(1, "%s: no response from board", devfname); + if (vflag) + printf("Programming...\n"); write_byte(0x7F, devf); /* start code */ write_byte(0x30 + mcu, devf); /* chip id */ } @@ -254,7 +268,7 @@ main(int argc, char *argv[]) write_byte(cksum >> 2, devf); write_byte(0x7E, devf); /* end code */ - r = read_result(mcu); + while ((r = read_result(mcu)) == -1) ; if (r == 1) printf("MCU #%d: program accepted\n", mcu); else if (r == 0) @@ -500,7 +514,7 @@ checksum(const uint8_t *buf, size_t n) return s >> 2; } -void +int read_bytes(uint8_t *buf, int o, int n) { int i, r; @@ -508,8 +522,9 @@ read_bytes(uint8_t *buf, int o, int n) r = fread(buf + o, 1, n, devf); if (ferror(devf)) errx(1, "%s: read error", devfname); - if (r == 0) - errx(1, "%s: no response from board", devfname); + if (r == 0) /* read timed out */ + return -1; + if (vflag >= 2) { printf("read_bytes:"); for (i = 0; i < r; i++) @@ -519,10 +534,12 @@ read_bytes(uint8_t *buf, int o, int n) if (r < n) errx(1, "%s: truncated message, %d/%d bytes", devfname, r + o, n + o); + + return r; /* success */ } struct message { - enum {RESULT, REPORT} type; + enum {JUNK, RESULT, REPORT} type; int source; /* MCU number */ union { int result; /* result of programming */ @@ -538,60 +555,112 @@ read_message(struct message *m) { uint8_t buf[6]; - read_bytes(buf, 0, 1); + if (read_bytes(buf, 0, 1) == -1) + return -1; /* no response */ if (buf[0] == 0x7F) { /* start code */ - read_bytes(buf, 1, 2); - m->type = RESULT; + if (read_bytes(buf, 1, 2) == -1) + return -1; if (buf[1] < 0x30 || buf[1] > 0x39) { fprintf(stderr, "%s: invalid chip ID 0x%.2X in " "response\n", devfname, buf[1]); - return -1; + return (m->type = JUNK); } + m->type = RESULT; m->source = buf[1] - 0x30; m->result = buf[2]; } else if (buf[0] >= 0x30 && buf[0] <= 0x39) { /* ASCII digit */ - read_bytes(buf, 1, 5); - m->type = REPORT; - m->source = buf[0] - 0x30; + if (read_bytes(buf, 1, 5) == -1) + return -1; if ((buf[5] & 0x3F) != checksum(buf + 1, 4)) { fprintf(stderr, "%s: bad checksum 0x%.2X in report\n", devfname, buf[5]); - return -1; + return (m->type = JUNK); } + m->type = REPORT; + m->source = buf[0] - 0x30; m->acc = (((buf[1] & 0x0F) << 7) | (buf[2] & 0x7F)) - 1000; m->dat = (((buf[3] & 0x0F) << 7) | (buf[4] & 0x7F)) - 1000; m->prog = buf[5] & 0x40; } else { fprintf(stderr, "%s: unexpected byte 0x%.2X\n", devfname, buf[0]); - return -1; + m->type = JUNK; } return m->type; } +/* + * Read and return the result of programming the given MCU. + * Prints diagnostics and returns -1 if an unexpected message is received. + * Timeout is considered a fatal error and exits the program. + */ int read_result(int mcu) { struct message m; - for (;;) { - if (read_message(&m) == -1) /* received junk */ - continue; + if (read_message(&m) == -1) + errx(1, "%s: no response from board", devfname); - if (m.type == REPORT) { - if (vflag) - fprintf(stderr, "spurious report from MCU #%d: " - "acc %d, dat %d, %sprogrammed\n", m.source, - m.acc, m.dat, m.prog ? "" : "not "); - } else if (m.source != mcu) - fprintf(stderr, "unexpected response from MCU #%d\n", - m.source); - else - break; /* got what we wanted */ + /* ignore unexpected or invalid messages */ + if (m.type == JUNK) + return -1; + if (m.type == REPORT) { + if (vflag) + fprintf(stderr, "spurious report from MCU #%d: " + "acc %d, dat %d, %sprogrammed\n", m.source, + m.acc, m.dat, m.prog ? "" : "not "); + return -1; } + if (m.source != mcu) { + fprintf(stderr, "unexpected response from MCU #%d\n", + m.source); + return -1; + } assert(m.type == RESULT); assert(m.source == mcu); return m.result; } + +/* + * Obtain and print a status report from the given MCU. + * Prints diagnostics and returns -1 if an unexpected message is received. + * Returns -1 on timeout, 0 on success. + */ +int +get_report(int mcu) +{ + struct message m; + + write_byte(0x30 + mcu, devf); + if (read_message(&m) == -1) /* timeout */ + return -1; + + /* ignore unexpected or invalid messages */ + if (m.type == JUNK) + return -1; + if (m.type == RESULT) { + fprintf(stderr, "unexpected message from MCU #%d: ", mcu); + if (m.result == 0) + fprintf(stderr, "programming failure\n"); + else if (m.result == 1) + fprintf(stderr, "program accepted\n"); + else + fprintf(stderr, "unknown result (%d)\n", m.result); + return -1; + } + if (m.source != mcu) { + fprintf(stderr, "unexpected report from MCU #%d: " + "acc %d, dat %d, %sprogrammed\n", m.source, + m.acc, m.dat, m.prog ? "" : "not "); + return -1; + } + + if (vflag) + printf("MCU #%d: acc %d, dat %d, %sprogrammed\n", m.source, + m.acc, m.dat, m.prog ? "" : "not "); + + return 0; /* success */ +}