shithub: stm32up

Download patch

ref: 252d709ce24e5544d9a6fc6faea2adf861c957ff
parent: dc316f180ae632e71f14a20b7ba0cf0168cdc8d8
author: k <k@santiago>
date: Tue Aug 1 11:13:18 EDT 2023

added code

--- /dev/null
+++ b/.gitignore
@@ -1,0 +1,2 @@
+*.out
+stm32up.*
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,14 @@
+</$objtype/mkfile
+BIN=/$objtype/bin
+
+TARG=stm32up
+OFILES=\
+	stm32up.$O\
+
+UPDATE=\
+	mkfile\
+	$HFILES\
+	${OFILES:%.$O=%.c}\
+	${TARG:%=/386/bin/%}\
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/stm32up.c
@@ -1,0 +1,518 @@
+#include <u.h>
+#include <libc.h>
+
+static int debug = 0;
+static uchar buf[256];
+
+enum {
+	Doinfo,
+	Doread,
+	Dowrite,
+	Dogo,
+	Doreadprot,
+	Doreadunprot,
+	Dowriteprot,
+	Dowriteunprot,
+	Docsum
+};
+
+enum Uartcmd {
+	Nop			= 0x00,
+	Full		= 0xFF,
+	Ack			= 0x79,
+	Nack		= 0x1F,
+	Conninit	= 0x7F,
+	Get			= 0x00,
+	Getversion	= 0x01,
+	Getid		= 0x02,
+	Read		= 0x11,
+	Go			= 0x21,
+	Write		= 0x31,
+	Erase		= 0x43,
+	Eraseext	= 0x44,
+	Special		= 0x50,
+	Specialext	= 0x51,
+	Writeprot	= 0x63,
+	Writeunprot	= 0x73,
+	Readprot	= 0x82,
+	Readunprot	= 0x92,
+	Checksum	= 0xA1	// this is not yet implemented
+};
+
+void
+stm_info(int dev)
+{
+	if(debug)
+		fprint(2, "acquiring device info\n");
+
+	// get the protocol version and commands
+	buf[0] = Get; buf[1] = Full ^ Get;
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write: %r\n");
+		exits("protoerr");;
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'get' rejected\n");
+		exits("protoerr");;
+	}
+	if(readn(dev, buf, 14) == 0 || buf[0] != 11 || buf[13] != Ack) {
+		fprint(2, "protocol error while getting device info\n");
+		exits("protoerr");;
+	}
+
+	fprint(2, "protocol version: %x\n", buf[1]);
+
+	if(debug) {
+		for(int i = 0; i < 14; i++)
+			fprint(2, "0x%02x ", buf[i]);
+		fprint(2, "\n");
+	}
+
+	if(buf[2] != Get ||
+		buf[3] != Getversion ||
+		buf[4] != Getid ||
+		buf[5] != Read ||
+		buf[6] != Go ||
+		buf[7] != Write ||
+		(buf[8] != Erase && buf[8] != Eraseext) ||
+		buf[9] != Writeprot ||
+		buf[10] != Writeunprot ||
+		buf[11] != Readprot ||
+		buf[12] != Readunprot) {
+		fprint(2, "command code mismatch, run with -d\n");
+		return;
+	}
+
+	// get the device id
+	if(debug)
+		fprint(2, "getting device id\n");
+	buf[0] = Getid; buf[1] = Full ^ Getid;
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");;
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'get id' command rejected\n");
+		exits("protoerr");;
+	}
+	if(readn(dev, buf, 4) == 0 || buf[0] != 1 || buf[3] != Ack) {
+		fprint(2, "protocol error while getting device id\n");
+		exits("protoerr");;
+	}
+
+	fprint(2, "device id: %x%x\n", buf[1], buf[2]);
+}
+
+void
+stm_protect(int dev, int acmd)
+{
+	char *cmds;
+	int cmd;
+
+	switch(acmd) {
+	case Doreadprot: cmd = Readprot; cmds = "read protect"; break;
+	case Doreadunprot: cmd = Readunprot; cmds = "read unprotect"; break;
+	case Dowriteunprot: cmd = Writeunprot; cmds = "write unprotect"; break;
+	default:
+		fprint(2, "stm_protect does not handle this command\n");
+		exits("apperr");
+	}
+
+	if(debug)
+		fprint(2, "%s device\n", cmds);
+
+	buf[0] = cmd; buf[1] = Full ^ cmd;
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");;
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'%s' command rejected\n", cmds);
+		exits("protoerr");;
+	}
+
+	buf[0] = Ack;
+	if(write(dev, buf, 1) < 0) {
+		fprint(2, "unable to ack %s", cmds);
+		exits("protoerr");;
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'%s' unable to ack\n", cmds);
+		exits("protoerr");;
+	}
+
+	fprint(2, "%s done\n", cmds);
+}
+
+void
+stm_readpage(int dev, uvlong addr, uchar sz) // size - 1
+{
+	if(addr + (sz + 1) < addr) {
+		fprint(2, "addr + sz < addr; please check values\n");
+		exits("protoerr");
+	}
+
+	buf[0] = Read; buf[1] = Full ^ Read;
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'read memory' command rejected\n");
+		exits("protoerr");
+	}
+
+	// send the start address
+	buf[0] = (addr >> 24) & 0xFF;
+	buf[1] = (addr >> 16) & 0xFF;
+	buf[2] = (addr >> 8) & 0xFF;
+	buf[3] = addr & 0xFF;
+	buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3];
+
+	if(write(dev, buf, 5) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "read memory address rejected\n");
+		exits("protoerr");
+	}
+
+	// send the size
+	buf[0] = sz; buf[1] = Full ^ buf[0];
+
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "read command rejected; check address and count\n");
+		exits("protoerr");
+	}
+
+	// read contents
+	int c = readn(dev, buf, sz + 1);
+	if(c != sz + 1) {
+		fprint(2, "memory read error, address 0x%08llx, size-1 0x%02x, c %d\n", addr, sz, c);
+		exits("apperr");
+	}
+	write(1, buf, c);
+}
+
+void
+stm_writepage(int dev, uvlong addr, uchar sz) // size - 1
+{
+	if(addr + (sz + 1) < addr) {
+		fprint(2, "addr + sz < addr; please check values\n");
+		exits("protoerr");
+	}
+
+	buf[0] = Write; buf[1] = Full ^ Write;
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'write memory' command rejected\n");
+		exits("protoerr");
+	}
+
+	// send the start address
+	buf[0] = (addr >> 24) & 0xFF;
+	buf[1] = (addr >> 16) & 0xFF;
+	buf[2] = (addr >> 8) & 0xFF;
+	buf[3] = addr & 0xFF;
+	buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3];
+
+	if(write(dev, buf, 5) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "write memory address rejected\n");
+		exits("protoerr");
+	}
+
+	// send the size
+	buf[0] = sz; buf[1] = Full ^ buf[0];
+
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "write command rejected; check address and count\n");
+		exits("protoerr");
+	}
+
+	// write contents
+	int c = readn(0, buf, sz + 1);
+	if(c != sz + 1) {
+		fprint(2, "memory write error, address 0x%08llx, size-1 0x%02x, c %d\n", addr, sz, c);
+		exits("apperr");
+	}
+	write(dev, buf, c);
+}
+
+void
+stm_read(int dev, uvlong addr, uvlong sz)
+{
+	if(sz == 0) {
+		fprint(2, "read size cannot be 0\n");
+		exits("protoerr");
+	}
+	if(addr + sz < addr) {
+		fprint(2, "addr + sz < addr; please check values\n");
+		exits("protoerr");
+	}
+
+
+	fprint(2, "reading device memory 0x%08llx, size: 0x%08llx\n", addr, sz);
+
+	// start read memory command
+	uvlong caddr = addr;
+	uvlong csz = sz;
+
+	while(caddr < (addr + sz)) {
+		uchar rsz = 0xFF;
+		if(csz < 0x100)
+			rsz = csz - 1;
+
+		stm_readpage(dev, caddr, rsz);
+
+		caddr = caddr + (rsz + 1);
+		csz = csz - (rsz + 1);
+	}
+
+	fprint(2, "memory read\n");
+}
+
+void
+stm_write(int dev, uvlong addr, uvlong sz)
+{
+	if(sz == 0) {
+		fprint(2, "write size cannot be 0\n");
+		exits("protoerr");
+	}
+	if(addr + sz < addr) {
+		fprint(2, "addr + sz < addr; please check values\n");
+		exits("protoerr");
+	}
+
+	fprint(2, "writing device memory 0x%08llx, size: 0x%08llx\n", addr, sz);
+
+	// start read memory command
+	uvlong caddr = addr;
+	uvlong csz = sz;
+
+	while(caddr < (addr + sz)) {
+		uchar rsz = 0xFF;
+		if(csz < 0x100)
+			rsz = csz - 1;
+
+		stm_writepage(dev, caddr, rsz);
+
+		caddr = caddr + (rsz + 1);
+		csz = csz - (rsz + 1);
+	}
+
+	fprint(2, "memory written\n");
+}
+
+void
+stm_go(int dev, uvlong addr)
+{
+	if(debug)
+		fprint(2, "device requested to jump to 0x%08llx\n", addr);
+
+	// get the protocol version and commands
+	buf[0] = Go; buf[1] = Full ^ Go;
+	if(write(dev, buf, 2) < 0) {
+		fprint(2, "unable to write: %r\n");
+		exits("protoerr");;
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "'go' rejected\n");
+		exits("protoerr");;
+	}
+
+	// send the start address
+	buf[0] = (addr >> 24) & 0xFF;
+	buf[1] = (addr >> 16) & 0xFF;
+	buf[2] = (addr >> 8) & 0xFF;
+	buf[3] = addr & 0xFF;
+	buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3];
+
+	if(write(dev, buf, 5) < 0) {
+		fprint(2, "unable to write\n");
+		exits("protoerr");
+	}
+
+	if(readn(dev, buf, 1) == 0 || buf[0] != Ack) {
+		fprint(2, "go address rejected\n");
+		exits("protoerr");
+	}
+
+	fprint(2, "device jumped to 0x%08llx\n", addr);
+}
+
+void
+stm_checksum(int dev)
+{
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-d] [-D device] command args ..\n", argv0);
+	fprint(2, "	info\n");
+	fprint(2, "	read 	addr size\n");
+	fprint(2, "	write 	addr size\n");
+	fprint(2, "	go		addr\n");
+	fprint(2, "	readp, readunp, writeunp\n");
+	fprint(2, "	TODO: writep,csum\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	char* devpath = "/dev/eia0";
+	int action = -1;
+	int dev = -1;
+
+	uvlong addr = 0;
+	uvlong sz = 0;
+
+	ARGBEGIN {
+	case 'd':
+		debug = 1;
+		break;
+	case 'D':
+		devpath = EARGF(usage());
+		break;
+	default: usage();
+	} ARGEND
+
+	if(argv[0] == 0)
+		usage();
+
+	if(!strcmp(argv[0], "info"))
+		action = Doinfo;
+	if(!strcmp(argv[0], "read")) {
+		if(argv[1] == 0 || argv[2] == 0)
+			usage();
+		addr = strtoull(argv[1], nil, 16);
+		sz = strtoull(argv[2], nil, 16);
+		action = Doread;
+	}
+	if(!strcmp(argv[0], "write")) {
+		if(argv[1] == 0 || argv[2] == 0)
+			usage();
+		addr = strtoull(argv[1], nil, 16);
+		sz = strtoull(argv[2], nil, 16);
+		action = Dowrite;
+	}
+	if(!strcmp(argv[0], "go")) {
+		if(argv[1] == 0)
+			usage();
+		addr = strtoull(argv[1], nil, 16);
+		action = Dogo;
+	}
+	if(!strcmp(argv[0], "readp"))
+		action = Doreadprot;
+	if(!strcmp(argv[0], "readunp"))
+		action = Doreadunprot;
+	if(!strcmp(argv[0], "writeunp"))
+		action = Doreadunprot;
+	if(!strcmp(argv[0], "csum"))
+		action = Docsum;
+	if(action < 0)
+		usage();
+
+	// set serial operating parameters
+	if(debug)
+		fprint(2, "setting modem to 9600 8E1\n");
+	int devctl = open(smprint("%sctl", devpath), OWRITE);
+	if(devctl < 0) {
+		fprint(2, "unable to open device ctl %sctl: %r\n", devpath);
+		exits("deverr");
+	}
+
+	if(write(devctl, "b9600\n", 8) < 0) {
+		fprint(2, "error: unable to set serial baud: %r\n");
+		exits("deverr");
+	}
+	if(write(devctl, "l8\n", 3) < 0) {
+		fprint(2, "error: unable to set serial length: %r\n");
+		exits("deverr");
+	}
+	if(write(devctl, "pe\n", 3) < 0) {
+		fprint(2, "error: unable to set serial parity: %r\n");
+		exits("deverr");
+	}
+	if(write(devctl, "s1\n", 3) < 0) {
+		fprint(2, "error: unable to set serial stop bits: %r\n");
+		exits("deverr");
+	}
+	if(write(devctl, "f\n", 3) < 0) {
+		fprint(2, "error: unable to flush the serial line: %r\n");
+		exits("deverr");
+	}
+
+	if(debug)
+		fprint(2, "modem set up accordingly\n");
+
+	// opening serial line
+	if(debug)
+		fprint(2, "opening %s\n", devpath);
+	dev = open(devpath, ORDWR);
+	if(dev < 0) {
+		fprint(2, "unable to open device %s: %r\n", devpath);
+		exits("deverr");
+	}
+
+	// initiate connection; send Conninit, and wait for Ack
+	if(debug)
+		fprint(2, "initiating connection\n");
+	buf[0] = Conninit;
+	if(write(dev, buf, 1) < 0) {
+		fprint(2, "error writing while initiating\n");
+		exits("connerr");
+	}
+
+	if(readn(dev, buf, 1) <= 0 || buf[0] != Ack) {
+		fprint(2, "connection could not be initiated, got %x\n", buf[0]);
+		exits("connerr");
+	}
+
+	// handle action
+	switch(action) {
+	case Doinfo: stm_info(dev); break;
+	case Doread: stm_read(dev, addr, sz); break;
+	case Dowrite: stm_write(dev, addr, sz); break;
+	case Doreadprot:
+	case Doreadunprot:
+	case Dowriteunprot:
+		stm_protect(dev, action); break;
+	case Dogo: stm_go(dev, addr); break;
+	case Docsum: stm_checksum(dev); break;
+	default: exits("apperr");
+	}
+
+	if(debug)
+		fprint(2, "exiting\n");
+
+	exits(nil);
+}