Commit Diff


commit - d8d8053101292a72f634e4aa888e4c796f48c640
commit + 2c2a629300a971043a6fc54136a390d26e2e9ee6
blob - 77d5b6bd556b9520627cffeb59079dfcb82cad79
blob + 34735651bf862c735090f4a6682c53469d6466e6
--- mc5000.c
+++ mc5000.c
@@ -100,18 +100,21 @@ FILE *outf = NULL;	/* output file */
 FILE *devf = NULL;	/* serial port */
 FILE *inf = NULL;	/* input file */
 const char *fname;	/* input file name */
+const char *devfname;	/* serial port device file name */
 int mcu = 1;		/* programming target */
+int vflag;		/* verbosity */
 int line;		/* current line number */
 int status;		/* exit code */
-uint8_t checksum;
+uint8_t cksum;
 
 static const char *lbltab[256];
 static const int maxlbl = sizeof lbltab / sizeof *lbltab;
 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 *);
-void emit_byte(int); // XXX
+int read_result(int);
 
 #define STR(X) matchstr(buf, rm, MATCH_ ## X)
 #define CHR(X) matchchr(buf, rm, MATCH_ ## X)
@@ -120,7 +123,7 @@ void
 usage(FILE *f, int x)
 {
 	extern const char *__progname;
-	fprintf(f, "usage: %s [-u num] [-l dev | -o file] [file]\n",
+	fprintf(f, "usage: %s [-v] [-u num] [-l dev | -o file] [file]\n",
 	    __progname);
 	exit(x);
 }
@@ -140,13 +143,14 @@ main(int argc, char *argv[])
 	}
 
 	/* handle command line options */
-	while ((r = getopt(argc, argv, "hl:o:u:")) != -1) {
+	while ((r = getopt(argc, argv, "hl:o:u:v")) != -1) {
 		switch (r) {
 		case 'h':
 			usage(stdout, 0);
 		case 'l':
-			if ((devf = fopen(optarg, "r+")) == NULL)
-				err(1, "%s", optarg);
+			devfname = optarg;
+			if ((devf = fopen(devfname, "r+")) == NULL)
+				err(1, "%s", devfname);
 			outf = devf;
 			break;
 		case 'o':
@@ -162,6 +166,9 @@ main(int argc, char *argv[])
 				    "expects a single digit MCU number",
 				    optarg, r);
 			break;
+		case 'v':
+			vflag++;
+			break;
 		default:
 			usage(stderr, 1);
 		}
@@ -203,8 +210,8 @@ main(int argc, char *argv[])
 		if (tcsetattr(fileno(devf), TCSAFLUSH, &t) != 0)
 			err(1, "tcsetattr");
 
-		emit_byte(0x7F);		/* start code */
-		emit_byte(0x30 + mcu);	/* chip id */
+		write_byte(0x7F, devf);		/* start code */
+		write_byte(0x30 + mcu, devf);	/* chip id */
 	}
 
 	/* process input */
@@ -243,48 +250,42 @@ main(int argc, char *argv[])
 
 	/* finish programming */
 	if (devf != NULL) {
-		uint8_t resp[3] = {};
+		write_byte(cksum >> 2, devf);
+		write_byte(0x7E, devf);		/* end code */
 
-		checksum = -checksum >> 2;
-		emit_byte(checksum);
-		emit_byte(0x7E);		/* end code */
-
-		/* read and validate response */
-		if ((r = fread(resp, 1, sizeof resp, devf)) < sizeof resp) {
-			for (int i = 0; i < sizeof resp; i++)	// XXX
-				fprintf(stderr, " %.2X", resp[i]);
-			fprintf(stderr, "\n");
-			errx(1, "short read (%d bytes) from board: %s%s", r,
-				ferror(devf) ? "read error" : "",
-				feof(devf) ? "end of file" : "");
-		}
-		if (resp[0] != 0x7F)
-			errx(1, "unexpected response (0x%.2x)", resp[0]);
-		if (resp[1] != 0x30 + mcu)
-			errx(1, "wrong chip ID (0x%.2x) in response", resp[1]);
-		if (resp[2] == 1)
+		r = read_result(mcu);
+		if (r == 1)
 			printf("MCU #%d: program accepted\n", mcu);
-		else if (resp[2] == 0)
+		else if (r == 0)
 			errx(1, "MCU #%d: programming failure", mcu);
 		else
-			errx(1, "MCU #%d: unknown result (%d)", mcu, resp[2]);
+			errx(1, "MCU #%d: unknown result (%d)", mcu, r);
 	}
 
 	return status;
 }
 
 void
+write_byte(uint8_t x, FILE *f)
+{
+	if (f == NULL)
+		return;
+
+	fputc(x, f);
+
+	if (f == devf) {
+		struct timespec ts = {0, 10 * 100000L};		/* 10 ms */
+		nanosleep(&ts, NULL);	// XXX could be interrupted
+	}
+}
+
+void
 emit_byte(int n)
 {
 	assert(n >= 0);
 	assert(n < 256);
-	if (outf != NULL)
-		fputc(n, outf);
-	checksum += n;
-
-	// XXX
-	struct timespec ts = {0, 10 * 100000L};		/* 10 ms */
-	nanosleep(&ts, NULL);	// XXX could be interrupted
+	write_byte(n, outf);
+	cksum -= n;
 }
 
 void
@@ -482,3 +483,109 @@ emit_op_lbl(const char *arg)
 	emit_byte(OP_LBL << 2);
 	emit_byte(find_label(arg));
 }
+
+uint8_t
+checksum(const uint8_t *buf, size_t n)
+{
+	uint8_t s = 0;
+
+	while (n-- > 0)
+		s -= *buf++;
+
+	return s >> 2;
+}
+
+void
+read_bytes(uint8_t *buf, int o, int n)
+{
+	int i, r;
+
+	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 (vflag >= 2) {
+		printf("read_bytes:");
+		for (i = 0; i < r; i++)
+			printf(" %.2X", buf[o + i]);
+		printf("\n");
+	}
+	if (r < n)
+		errx(1, "%s: truncated message, %d/%d bytes", devfname,
+		    r + o, r + n);
+}
+
+struct message {
+	enum {RESULT, REPORT} type;
+	int source;				/* MCU number */
+	union {
+		int result;			/* result of programming */
+		struct {
+			int acc, dat;		/* register values */
+			int prog;		/* is MCU programmed? */
+		};
+	};
+};
+
+int
+read_message(struct message *m)
+{
+	uint8_t buf[6];
+	
+	read_bytes(buf, 0, 1);
+	if (buf[0] == 0x7F) {				/* start code */
+		read_bytes(buf, 1, 2);
+		m->type = RESULT;
+		if (buf[1] < 0x30 || buf[1] > 0x39) {
+			fprintf(stderr, "%s: invalid chip ID 0x%.2X in "
+			    "response\n", devfname, buf[1]);
+			return -1;
+		}
+		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 ((buf[5] & 0x3F) != checksum(buf + 1, 4)) {
+			fprintf(stderr, "%s: bad checksum 0x%.2X in report\n",
+			    devfname, buf[5]);
+			return -1;
+		}
+		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;
+	}
+
+	return m->type;
+}
+
+int
+read_result(int mcu)
+{
+	struct message m;
+
+	for (;;) {
+		if (read_message(&m) == -1)	/* junk */
+			continue;
+
+		if (m.type == REPORT)
+			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, "spurious response from MCU #%d\n",
+			    m.source);
+		else
+			break;			/* success */
+	}
+
+	assert (m.type == RESULT);
+	assert (m.source == mcu);
+	return m.result;
+}
blob - 68d770f61b16ef5842d5e462cdba5d61701aedb9
blob + a71c3fecf871c5cdc3961dfbcc942729d05fad2d
--- notes
+++ notes
@@ -1,7 +1,16 @@
-serial programming:
-
 - both microcontrollers are directly connected to the TX and RX lines of the
   USB serial chip.
+
+requesting MCU status:
+ 1. send chip ID (0x31 or 0x32)
+ 2. receive 6-byte report from chip:
+    a. chip ID
+    b. acc + 1000 = xxxxhhhh xlllllll (11 significant bits)
+    c. dat + 1000 = xxxxhhhh xlllllll (11 significant bits)
+    d. checksum over acc and dat
+
+programming:
+
 - a start byte followed by a chip ID indicates which MCU should receive/respond
 - maximum program size: 255
 
@@ -11,7 +20,7 @@ protocol:
 3. send program
 4. send checksum (over program)
 5. send end code (0x7E)
-6. expect confirmation from chip:
+6. expect 3-byte confirmation from chip:
    a. start code (0x7F)
    b. chip ID
    c. result (0x01 = success, 0x00 = failure)