From: Andreas Fritiofson Date: Fri, 15 Jul 2011 20:20:34 +0000 (+0200) Subject: armv7m: implement async algorithm functions X-Git-Tag: v0.6.0-rc1~553 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=9d4c466c219039bd6a2ea03467cd3ee8be2a0e76 armv7m: implement async algorithm functions Split armv7m_run_algorithm into two pieces and use them to reimplement it. The arch_info parameter is used to keep context between the two calls, so both calls must refer to the same armv7m_algorithm struct. Ugly but works for a proof-of-concept. Signed-off-by: Andreas Fritiofson --- diff --git a/src/target/armv7m.c b/src/target/armv7m.c index fff5dd8406..39a89b9414 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -287,53 +287,42 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int return ERROR_OK; } -/* run to exit point. return error if exit point was not reached. */ -static int armv7m_run_and_wait(struct target *target, uint32_t entry_point, int timeout_ms, uint32_t exit_point, struct armv7m_common *armv7m) +/** Runs a Thumb algorithm in the target. */ +int armv7m_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t entry_point, uint32_t exit_point, + int timeout_ms, void *arch_info) { - uint32_t pc; int retval; - /* This code relies on the target specific resume() and poll()->debug_entry() - * sequence to write register values to the processor and the read them back */ - if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK) - { - return retval; - } - retval = target_wait_state(target, TARGET_HALTED, timeout_ms); - /* If the target fails to halt due to the breakpoint, force a halt */ - if (retval != ERROR_OK || target->state != TARGET_HALTED) - { - if ((retval = target_halt(target)) != ERROR_OK) - return retval; - if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK) - { - return retval; - } - return ERROR_TARGET_TIMEOUT; - } + retval = armv7m_start_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, exit_point, + arch_info); - armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc); - if (exit_point && (pc != exit_point)) - { - LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc); - return ERROR_TARGET_TIMEOUT; - } + if (retval == ERROR_OK) + retval = armv7m_wait_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, timeout_ms, + arch_info); - return ERROR_OK; + return retval; } -/** Runs a Thumb algorithm in the target. */ -int armv7m_run_algorithm(struct target *target, +/** Starts a Thumb algorithm in the target. */ +int armv7m_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, - int timeout_ms, void *arch_info) + void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); struct armv7m_algorithm *armv7m_algorithm_info = arch_info; enum armv7m_mode core_mode = armv7m->core_mode; int retval = ERROR_OK; - uint32_t context[ARMV7M_NUM_REGS]; /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint * at the exit point */ @@ -356,11 +345,12 @@ int armv7m_run_algorithm(struct target *target, { if (!armv7m->core_cache->reg_list[i].valid) armv7m->read_core_reg(target, i); - context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32); + armv7m_algorithm_info->context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32); } for (int i = 0; i < num_mem_params; i++) { + // TODO: Write only out params if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) return retval; } @@ -394,12 +384,52 @@ int armv7m_run_algorithm(struct target *target, armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1; } + armv7m_algorithm_info->core_mode = core_mode; - retval = armv7m_run_and_wait(target, entry_point, timeout_ms, exit_point, armv7m); + retval = target_resume(target, 0, entry_point, 1, 1); - if (retval != ERROR_OK) + return retval; +} + +/** Waits for an algorithm in the target. */ +int armv7m_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t exit_point, int timeout_ms, + void *arch_info) +{ + struct armv7m_common *armv7m = target_to_armv7m(target); + struct armv7m_algorithm *armv7m_algorithm_info = arch_info; + int retval = ERROR_OK; + uint32_t pc; + + /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + + if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { - return retval; + LOG_ERROR("current target isn't an ARMV7M target"); + return ERROR_TARGET_INVALID; + } + + retval = target_wait_state(target, TARGET_HALTED, timeout_ms); + /* If the target fails to halt due to the breakpoint, force a halt */ + if (retval != ERROR_OK || target->state != TARGET_HALTED) + { + if ((retval = target_halt(target)) != ERROR_OK) + return retval; + if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK) + { + return retval; + } + return ERROR_TARGET_TIMEOUT; + } + + armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc); + if (exit_point && (pc != exit_point)) + { + LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32 , pc, exit_point); + return ERROR_TARGET_TIMEOUT; } /* Read memory values to mem_params[] */ @@ -439,18 +469,18 @@ int armv7m_run_algorithm(struct target *target, { uint32_t regvalue; regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32); - if (regvalue != context[i]) + if (regvalue != armv7m_algorithm_info->context[i]) { LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32, - armv7m->core_cache->reg_list[i].name, context[i]); + armv7m->core_cache->reg_list[i].name, armv7m_algorithm_info->context[i]); buf_set_u32(armv7m->core_cache->reg_list[i].value, - 0, 32, context[i]); + 0, 32, armv7m_algorithm_info->context[i]); armv7m->core_cache->reg_list[i].valid = 1; armv7m->core_cache->reg_list[i].dirty = 1; } } - armv7m->core_mode = core_mode; + armv7m->core_mode = armv7m_algorithm_info->core_mode; return retval; } diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 8ef380088b..ca921468fc 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -142,6 +142,8 @@ struct armv7m_algorithm int common_magic; enum armv7m_mode core_mode; + + uint32_t context[ARMV7M_CONTROL + 1]; //ARMV7M_NUM_REGS }; struct armv7m_core_reg @@ -168,6 +170,18 @@ int armv7m_run_algorithm(struct target *target, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info); +int armv7m_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t entry_point, uint32_t exit_point, + void *arch_info); + +int armv7m_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t exit_point, int timeout_ms, + void *arch_info); + int armv7m_invalidate_core_regs(struct target *target); int armv7m_restore_context(struct target *target);