/* wait for execution to complete and check exit point */ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval; struct arm *arm = target_to_arm(target); retval = target_wait_state(target, TARGET_HALTED, timeout_ms); if (retval != ERROR_OK) return retval; if (target->state != TARGET_HALTED) { retval = target_halt(target); if (retval != ERROR_OK) return retval; retval = target_wait_state(target, TARGET_HALTED, 500); if (retval != ERROR_OK) return retval; return ERROR_TARGET_TIMEOUT; } /* fast exit: ARMv5+ code can use BKPT */ if (exit_point && buf_get_u32(arm->pc->value, 0, 32) != exit_point) { LOG_WARNING( "target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "", buf_get_u32(arm->pc->value, 0, 32)); return ERROR_TARGET_TIMEOUT; } return ERROR_OK; }
/* run to exit point. return error if exit point was not reached. */ static int mips32_run_and_wait(struct target *target, uint32_t entry_point, int timeout_ms, uint32_t exit_point, struct mips32_common *mips32) { 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, 0, 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; } pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32); if (exit_point && (pc != exit_point)) { LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc); return ERROR_TARGET_TIMEOUT; } 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) { 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; } armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc); if (exit_point && (pc != exit_point)) { LOG_DEBUG("failed algoritm halted at 0x%" PRIx32 " ", pc); return ERROR_TARGET_TIMEOUT; } return ERROR_OK; }
/** 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) { 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[] */ for (int i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) { return retval; } } /* Copy core register values to reg_params[] */ for (int i = 0; i < num_reg_params; i++) { if (reg_params[i].direction != PARAM_OUT) { struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_INVALID_ARGUMENTS; } if (reg->size != reg_params[i].size) { LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_INVALID_ARGUMENTS; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); } } for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--) { uint32_t regvalue; regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32); 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, armv7m_algorithm_info->context[i]); buf_set_u32(armv7m->core_cache->reg_list[i].value, 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 = armv7m_algorithm_info->core_mode; return retval; }