diff --git a/cmddb.c b/cmddb.c index f45d2e8..d2630f0 100644 --- a/cmddb.c +++ b/cmddb.c @@ -226,7 +226,14 @@ const struct cmddb_record commands[] = { "cgraph
[function]\n" " Analyse the range given and produce a call graph. Displays a summary\n" " of all functions if no function address is given.\n" - } + }, + { + .name = "locka", + .func = cmd_locka, + .help = +"locka [set|clear]\n" +" Show or change the status of the LOCKA flash write-protect bit.\n" + }, }; int cmddb_get(const char *name, struct cmddb_record *ret) diff --git a/devcmd.c b/devcmd.c index 9037252..562b036 100644 --- a/devcmd.c +++ b/devcmd.c @@ -631,3 +631,52 @@ int cmd_break(char **arg) return 0; } + +#define FCTL3 0x012c +#define FCTL3_LOCKA 0x40 +#define FWKEY 0xa5 +#define FRKEY 0x96 + +int cmd_locka(char **arg) +{ + const char *status = get_arg(arg); + int value = 0; + uint8_t regval[2]; + + if (status) { + if (!strcasecmp(status, "set")) { + value = FCTL3_LOCKA; + } else if (!strcasecmp(status, "clear")) { + value = 0; + } else { + printc_err("locka: unknown action: %s\n", status); + return -1; + } + } + + if (device_default->readmem(device_default, FCTL3, regval, 2) < 0) { + printc_err("locka: can't read FCTL3 register\n"); + return -1; + } + + if (regval[1] != FRKEY) { + printc_err("warning: locka: read key invalid (got 0x%02x)\n", + regval[1]); + return -1; + } + + if (status && ((regval[0] & FCTL3_LOCKA) != value)) { + printc_dbg("Toggling LOCKA bit\n"); + + regval[0] |= FCTL3_LOCKA; + regval[1] = FWKEY; + if (device_default->writemem(device_default, FCTL3, + regval, 2) < 0) { + printc_err("locka: can't write FCTL3 register\n"); + return -1; + } + } + + printc("LOCKA is %s\n", (regval[0] & FCTL3_LOCKA) ? "set" : "clear"); + return 0; +} diff --git a/devcmd.h b/devcmd.h index 7b5bbbc..fa20af9 100644 --- a/devcmd.h +++ b/devcmd.h @@ -34,5 +34,6 @@ int cmd_load(char **arg); int cmd_setbreak(char **arg); int cmd_delbreak(char **arg); int cmd_break(char **arg); +int cmd_locka(char **arg); #endif diff --git a/mspdebug.man b/mspdebug.man index 125cacd..b8000e7 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -168,7 +168,7 @@ length (64 bytes) is disassembled and shown. If symbols are available, then all addresses used as operands are translated into \fIsymbol\fR+\fIoffset\fR form. -.IP "\fBerase\fR [\fIall\fR|\fIsegment\fR] [\fIaddress\fR]" +.IP "\fBerase\fR [\fBall\fR|\fBsegment\fR] [\fIaddress\fR]" Erase the device under test. With no arguments, all code memory is erased (but not information or boot memory). With the argument "all", a mass erase is performed (the results may depend on the state of the LOCKA @@ -272,6 +272,17 @@ command is like \fBprog\fR, but it does not load symbols or erase the device before programming. The CPU is reset and halted before and after programming. +.IP "\fBlocka\fR [\fBset\fR|\fBclear\fR]" +Show or change the status of the LOCKA bit in the chip's memory +controller. The LOCKA bit is set on POR and acts as a write-protect bit +for info segment A. This segment contains factory-configured calibration +data, and under normal circumstances, should not be changed. + +If the LOCKA bit is cleared, erasing the info A segment is possible. + +The LOCKA bit also affects the behaviour of the "erase all" command. If +LOCKA is set (the default), only main memory is erased. If LOCKA is +cleared, main and information memory are both erased. .IP "\fBmd\fR \fIaddress\fR [\fIlength\fR]" Read the specified section of device memory and display it as a canonical\-style hexdump. Both arguments may be address expressions. If