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