From e72edc05799604944e1dff1efaa7573ea9e7ab1a Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 22 Aug 2022 11:21:41 +0100 Subject: [PATCH] target_flash: abstract target flash mode/flash preparation --- src/gdb_main.c | 17 ++++------ src/include/target.h | 2 +- src/platforms/hosted/cli.c | 2 +- src/target/target_flash.c | 62 ++++++++++++++++++++++++++++++------ src/target/target_internal.h | 5 +++ 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index db00efd..30914ad 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -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) { diff --git a/src/include/target.h b/src/include/target.h index 2a07016..2127d71 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -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); diff --git a/src/platforms/hosted/cli.c b/src/platforms/hosted/cli.c index 1e4d6f8..86862a5 100644 --- a/src/platforms/hosted/cli.c +++ b/src/platforms/hosted/cli.c @@ -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; diff --git a/src/target/target_flash.c b/src/target/target_flash.c index 20a96ae..df71b69 100644 --- a/src/target/target_flash.c +++ b/src/target/target_flash.c @@ -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) diff --git a/src/target/target_internal.h b/src/target/target_internal.h index c028d45..cacf0aa 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -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;