X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7m.c;h=6c1732e92d5702faa02e92b7be46042ee3abc3c0;hp=1216a45fbe2564e3af9f5dd16dce8d43566e53d3;hb=3a550e5b5fe011e526b150a5d234b48e8e2aaad6;hpb=d33a81c549743e13633db9e8749f0e7cb0f7324b diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 1216a45fbe..6c1732e92d 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -58,6 +58,24 @@ static char *armv7m_exception_strings[] = "DebugMonitor", "RESERVED", "PendSV", "SysTick" }; +/* PSP is used in some thread modes */ +const int armv7m_psp_reg_map[17] = { + ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3, + ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7, + ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11, + ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC, + ARMV7M_xPSR, +}; + +/* MSP is used in handler and some thread modes */ +const int armv7m_msp_reg_map[17] = { + ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3, + ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7, + ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11, + ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC, + ARMV7M_xPSR, +}; + #ifdef ARMV7_GDB_HACKS uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0}; @@ -82,7 +100,7 @@ struct reg armv7m_gdb_dummy_cpsr_reg = */ static const struct { unsigned id; - char *name; + const char *name; unsigned bits; } armv7m_regs[] = { { ARMV7M_R0, "r0", 32 }, @@ -139,9 +157,6 @@ int armv7m_restore_context(struct target *target) } } - if (armv7m->post_restore_context) - armv7m->post_restore_context(target); - return ERROR_OK; } @@ -209,7 +224,7 @@ static int armv7m_read_core_reg(struct target *target, unsigned num) struct armv7m_common *armv7m = target_to_armv7m(target); if (num >= ARMV7M_NUM_REGS) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info; retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, ®_value); @@ -228,7 +243,7 @@ static int armv7m_write_core_reg(struct target *target, unsigned num) struct armv7m_common *armv7m = target_to_armv7m(target); if (num >= ARMV7M_NUM_REGS) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32); armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info; @@ -290,53 +305,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 (pc != exit_point) - { - LOG_DEBUG("failed algoritm 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 */ @@ -359,11 +363,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; } @@ -376,13 +381,13 @@ int armv7m_run_algorithm(struct target *target, if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } 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; + return ERROR_COMMAND_SYNTAX_ERROR; } // regvalue = buf_get_u32(reg_params[i].value, 0, 32); @@ -397,12 +402,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[] */ @@ -425,13 +470,13 @@ int armv7m_run_algorithm(struct target *target, if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } 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; + return ERROR_COMMAND_SYNTAX_ERROR; } buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); @@ -442,18 +487,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; } @@ -530,7 +575,7 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) return cache; } -int armv7m_setup_semihosting(struct target *target, int enable) +static int armv7m_setup_semihosting(struct target *target, int enable) { /* nothing todo for armv7m */ return ERROR_OK; @@ -565,6 +610,8 @@ int armv7m_checksum_memory(struct target *target, struct reg_param reg_params[2]; int retval; + /* see contib/loaders/checksum/armv7m_crc.s for src */ + static const uint16_t cortex_m3_crc_code[] = { 0x4602, /* mov r2, r0 */ 0xF04F, 0x30FF, /* mov r0, #0xffffffff */ @@ -597,17 +644,16 @@ int armv7m_checksum_memory(struct target *target, uint32_t i; - if (target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm) != ERROR_OK) - { - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } + retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm); + if (retval != ERROR_OK) + return retval; /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) - if ((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i])) != ERROR_OK) - { - return retval; - } + for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++) { + retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i]); + if (retval != ERROR_OK) + goto cleanup; + } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARMV7M_MODE_ANY; @@ -618,24 +664,24 @@ int armv7m_checksum_memory(struct target *target, buf_set_u32(reg_params[0].value, 0, 32, address); buf_set_u32(reg_params[1].value, 0, 32, count); - if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK) - { - LOG_ERROR("error executing cortex_m3 crc algorithm"); - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - target_free_working_area(target, crc_algorithm); - return retval; - } + int timeout = 20000 * (1 + (count / (1024 * 1024))); - *checksum = buf_get_u32(reg_params[0].value, 0, 32); + retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, + crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6), + timeout, &armv7m_info); + + if (retval == ERROR_OK) + *checksum = buf_get_u32(reg_params[0].value, 0, 32); + else + LOG_ERROR("error executing cortex_m3 crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); +cleanup: target_free_working_area(target, crc_algorithm); - return ERROR_OK; + return retval; } /** Checks whether a memory region is zeroed. */ @@ -680,17 +726,12 @@ int armv7m_blank_check_memory(struct target *target, init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, 0xff); - if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code)-2), 10000, &armv7m_info)) != ERROR_OK) - { - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - target_free_working_area(target, erase_check_algorithm); - return 0; - } + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, + erase_check_algorithm->address + (sizeof(erase_check_code) - 2), + 10000, &armv7m_info); - *blank = buf_get_u32(reg_params[2].value, 0, 32); + if (retval == ERROR_OK) + *blank = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -698,7 +739,7 @@ int armv7m_blank_check_memory(struct target *target, target_free_working_area(target, erase_check_algorithm); - return ERROR_OK; + return retval; } int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)