aboutsummaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2017-11-23 09:18:24 +0100
committerTomas Vanek <vanekt@fbl.cz>2018-04-10 06:16:40 +0100
commiteb8912ec38c0fd6867d2b5a88b40549f791ce7bb (patch)
treed5cca832fad51f70f1202506dd6cecfedd561378 /src/flash
parentf00d9bb1d7e6d52e62e7cfc402fda96f3544d911 (diff)
downloadriscv-openocd-eb8912ec38c0fd6867d2b5a88b40549f791ce7bb.zip
riscv-openocd-eb8912ec38c0fd6867d2b5a88b40549f791ce7bb.tar.gz
riscv-openocd-eb8912ec38c0fd6867d2b5a88b40549f791ce7bb.tar.bz2
target, flash: prepare infrastructure for multi-block blank check
'flash erase_check' command runs a check algorithm on a target if possible. The algorithm is run repeatedly for each flash sector. Unfortunately every start and stop of the algorithm impose not negligible overhead. In practice it means checking is faster than plain read only for sectors of size approx 4 kByte or bigger. And checking sectors as short as 512 bytes runs approx 4 times slower than plain read. The patch changes API call target_blank_check_memory() and related to take an array of sectors (or arbitrary memory blocks). Changes in target-specific checking routines are kept minimal. They use only the first block from the array and process it by the unchanged algorithm. default_flash_blank_check() routine repeats target_blank_check_memory() until all blocks are checked, so it works with both multi-block and single-block based checkers. Change-Id: I0e6c60f2d71364c9c07c09416b04de9268807f5e Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: http://openocd.zylin.com/4297 Tested-by: jenkins Reviewed-by: Andreas Bolsch <hyphen0break@gmail.com>
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/at91sam7.c48
-rw-r--r--src/flash/nor/core.c43
2 files changed, 29 insertions, 62 deletions
diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c
index 03f771c..9de8293 100644
--- a/src/flash/nor/at91sam7.c
+++ b/src/flash/nor/at91sam7.c
@@ -639,14 +639,6 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
static int at91sam7_erase_check(struct flash_bank *bank)
{
- struct target *target = bank->target;
- uint16_t retval;
- uint32_t blank;
- uint16_t fast_check;
- uint8_t *buffer;
- uint16_t nSector;
- uint16_t nByte;
-
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
@@ -656,45 +648,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
at91sam7_read_clock_info(bank);
at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
- fast_check = 1;
- for (nSector = 0; nSector < bank->num_sectors; nSector++) {
- retval = target_blank_check_memory(target,
- bank->base + bank->sectors[nSector].offset,
- bank->sectors[nSector].size,
- &blank, bank->erased_value);
- if (retval != ERROR_OK) {
- fast_check = 0;
- break;
- }
- if (blank == 0xFF)
- bank->sectors[nSector].is_erased = 1;
- else
- bank->sectors[nSector].is_erased = 0;
- }
-
- if (fast_check)
- return ERROR_OK;
-
- LOG_USER("Running slow fallback erase check - add working memory");
-
- buffer = malloc(bank->sectors[0].size);
- for (nSector = 0; nSector < bank->num_sectors; nSector++) {
- bank->sectors[nSector].is_erased = 1;
- retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4,
- bank->sectors[nSector].size/4, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) {
- if (buffer[nByte] != 0xFF) {
- bank->sectors[nSector].is_erased = 0;
- break;
- }
- }
- }
- free(buffer);
-
- return ERROR_OK;
+ return default_flash_blank_check(bank);
}
static int at91sam7_protect_check(struct flash_bank *bank)
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index 636d50c..707dcff 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -339,36 +339,49 @@ int default_flash_blank_check(struct flash_bank *bank)
struct target *target = bank->target;
int i;
int retval;
- int fast_check = 0;
- uint32_t blank;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
+ struct target_memory_check_block *block_array;
+ block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
+ if (block_array == NULL)
+ return default_flash_mem_blank_check(bank);
+
for (i = 0; i < bank->num_sectors; i++) {
- uint32_t address = bank->base + bank->sectors[i].offset;
- uint32_t size = bank->sectors[i].size;
+ block_array[i].address = bank->base + bank->sectors[i].offset;
+ block_array[i].size = bank->sectors[i].size;
+ block_array[i].result = UINT32_MAX; /* erase state unknown */
+ }
- retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value);
- if (retval != ERROR_OK) {
- fast_check = 0;
+ bool fast_check = true;
+ for (i = 0; i < bank->num_sectors; ) {
+ retval = target_blank_check_memory(target,
+ block_array + i, bank->num_sectors - i,
+ bank->erased_value);
+ if (retval < 1) {
+ /* Run slow fallback if the first run gives no result
+ * otherwise use possibly incomplete results */
+ if (i == 0)
+ fast_check = false;
break;
}
- if (blank == bank->erased_value)
- bank->sectors[i].is_erased = 1;
- else
- bank->sectors[i].is_erased = 0;
- fast_check = 1;
+ i += retval; /* add number of blocks done this round */
}
- if (!fast_check) {
+ if (fast_check) {
+ for (i = 0; i < bank->num_sectors; i++)
+ bank->sectors[i].is_erased = block_array[i].result;
+ retval = ERROR_OK;
+ } else {
LOG_USER("Running slow fallback erase check - add working memory");
- return default_flash_mem_blank_check(bank);
+ retval = default_flash_mem_blank_check(bank);
}
+ free(block_array);
- return ERROR_OK;
+ return retval;
}
/* Manipulate given flash region, selecting the bank according to target