Skip to content

Commit 196dafc

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
1 parent a1cb6d9 commit 196dafc

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

src/include/target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ bool target_mem_access_needs_halt(target_s *target);
7070
bool target_flash_erase(target_s *target, target_addr_t addr, size_t len);
7171
bool target_flash_write(target_s *target, target_addr_t dest, const void *src, size_t len);
7272
bool target_flash_complete(target_s *target);
73+
bool target_flash_blank_check(target_s *target);
7374

7475
/* Register access functions */
7576
size_t target_regs_size(target_s *target);

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
};
@@ -510,6 +512,16 @@ static bool target_cmd_range_erase(target_s *const target, const int argc, const
510512
return target_flash_erase(target, addr, length);
511513
}
512514

515+
static bool target_cmd_blank_check(target_s *const target, const int argc, const char **const argv)
516+
{
517+
(void)argc;
518+
(void)argv;
519+
gdb_out("Blank-checking device Flash: ");
520+
const bool result = target_flash_blank_check(target);
521+
gdb_out("done\n");
522+
return result;
523+
}
524+
513525
static bool target_cmd_redirect_output(target_s *target, int argc, const char **argv)
514526
{
515527
if (argc == 1) {

src/target/target_flash.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,61 @@ bool target_flash_complete(target_s *target)
312312
target_exit_flash_mode(target);
313313
return result;
314314
}
315+
316+
static bool flash_blank_check(target_flash_s *flash, target_addr_t src, size_t len, target_addr_t *mismatch)
317+
{
318+
bool result = true; /* Catch false returns with &= */
319+
target_s *target = flash->t;
320+
platform_timeout_s timeout;
321+
platform_timeout_set(&timeout, 500);
322+
323+
while (len) {
324+
const size_t offset = src % flash->writebufsize;
325+
const size_t local_len = MIN(flash->writebufsize - offset, len);
326+
/* Fetch chunk into sector buffer */
327+
target_mem32_read(target, flash->buf, src, local_len);
328+
329+
/* Compare bytewise with erased value */
330+
const uint8_t erased = flash->erased;
331+
for (size_t i = 0; i < local_len; i++) {
332+
if (flash->buf[i] != erased) {
333+
*mismatch = src + i;
334+
return false;
335+
}
336+
}
337+
src += local_len;
338+
len -= local_len;
339+
target_print_progress(&timeout);
340+
}
341+
return result;
342+
}
343+
344+
bool target_flash_blank_check(target_s *target)
345+
{
346+
if (!target->flash)
347+
return false;
348+
349+
bool result = true;
350+
target_addr_t mismatch = 0;
351+
352+
for (target_flash_s *flash = target->flash; flash; flash = flash->next) {
353+
if (!flash->buf && !flash_buffer_alloc(flash))
354+
return false;
355+
356+
const target_addr_t local_end = flash->start + flash->length;
357+
for (target_addr_t local_start = flash->start; local_start < local_end; local_start += flash->blocksize) {
358+
result = flash_blank_check(flash, local_start, flash->blocksize, &mismatch);
359+
if (!result)
360+
tc_printf(target, "Has data at 0x%08" PRIx32 "\n", mismatch);
361+
else
362+
tc_printf(target, "Blank 0x%08" PRIx32 "+%" PRIu32 "\n", local_start, (uint32_t)flash->blocksize);
363+
}
364+
/* Free the operation buffer */
365+
if (flash->buf) {
366+
free(flash->buf);
367+
flash->buf = NULL;
368+
}
369+
}
370+
371+
return result;
372+
}

0 commit comments

Comments
 (0)