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>
This commit is contained in:
Tomas Vanek
2017-11-23 09:18:24 +01:00
parent f00d9bb1d7
commit eb8912ec38
12 changed files with 83 additions and 96 deletions

View File

@@ -308,7 +308,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
int arm_checksum_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *checksum);
int arm_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value);
void arm_set_cpsr(struct arm *arm, uint32_t cpsr);
struct reg *arm_reg_current(struct arm *arm, unsigned regnum);

View File

@@ -1663,7 +1663,7 @@ cleanup:
*
*/
int arm_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
{
struct working_area *check_algorithm;
struct reg_param reg_params[3];
@@ -1706,10 +1706,10 @@ int arm_blank_check_memory(struct target *target,
arm_algo.core_state = ARM_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, erased_value);
@@ -1724,7 +1724,7 @@ int arm_blank_check_memory(struct target *target,
10000, &arm_algo);
if (retval == ERROR_OK)
*blank = buf_get_u32(reg_params[2].value, 0, 32);
blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
@@ -1733,7 +1733,10 @@ int arm_blank_check_memory(struct target *target,
cleanup:
target_free_working_area(target, check_algorithm);
return retval;
if (retval != ERROR_OK)
return retval;
return 1; /* only one block has been checked */
}
static int arm_full_context(struct target *target)

View File

@@ -733,7 +733,7 @@ cleanup:
/** Checks whether a memory region is erased. */
int armv7m_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
{
struct working_area *erase_check_algorithm;
struct reg_param reg_params[3];
@@ -774,10 +774,10 @@ int armv7m_blank_check_memory(struct target *target,
armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[0].value, 0, 32, blocks->address);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
buf_set_u32(reg_params[1].value, 0, 32, blocks->size);
init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, erased_value);
@@ -793,7 +793,7 @@ int armv7m_blank_check_memory(struct target *target,
&armv7m_info);
if (retval == ERROR_OK)
*blank = buf_get_u32(reg_params[2].value, 0, 32);
blocks->result = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
@@ -802,7 +802,10 @@ int armv7m_blank_check_memory(struct target *target,
cleanup:
target_free_working_area(target, erase_check_algorithm);
return retval;
if (retval != ERROR_OK)
return retval;
return 1; /* only one block checked */
}
int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)

View File

@@ -225,7 +225,7 @@ int armv7m_restore_context(struct target *target);
int armv7m_checksum_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *checksum);
int armv7m_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value);
int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found);

View File

@@ -827,7 +827,8 @@ int mips32_checksum_memory(struct target *target, target_addr_t address,
/** Checks whether a memory region is erased. */
int mips32_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
struct target_memory_check_block *blocks, int num_blocks,
uint8_t erased_value)
{
struct working_area *erase_check_algorithm;
struct reg_param reg_params[3];
@@ -866,16 +867,16 @@ int mips32_blank_check_memory(struct target *target,
int retval = target_write_buffer(target, erase_check_algorithm->address,
sizeof(erase_check_code), erase_check_code_8);
if (retval != ERROR_OK)
return retval;
goto cleanup;
mips32_info.common_magic = MIPS32_COMMON_MAGIC;
mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, erased_value);
@@ -884,15 +885,19 @@ int mips32_blank_check_memory(struct target *target,
erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
if (retval == ERROR_OK)
*blank = buf_get_u32(reg_params[2].value, 0, 32);
blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
cleanup:
target_free_working_area(target, erase_check_algorithm);
return retval;
if (retval != ERROR_OK)
return retval;
return 1; /* only one block has been checked */
}
static int mips32_verify_pointer(struct command_context *cmd_ctx,

View File

@@ -428,6 +428,6 @@ int mips32_get_gdb_reg_list(struct target *target,
int mips32_checksum_memory(struct target *target, target_addr_t address,
uint32_t count, uint32_t *checksum);
int mips32_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value);
#endif /* OPENOCD_TARGET_MIPS32_H */

View File

@@ -1750,7 +1750,7 @@ static int stm8_examine(struct target *target)
/** Checks whether a memory region is erased. */
static int stm8_blank_check_memory(struct target *target,
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
{
struct working_area *erase_check_algorithm;
struct reg_param reg_params[2];
@@ -1778,10 +1778,10 @@ static int stm8_blank_check_memory(struct target *target,
stm8_info.common_magic = STM8_COMMON_MAGIC;
init_mem_param(&mem_params[0], 0x0, 3, PARAM_OUT);
buf_set_u32(mem_params[0].value, 0, 24, address);
buf_set_u32(mem_params[0].value, 0, 24, blocks[0].address);
init_mem_param(&mem_params[1], 0x3, 3, PARAM_OUT);
buf_set_u32(mem_params[1].value, 0, 24, count);
buf_set_u32(mem_params[1].value, 0, 24, blocks[0].size);
init_reg_param(&reg_params[0], "a", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[0].value, 0, 32, erased_value);
@@ -1795,7 +1795,7 @@ static int stm8_blank_check_memory(struct target *target,
10000, &stm8_info);
if (retval == ERROR_OK)
*blank = (*(reg_params[0].value) == 0xff);
blocks[0].result = (*(reg_params[0].value) == 0xff);
destroy_mem_param(&mem_params[0]);
destroy_mem_param(&mem_params[1]);
@@ -1803,7 +1803,10 @@ static int stm8_blank_check_memory(struct target *target,
target_free_working_area(target, erase_check_algorithm);
return retval;
if (retval != ERROR_OK)
return retval;
return 1; /* only one block has been checked */
}
static int stm8_checksum_memory(struct target *target, target_addr_t address,

View File

@@ -2251,21 +2251,19 @@ int target_checksum_memory(struct target *target, target_addr_t address, uint32_
return retval;
}
int target_blank_check_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* blank,
int target_blank_check_memory(struct target *target,
struct target_memory_check_block *blocks, int num_blocks,
uint8_t erased_value)
{
int retval;
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
}
if (target->type->blank_check_memory == 0)
if (target->type->blank_check_memory == NULL)
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
retval = target->type->blank_check_memory(target, address, size, blank, erased_value);
return retval;
return target->type->blank_check_memory(target, blocks, num_blocks, erased_value);
}
int target_read_u64(struct target *target, target_addr_t address, uint64_t *value)

View File

@@ -312,6 +312,12 @@ struct target_timer_callback {
struct target_timer_callback *next;
};
struct target_memory_check_block {
target_addr_t address;
uint32_t size;
uint32_t result;
};
int target_register_commands(struct command_context *cmd_ctx);
int target_examine(void);
@@ -585,7 +591,8 @@ int target_read_buffer(struct target *target,
int target_checksum_memory(struct target *target,
target_addr_t address, uint32_t size, uint32_t *crc);
int target_blank_check_memory(struct target *target,
target_addr_t address, uint32_t size, uint32_t *blank, uint8_t erased_value);
struct target_memory_check_block *blocks, int num_blocks,
uint8_t erased_value);
int target_wait_state(struct target *target, enum target_state state, int ms);
/**

View File

@@ -130,8 +130,9 @@ struct target_type {
int (*checksum_memory)(struct target *target, target_addr_t address,
uint32_t count, uint32_t *checksum);
int (*blank_check_memory)(struct target *target, target_addr_t address,
uint32_t count, uint32_t *blank, uint8_t erased_value);
int (*blank_check_memory)(struct target *target,
struct target_memory_check_block *blocks, int num_blocks,
uint8_t erased_value);
/*
* target break-/watchpoint control