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);
+}