Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Flash blank check #1971

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/include/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ bool target_flash_erase(target_s *target, target_addr_t addr, size_t len);
bool target_flash_write(target_s *target, target_addr_t dest, const void *src, size_t len);
bool target_flash_complete(target_s *target);
bool target_flash_mass_erase(target_s *target);
bool target_flash_blank_check(target_s *target);

/* Register access functions */
size_t target_regs_size(target_s *target);
Expand Down
12 changes: 12 additions & 0 deletions src/target/target.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ target_s *target_list = NULL;

static bool target_cmd_mass_erase(target_s *target, int argc, const char **argv);
static bool target_cmd_range_erase(target_s *target, int argc, const char **argv);
static bool target_cmd_blank_check(target_s *target, int argc, const char **argv);
static bool target_cmd_redirect_output(target_s *target, int argc, const char **argv);

const command_s target_cmd_list[] = {
{"erase_mass", target_cmd_mass_erase, "Erase whole device Flash"},
{"erase_range", target_cmd_range_erase, "Erase a range of memory on a device"},
{"blank_check", target_cmd_blank_check, "Blank-check device Flash"},
{"redirect_stdout", target_cmd_redirect_output, "Redirect semihosting output to aux USB serial"},
{NULL, NULL, NULL},
};
Expand Down Expand Up @@ -516,6 +518,16 @@ static bool target_cmd_range_erase(target_s *const target, const int argc, const
return target_flash_erase(target, addr, length);
}

static bool target_cmd_blank_check(target_s *const target, const int argc, const char **const argv)
{
(void)argc;
(void)argv;
gdb_out("Blank-checking device Flash: ");
const bool result = target_flash_blank_check(target);
gdb_out("done\n");
return result;
}

static bool target_cmd_redirect_output(target_s *target, int argc, const char **argv)
{
if (argc == 1) {
Expand Down
54 changes: 54 additions & 0 deletions src/target/target_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,57 @@ bool target_flash_complete(target_s *target)
target_exit_flash_mode(target);
return result;
}

static bool flash_blank_check(target_flash_s *flash, target_addr_t src, size_t len, target_addr_t *mismatch)
{
bool result = true; /* Catch false returns with &= */
target_s *target = flash->t;
platform_timeout_s timeout;
platform_timeout_set(&timeout, 500);

for (size_t offset = 0U; offset < len; offset += flash->writebufsize) {
/* Fetch chunk into sector buffer */
target_mem32_read(target, flash->buf, src + offset, flash->writebufsize);

/* Compare bytewise with erased value */
const uint8_t erased = flash->erased;
for (size_t i = 0; i < flash->writebufsize; i++) {
if (flash->buf[i] != erased) {
*mismatch = src + i;
return false;
}
}
target_print_progress(&timeout);
}
return result;
}

bool target_flash_blank_check(target_s *target)
{
if (!target->flash)
return false;

bool result = true;
target_addr_t mismatch = 0;

for (target_flash_s *flash = target->flash; flash; flash = flash->next) {
if (!flash->buf && !flash_buffer_alloc(flash))
return false;

const target_addr_t local_end = flash->start + flash->length;
for (target_addr_t local_start = flash->start; local_start < local_end; local_start += flash->blocksize) {
result = flash_blank_check(flash, local_start, flash->blocksize, &mismatch);
if (!result)
tc_printf(target, "Has data at 0x%08" PRIx32 "\n", mismatch);
else
tc_printf(target, "Blank 0x%08" PRIx32 "+%" PRIu32 "\n", local_start, (uint32_t)flash->blocksize);
}
/* Free the operation buffer */
if (flash->buf) {
free(flash->buf);
flash->buf = NULL;
}
}

return result;
}
Loading