Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit 75dc9e4

Browse files
committed
target_flash: Implement blank check
* Reuse flash write buffer for block reads * Compare against erased value and skip to next sector on mismatch * Indicate progress via tc_printf() to gdb_if.c or BMDA stdout target_flash: Simplify inner loop of blank_check target_flash: Fix blank_check for pages smaller than writebufsize
1 parent 2ff786f commit 75dc9e4

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

src/include/target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ bool target_flash_erase(target_s *target, target_addr_t addr, size_t len);
7979
bool target_flash_write(target_s *target, target_addr_t dest, const void *src, size_t len);
8080
bool target_flash_complete(target_s *target);
8181
bool target_flash_mass_erase(target_s *target);
82+
bool target_flash_blank_check(target_s *target);
8283

8384
/* Register access functions */
8485
void target_regs_read(target_s *target, void *data);

src/target/target.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ target_s *target_list = NULL;
4545

4646
static bool target_cmd_mass_erase(target_s *target, int argc, const char **argv);
4747
static bool target_cmd_range_erase(target_s *target, int argc, const char **argv);
48+
static bool target_cmd_blank_check(target_s *target, int argc, const char **argv);
4849
static bool target_cmd_redirect_output(target_s *target, int argc, const char **argv);
4950

5051
const command_s target_cmd_list[] = {
5152
{"erase_mass", target_cmd_mass_erase, "Erase whole device Flash"},
5253
{"erase_range", target_cmd_range_erase, "Erase a range of memory on a device"},
54+
{"blank_check", target_cmd_blank_check, "Blank-check device Flash"},
5355
{"redirect_stdout", target_cmd_redirect_output, "Redirect semihosting output to aux USB serial"},
5456
{NULL, NULL, NULL},
5557
};
@@ -598,6 +600,16 @@ static bool target_cmd_range_erase(target_s *const target, const int argc, const
598600
return target_flash_erase(target, addr, length);
599601
}
600602

603+
static bool target_cmd_blank_check(target_s *const target, const int argc, const char **const argv)
604+
{
605+
(void)argc;
606+
(void)argv;
607+
gdb_out("Blank-checking device Flash: ");
608+
const bool result = target_flash_blank_check(target);
609+
gdb_out("done\n");
610+
return result;
611+
}
612+
601613
static bool target_cmd_redirect_output(target_s *target, int argc, const char **argv)
602614
{
603615
if (argc == 1) {

src/target/target_flash.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,60 @@ bool target_flash_complete(target_s *target)
391391
target_exit_flash_mode(target);
392392
return result;
393393
}
394+
395+
static bool flash_blank_check(target_flash_s *flash, target_addr_t src, size_t len, target_addr_t *mismatch)
396+
{
397+
bool result = true; /* Catch false returns with &= */
398+
target_s *target = flash->t;
399+
platform_timeout_s timeout;
400+
platform_timeout_set(&timeout, 500);
401+
402+
/* Pick smaller of: len = option bytes (8), writebufsize (1024), len = flash page (8192) */
403+
const size_t chunksize = flash->writebufsize < len ? flash->writebufsize : len;
404+
405+
for (size_t offset = 0U; offset < len; offset += chunksize) {
406+
/* Fetch chunk into sector buffer */
407+
target_mem32_read(target, flash->buf, src + offset, chunksize);
408+
409+
/* Compare bytewise with erased value */
410+
const uint8_t erased = flash->erased;
411+
for (size_t i = 0; i < chunksize; i++) {
412+
if (flash->buf[i] != erased) {
413+
*mismatch = src + i;
414+
return false;
415+
}
416+
}
417+
target_print_progress(&timeout);
418+
}
419+
return result;
420+
}
421+
422+
bool target_flash_blank_check(target_s *target)
423+
{
424+
if (!target->flash)
425+
return false;
426+
427+
bool result = true;
428+
target_addr_t mismatch = 0;
429+
430+
for (target_flash_s *flash = target->flash; flash; flash = flash->next) {
431+
if (!flash->buf && !flash_buffer_alloc(flash))
432+
return false;
433+
434+
const target_addr_t local_end = flash->start + flash->length;
435+
for (target_addr_t local_start = flash->start; local_start < local_end; local_start += flash->blocksize) {
436+
result = flash_blank_check(flash, local_start, flash->blocksize, &mismatch);
437+
if (!result)
438+
tc_printf(target, "Has data at 0x%08" PRIx32 "\n", mismatch);
439+
else
440+
tc_printf(target, "Blank 0x%08" PRIx32 "+%" PRIu32 "\n", local_start, (uint32_t)flash->blocksize);
441+
}
442+
/* Free the operation buffer */
443+
if (flash->buf) {
444+
free(flash->buf);
445+
flash->buf = NULL;
446+
}
447+
}
448+
449+
return result;
450+
}

0 commit comments

Comments
 (0)