target_flash: abstract target flash mode/flash preparation

This commit is contained in:
Rafael Silva 2022-08-22 11:21:41 +01:00 committed by Rachel Mant
parent 520be57e3d
commit e72edc0579
5 changed files with 65 additions and 23 deletions

View File

@ -543,7 +543,6 @@ static void handle_v_packet(char *packet, const size_t plen)
uint32_t addr = 0;
uint32_t len = 0;
int bin;
static uint8_t flash_mode = 0;
if (sscanf(packet, "vAttach;%08" PRIx32, &addr) == 1) {
/* Attach to remote target processor */
@ -631,16 +630,10 @@ static void handle_v_packet(char *packet, const size_t plen)
return;
}
if (!flash_mode) {
/* Reset target if first flash command! */
/* This saves us if we're interrupted in IRQ context */
target_reset(cur_target);
flash_mode = 1;
}
if (target_flash_erase(cur_target, addr, len) == 0)
gdb_putpacketz("OK");
else {
flash_mode = 0;
target_flash_complete(cur_target);
gdb_putpacketz("EFF");
}
@ -651,14 +644,16 @@ static void handle_v_packet(char *packet, const size_t plen)
if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, count) == 0)
gdb_putpacketz("OK");
else {
flash_mode = 0;
target_flash_complete(cur_target);
gdb_putpacketz("EFF");
}
} else if (!strcmp(packet, "vFlashDone")) {
/* Commit flash operations. */
gdb_putpacketz(target_flash_done(cur_target) ? "EFF" : "OK");
flash_mode = 0;
if (target_flash_complete(cur_target) == 0)
gdb_putpacketz("OK");
else
gdb_putpacketz("EFF");
} else if (!strcmp(packet, "vStopped")) {
if (gdb_needs_detach_notify) {

View File

@ -61,7 +61,7 @@ int target_mem_write(target *t, target_addr_t dest, const void *src, size_t len)
/* Flash memory access functions */
int target_flash_erase(target *t, target_addr_t addr, size_t len);
int target_flash_write(target *t, target_addr_t dest, const void *src, size_t len);
int target_flash_done(target *t);
int target_flash_complete(target *t);
/* Register access functions */
size_t target_regs_size(target *t);

View File

@ -577,7 +577,7 @@ found_targets:
map.data, map.size);
/* Buffered write cares for padding*/
if (!flashed)
flashed = target_flash_done(t);
flashed = target_flash_complete(t);
if (flashed) {
DEBUG_WARN("Flashing failed!\n");
res = -1;

View File

@ -49,8 +49,47 @@ target_flash_s *target_flash_for_addr(target *t, uint32_t addr)
return NULL;
}
static int target_enter_flash_mode(target *t)
{
if (t->flash_mode)
return 0;
int ret = 0;
if (t->enter_flash_mode)
ret = t->enter_flash_mode(t);
else
/* Reset target on flash command */
/* This saves us if we're interrupted in IRQ context */
target_reset(t);
if (ret == 0)
t->flash_mode = true;
return ret;
}
static int target_exit_flash_mode(target *t)
{
if (!t->flash_mode)
return 0;
int ret = 0;
if (t->exit_flash_mode)
ret = t->exit_flash_mode(t);
else
/* Reset target to known state when done flashing */
target_reset(t);
t->flash_mode = false;
return ret;
}
int target_flash_erase(target *t, target_addr_t addr, size_t len)
{
if (!t->flash_mode)
target_enter_flash_mode(t);
int ret = 0;
while (len) {
target_flash_s *f = target_flash_for_addr(t, addr);
@ -72,6 +111,9 @@ int target_flash_erase(target *t, target_addr_t addr, size_t len)
int target_flash_write(target *t, target_addr_t dest, const void *src, size_t len)
{
if (!t->flash_mode)
target_enter_flash_mode(t);
int ret = 0;
while (len) {
target_flash_s *f = target_flash_for_addr(t, dest);
@ -92,19 +134,19 @@ int target_flash_write(target *t, target_addr_t dest, const void *src, size_t le
return ret;
}
int target_flash_done(target *t)
int target_flash_complete(target *t)
{
if (!t->flash_mode)
return -1;
int ret = 0;
for (target_flash_s *f = t->flash; f; f = f->next) {
int tmp = target_flash_done_buffered(f);
if (tmp)
return tmp;
if (f->done) {
tmp = f->done(f);
if (tmp)
return tmp;
}
ret |= target_flash_done_buffered(f);
if (f->done)
ret |= f->done(f);
}
return 0;
target_exit_flash_mode(t);
return ret;
}
int target_flash_write_buffered(target_flash_s *f, target_addr_t dest, const void *src, size_t len)

View File

@ -115,6 +115,11 @@ struct target_s {
/* Recovery functions */
bool (*mass_erase)(target *t);
/* Flash functions */
int (*enter_flash_mode)(target *t);
int (*exit_flash_mode)(target *t);
bool flash_mode;
/* target-defined options */
unsigned target_options;