Merge branch 'erase'
This commit is contained in:
commit
fd98116298
26
bsl.c
26
bsl.c
|
@ -212,20 +212,9 @@ static void bsl_destroy(device_t dev_base)
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bsl_erase(struct bsl_device *dev)
|
|
||||||
{
|
|
||||||
/* Constants found from viewing gdbproxy's activities */
|
|
||||||
return bsl_xfer(dev, CMD_ERASE, 0x2500, NULL, 0x0069);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bsl_ctl(device_t dev_base, device_ctl_t type)
|
static int bsl_ctl(device_t dev_base, device_ctl_t type)
|
||||||
{
|
{
|
||||||
struct bsl_device *dev = (struct bsl_device *)dev_base;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DEVICE_CTL_ERASE:
|
|
||||||
return bsl_erase(dev);
|
|
||||||
|
|
||||||
case DEVICE_CTL_HALT:
|
case DEVICE_CTL_HALT:
|
||||||
/* Ignore halt requests */
|
/* Ignore halt requests */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -320,6 +309,20 @@ static int bsl_readmem(device_t dev_base,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bsl_erase(device_t dev_base, device_erase_type_t type,
|
||||||
|
address_t addr)
|
||||||
|
{
|
||||||
|
struct bsl_device *dev = (struct bsl_device *)dev_base;
|
||||||
|
|
||||||
|
if (type != DEVICE_ERASE_MAIN) {
|
||||||
|
printc_err("bsl: only main erase is supported\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constants found from viewing gdbproxy's activities */
|
||||||
|
return bsl_xfer(dev, CMD_ERASE, 0x2500, NULL, 0x0069);
|
||||||
|
}
|
||||||
|
|
||||||
static int enter_via_fet(struct bsl_device *dev)
|
static int enter_via_fet(struct bsl_device *dev)
|
||||||
{
|
{
|
||||||
uint8_t buf[16];
|
uint8_t buf[16];
|
||||||
|
@ -372,6 +375,7 @@ device_t bsl_open(const char *device)
|
||||||
dev->base.destroy = bsl_destroy;
|
dev->base.destroy = bsl_destroy;
|
||||||
dev->base.readmem = bsl_readmem;
|
dev->base.readmem = bsl_readmem;
|
||||||
dev->base.writemem = bsl_writemem;
|
dev->base.writemem = bsl_writemem;
|
||||||
|
dev->base.erase = bsl_erase;
|
||||||
dev->base.getregs = bsl_getregs;
|
dev->base.getregs = bsl_getregs;
|
||||||
dev->base.setregs = bsl_setregs;
|
dev->base.setregs = bsl_setregs;
|
||||||
dev->base.ctl = bsl_ctl;
|
dev->base.ctl = bsl_ctl;
|
||||||
|
|
15
cmddb.c
15
cmddb.c
|
@ -124,8 +124,10 @@ const struct cmddb_record commands[] = {
|
||||||
.name = "erase",
|
.name = "erase",
|
||||||
.func = cmd_erase,
|
.func = cmd_erase,
|
||||||
.help =
|
.help =
|
||||||
"erase\n"
|
"erase [all|segment] [address]\n"
|
||||||
" Erase the device under test.\n"
|
" Erase the device under test. With no arguments, erases all of main\n"
|
||||||
|
" memory. Specify arguments to perform a mass erase, or to erase\n"
|
||||||
|
" individual segments.\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "step",
|
.name = "step",
|
||||||
|
@ -224,7 +226,14 @@ const struct cmddb_record commands[] = {
|
||||||
"cgraph <address> <length> [function]\n"
|
"cgraph <address> <length> [function]\n"
|
||||||
" Analyse the range given and produce a call graph. Displays a summary\n"
|
" Analyse the range given and produce a call graph. Displays a summary\n"
|
||||||
" of all functions if no function address is given.\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)
|
int cmddb_get(const char *name, struct cmddb_record *ret)
|
||||||
|
|
85
devcmd.c
85
devcmd.c
|
@ -138,11 +138,38 @@ int cmd_reset(char **arg)
|
||||||
|
|
||||||
int cmd_erase(char **arg)
|
int cmd_erase(char **arg)
|
||||||
{
|
{
|
||||||
|
const char *type_text = get_arg(arg);
|
||||||
|
const char *seg_text = get_arg(arg);
|
||||||
|
device_erase_type_t type = DEVICE_ERASE_MAIN;
|
||||||
|
address_t segment = 0;
|
||||||
|
|
||||||
|
if (seg_text && expr_eval(stab_default, seg_text, &segment) < 0) {
|
||||||
|
printc_err("erase: invalid expression: %s\n", seg_text);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_text) {
|
||||||
|
if (!strcasecmp(type_text, "all")) {
|
||||||
|
type = DEVICE_ERASE_ALL;
|
||||||
|
} else if (!strcasecmp(type_text, "segment")) {
|
||||||
|
type = DEVICE_ERASE_SEGMENT;
|
||||||
|
if (!seg_text) {
|
||||||
|
printc_err("erase: expected segment "
|
||||||
|
"address\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printc_err("erase: unknown erase type: %s\n",
|
||||||
|
type_text);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (device_default->ctl(device_default, DEVICE_CTL_HALT) < 0)
|
if (device_default->ctl(device_default, DEVICE_CTL_HALT) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
printc("Erasing...\n");
|
printc("Erasing...\n");
|
||||||
return device_default->ctl(device_default, DEVICE_CTL_ERASE);
|
return device_default->erase(device_default, type, segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_step(char **arg)
|
int cmd_step(char **arg)
|
||||||
|
@ -604,3 +631,59 @@ int cmd_break(char **arg)
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_default->readmem(device_default, FCTL3,
|
||||||
|
regval, 2) < 0) {
|
||||||
|
printc_err("locka: can't read FCTL3 register\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printc("LOCKA is %s\n", (regval[0] & FCTL3_LOCKA) ? "set" : "clear");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
1
devcmd.h
1
devcmd.h
|
@ -34,5 +34,6 @@ int cmd_load(char **arg);
|
||||||
int cmd_setbreak(char **arg);
|
int cmd_setbreak(char **arg);
|
||||||
int cmd_delbreak(char **arg);
|
int cmd_delbreak(char **arg);
|
||||||
int cmd_break(char **arg);
|
int cmd_break(char **arg);
|
||||||
|
int cmd_locka(char **arg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
13
device.h
13
device.h
|
@ -31,8 +31,7 @@ typedef enum {
|
||||||
DEVICE_CTL_RESET,
|
DEVICE_CTL_RESET,
|
||||||
DEVICE_CTL_RUN,
|
DEVICE_CTL_RUN,
|
||||||
DEVICE_CTL_HALT,
|
DEVICE_CTL_HALT,
|
||||||
DEVICE_CTL_STEP,
|
DEVICE_CTL_STEP
|
||||||
DEVICE_CTL_ERASE
|
|
||||||
} device_ctl_t;
|
} device_ctl_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -42,6 +41,12 @@ typedef enum {
|
||||||
DEVICE_STATUS_ERROR
|
DEVICE_STATUS_ERROR
|
||||||
} device_status_t;
|
} device_status_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEVICE_ERASE_ALL,
|
||||||
|
DEVICE_ERASE_MAIN,
|
||||||
|
DEVICE_ERASE_SEGMENT
|
||||||
|
} device_erase_type_t;
|
||||||
|
|
||||||
#define DEVICE_NUM_REGS 16
|
#define DEVICE_NUM_REGS 16
|
||||||
#define DEVICE_MAX_BREAKPOINTS 32
|
#define DEVICE_MAX_BREAKPOINTS 32
|
||||||
|
|
||||||
|
@ -71,6 +76,10 @@ struct device {
|
||||||
int (*writemem)(device_t dev, address_t addr,
|
int (*writemem)(device_t dev, address_t addr,
|
||||||
const uint8_t *mem, address_t len);
|
const uint8_t *mem, address_t len);
|
||||||
|
|
||||||
|
/* Erase memory */
|
||||||
|
int (*erase)(device_t dev, device_erase_type_t type,
|
||||||
|
address_t address);
|
||||||
|
|
||||||
/* Read/write registers */
|
/* Read/write registers */
|
||||||
int (*getregs)(device_t dev, address_t *regs);
|
int (*getregs)(device_t dev, address_t *regs);
|
||||||
int (*setregs)(device_t dev, const address_t *regs);
|
int (*setregs)(device_t dev, const address_t *regs);
|
||||||
|
|
36
fet.c
36
fet.c
|
@ -575,12 +575,11 @@ static int do_run(struct fet_device *dev, int type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_erase(struct fet_device *dev)
|
static int fet_erase(device_t dev_base, device_erase_type_t type,
|
||||||
|
address_t addr)
|
||||||
{
|
{
|
||||||
if (xfer(dev, C_RESET, NULL, 0, 3, FET_RESET_ALL, 0, 0) < 0) {
|
struct fet_device *dev = (struct fet_device *)dev_base;
|
||||||
printc_err("fet: reset before erase failed\n");
|
int fet_erase_type = FET_ERASE_MAIN;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xfer(dev, C_CONFIGURE, NULL, 0, 2, FET_CONFIG_CLKCTRL, 0x26) < 0) {
|
if (xfer(dev, C_CONFIGURE, NULL, 0, 2, FET_CONFIG_CLKCTRL, 0x26) < 0) {
|
||||||
printc_err("fet: config (1) failed\n");
|
printc_err("fet: config (1) failed\n");
|
||||||
|
@ -592,8 +591,27 @@ static int do_erase(struct fet_device *dev)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xfer(dev, C_ERASE, NULL, 0, 3, FET_ERASE_MAIN,
|
switch (type) {
|
||||||
dev->code_start, 0) < 0) {
|
case DEVICE_ERASE_MAIN:
|
||||||
|
fet_erase_type = FET_ERASE_MAIN;
|
||||||
|
addr = dev->code_start;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_ERASE_SEGMENT:
|
||||||
|
fet_erase_type = FET_ERASE_SEGMENT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_ERASE_ALL:
|
||||||
|
fet_erase_type = FET_ERASE_ALL;
|
||||||
|
addr = dev->code_start;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printc_err("fet: unsupported erase type\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xfer(dev, C_ERASE, NULL, 0, 3, fet_erase_type, addr, 0) < 0) {
|
||||||
printc_err("fet: erase command failed\n");
|
printc_err("fet: erase command failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -686,9 +704,6 @@ static int fet_ctl(device_t dev_base, device_ctl_t action)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_CTL_ERASE:
|
|
||||||
return do_erase(dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -921,6 +936,7 @@ device_t fet_open(transport_t transport, int proto_flags, int vcc_mv,
|
||||||
dev->base.setregs = fet_setregs;
|
dev->base.setregs = fet_setregs;
|
||||||
dev->base.ctl = fet_ctl;
|
dev->base.ctl = fet_ctl;
|
||||||
dev->base.poll = fet_poll;
|
dev->base.poll = fet_poll;
|
||||||
|
dev->base.erase = fet_erase;
|
||||||
|
|
||||||
dev->transport = transport;
|
dev->transport = transport;
|
||||||
dev->proto_flags = proto_flags;
|
dev->proto_flags = proto_flags;
|
||||||
|
|
17
flash_bsl.c
17
flash_bsl.c
|
@ -327,12 +327,19 @@ static int flash_bsl_readmem(device_t dev_base,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flash_bsl_erase(struct flash_bsl_device *dev)
|
static int flash_bsl_erase(device_t dev_base, device_erase_type_t type,
|
||||||
|
address_t addr)
|
||||||
{
|
{
|
||||||
|
struct flash_bsl_device *dev = (struct flash_bsl_device *)dev_base;
|
||||||
const uint8_t mass_erase_cmd[] = { MASS_ERASE };
|
const uint8_t mass_erase_cmd[] = { MASS_ERASE };
|
||||||
uint8_t response_buffer[16];
|
uint8_t response_buffer[16];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (type != DEVICE_ERASE_ALL) {
|
||||||
|
printc_err("flash_bsl_erase: only mass erase is supported\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (flash_bsl_send(dev, mass_erase_cmd, sizeof(mass_erase_cmd)) < 0) {
|
if (flash_bsl_send(dev, mass_erase_cmd, sizeof(mass_erase_cmd)) < 0) {
|
||||||
printc_err("flash_bsl_erase: failed to send erase command\n");
|
printc_err("flash_bsl_erase: failed to send erase command\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -380,7 +387,7 @@ static int flash_bsl_unlock(struct flash_bsl_device *dev)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* mass erase (this might wipe Information Memory on some devices */
|
/* mass erase (this might wipe Information Memory on some devices */
|
||||||
if (flash_bsl_erase(dev) < 0) {
|
if (flash_bsl_erase((device_t)dev, DEVICE_ERASE_ALL, 0) < 0) {
|
||||||
printc_err("flash_bsl_unlock: warning: erase failed\n");
|
printc_err("flash_bsl_unlock: warning: erase failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,12 +426,7 @@ static int flash_bsl_unlock(struct flash_bsl_device *dev)
|
||||||
|
|
||||||
static int flash_bsl_ctl(device_t dev_base, device_ctl_t type)
|
static int flash_bsl_ctl(device_t dev_base, device_ctl_t type)
|
||||||
{
|
{
|
||||||
struct flash_bsl_device *dev = (struct flash_bsl_device *)dev_base;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DEVICE_CTL_ERASE:
|
|
||||||
return flash_bsl_erase(dev);
|
|
||||||
|
|
||||||
case DEVICE_CTL_HALT:
|
case DEVICE_CTL_HALT:
|
||||||
/* Ignore halt requests */
|
/* Ignore halt requests */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -628,6 +630,7 @@ device_t flash_bsl_open(const char *device, int long_password)
|
||||||
dev->base.setregs = flash_bsl_setregs;
|
dev->base.setregs = flash_bsl_setregs;
|
||||||
dev->base.ctl = flash_bsl_ctl;
|
dev->base.ctl = flash_bsl_ctl;
|
||||||
dev->base.poll = flash_bsl_poll;
|
dev->base.poll = flash_bsl_poll;
|
||||||
|
dev->base.erase = flash_bsl_erase;
|
||||||
|
|
||||||
dev->serial_fd = open_serial_even_parity(device, B9600);
|
dev->serial_fd = open_serial_even_parity(device, B9600);
|
||||||
if (dev->serial_fd < 0) {
|
if (dev->serial_fd < 0) {
|
||||||
|
|
22
mspdebug.man
22
mspdebug.man
|
@ -166,9 +166,14 @@ length (64 bytes) is disassembled and shown.
|
||||||
|
|
||||||
If symbols are available, then all addresses used as operands are
|
If symbols are available, then all addresses used as operands are
|
||||||
translated into \fIsymbol\fR+\fIoffset\fR form.
|
translated into \fIsymbol\fR+\fIoffset\fR form.
|
||||||
.IP "\fBerase\fR"
|
.IP "\fBerase\fR [\fBall\fR|\fBsegment\fR] [\fIaddress\fR]"
|
||||||
Erase the device under test. All code memory is erased (but not
|
Erase the device under test. With no arguments, all code memory is erased
|
||||||
information or boot memory).
|
(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
|
||||||
|
bit in the flash memory controller).
|
||||||
|
|
||||||
|
Specify "segment" and a memory address to erase an individual flash
|
||||||
|
segment.
|
||||||
.IP "\fBgdb\fR [\fIport\fR]"
|
.IP "\fBgdb\fR [\fIport\fR]"
|
||||||
Start a GDB remote stub, optionally specifying a TCP port to listen on.
|
Start a GDB remote stub, optionally specifying a TCP port to listen on.
|
||||||
If no port is given, the default port is 2000.
|
If no port is given, the default port is 2000.
|
||||||
|
@ -265,6 +270,17 @@ command is like \fBprog\fR, but it does not load symbols or erase
|
||||||
the device before programming.
|
the device before programming.
|
||||||
|
|
||||||
The CPU is reset and halted before and after 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]"
|
.IP "\fBmd\fR \fIaddress\fR [\fIlength\fR]"
|
||||||
Read the specified section of device memory and display it as a
|
Read the specified section of device memory and display it as a
|
||||||
canonical\-style hexdump. Both arguments may be address expressions. If
|
canonical\-style hexdump. Both arguments may be address expressions. If
|
||||||
|
|
4
prog.c
4
prog.c
|
@ -34,8 +34,8 @@ int prog_flush(struct prog_data *prog)
|
||||||
|
|
||||||
if (!prog->have_erased && (prog->flags & PROG_WANT_ERASE)) {
|
if (!prog->have_erased && (prog->flags & PROG_WANT_ERASE)) {
|
||||||
printc("Erasing...\n");
|
printc("Erasing...\n");
|
||||||
if (device_default->ctl(device_default,
|
if (device_default->erase(device_default,
|
||||||
DEVICE_CTL_ERASE) < 0)
|
DEVICE_ERASE_MAIN, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
prog->have_erased = 1;
|
prog->have_erased = 1;
|
||||||
|
|
29
sim.c
29
sim.c
|
@ -504,10 +504,6 @@ static int sim_ctl(device_t dev_base, device_ctl_t op)
|
||||||
dev->regs[MSP430_REG_PC] = MEM_GETW(dev, 0xfffe);
|
dev->regs[MSP430_REG_PC] = MEM_GETW(dev, 0xfffe);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case DEVICE_CTL_ERASE:
|
|
||||||
memset(dev->memory, 0xff, MEM_SIZE);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case DEVICE_CTL_HALT:
|
case DEVICE_CTL_HALT:
|
||||||
dev->running = 0;
|
dev->running = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -523,6 +519,30 @@ static int sim_ctl(device_t dev_base, device_ctl_t op)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sim_erase(device_t dev_base, device_erase_type_t type,
|
||||||
|
address_t addr)
|
||||||
|
{
|
||||||
|
struct sim_device *dev = (struct sim_device *)dev_base;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DEVICE_ERASE_MAIN:
|
||||||
|
memset(dev->memory + 0x2000, 0xff, MEM_SIZE - 0x2000);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_ERASE_ALL:
|
||||||
|
memset(dev->memory, 0xff, MEM_SIZE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_ERASE_SEGMENT:
|
||||||
|
addr &= ~0x3f;
|
||||||
|
addr &= (MEM_SIZE - 1);
|
||||||
|
memset(dev->memory + addr, 0xff, 64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static device_status_t sim_poll(device_t dev_base)
|
static device_status_t sim_poll(device_t dev_base)
|
||||||
{
|
{
|
||||||
struct sim_device *dev = (struct sim_device *)dev_base;
|
struct sim_device *dev = (struct sim_device *)dev_base;
|
||||||
|
@ -583,6 +603,7 @@ device_t sim_open(sim_fetch_func_t fetch_func,
|
||||||
dev->base.destroy = sim_destroy;
|
dev->base.destroy = sim_destroy;
|
||||||
dev->base.readmem = sim_readmem;
|
dev->base.readmem = sim_readmem;
|
||||||
dev->base.writemem = sim_writemem;
|
dev->base.writemem = sim_writemem;
|
||||||
|
dev->base.erase = sim_erase;
|
||||||
dev->base.getregs = sim_getregs;
|
dev->base.getregs = sim_getregs;
|
||||||
dev->base.setregs = sim_setregs;
|
dev->base.setregs = sim_setregs;
|
||||||
dev->base.ctl = sim_ctl;
|
dev->base.ctl = sim_ctl;
|
||||||
|
|
Loading…
Reference in New Issue