X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7m.c;h=a3c81dcee9d0f8d0e97389f1597823313b4b4044;hp=0a34adf21c50feb247f0e95c38c74bfacd50979a;hb=17b57f886593d92125fac6b709533efd7abfe39e;hpb=e6b27756da1912e9ed5c48d18d934784fa24a019 diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 0a34adf21c..a3c81dcee9 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -135,6 +135,7 @@ int armv7m_restore_context(struct target *target) { int i; struct armv7m_common *armv7m = target_to_armv7m(target); + struct reg_cache *cache = armv7m->arm.core_cache; LOG_DEBUG(" "); @@ -142,8 +143,10 @@ int armv7m_restore_context(struct target *target) armv7m->pre_restore_context(target); for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) { - if (armv7m->arm.core_cache->reg_list[i].dirty) - armv7m->write_core_reg(target, i); + if (cache->reg_list[i].dirty) { + uint32_t value = buf_get_u32(cache->reg_list[i].value, 0, 32); + armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, value); + } } return ERROR_OK; @@ -175,12 +178,12 @@ static int armv7m_get_core_reg(struct reg *reg) int retval; struct arm_reg *armv7m_reg = reg->arch_info; struct target *target = armv7m_reg->target; - struct armv7m_common *armv7m = target_to_armv7m(target); + struct arm *arm = target_to_arm(target); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; - retval = armv7m->read_core_reg(target, armv7m_reg->num); + retval = arm->read_core_reg(target, reg, armv7m_reg->num, arm->core_mode); return retval; } @@ -201,20 +204,20 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_OK; } -static int armv7m_read_core_reg(struct target *target, unsigned num) +static int armv7m_read_core_reg(struct target *target, struct reg *r, + int num, enum arm_mode mode) { uint32_t reg_value; int retval; struct arm_reg *armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); - if (num >= ARMV7M_NUM_REGS) - return ERROR_COMMAND_SYNTAX_ERROR; + assert(num < (int)armv7m->arm.core_cache->num_regs); armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; retval = armv7m->load_core_reg_u32(target, - armv7m_core_reg->num, - ®_value); + armv7m_core_reg->num, ®_value); + buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); armv7m->arm.core_cache->reg_list[num].valid = 1; armv7m->arm.core_cache->reg_list[num].dirty = 0; @@ -222,15 +225,15 @@ static int armv7m_read_core_reg(struct target *target, unsigned num) return retval; } -static int armv7m_write_core_reg(struct target *target, unsigned num) +static int armv7m_write_core_reg(struct target *target, struct reg *r, + int num, enum arm_mode mode, uint32_t value) { int retval; uint32_t reg_value; struct arm_reg *armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); - if (num >= ARMV7M_NUM_REGS) - return ERROR_COMMAND_SYNTAX_ERROR; + assert(num < (int)armv7m->arm.core_cache->num_regs); reg_value = buf_get_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32); armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; @@ -242,6 +245,7 @@ static int armv7m_write_core_reg(struct target *target, unsigned num) armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid; return ERROR_JTAG_DEVICE_ERROR; } + LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value); armv7m->arm.core_cache->reg_list[num].valid = 1; armv7m->arm.core_cache->reg_list[num].dirty = 0; @@ -285,7 +289,7 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int * if it does not support this arch */ *((char *)armv7m->arm.pc->value) |= 1; #else - (*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR]; + (*reg_list)[25] = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR]; #endif return ERROR_OK; @@ -344,8 +348,7 @@ int armv7m_start_algorithm(struct target *target, /* refresh core register cache * Not needed if core register cache is always consistent with target process state */ for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) { - if (!armv7m->arm.core_cache->reg_list[i].valid) - armv7m->read_core_reg(target, i); + armv7m_algorithm_info->context[i] = buf_get_u32( armv7m->arm.core_cache->reg_list[i].value, 0, @@ -381,13 +384,23 @@ int armv7m_start_algorithm(struct target *target, armv7m_set_core_reg(reg, reg_params[i].value); } - if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY) { + if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY && + armv7m_algorithm_info->core_mode != core_mode) { + + /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */ + if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) { + armv7m_algorithm_info->core_mode = ARM_MODE_THREAD; + LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead"); + } + LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1; } + + /* save previous core mode */ armv7m_algorithm_info->core_mode = core_mode; retval = target_resume(target, 0, entry_point, 1, 1); @@ -483,6 +496,15 @@ int armv7m_wait_algorithm(struct target *target, } } + /* restore previous core mode */ + if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) { + LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); + buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, + 0, 1, armv7m_algorithm_info->core_mode); + armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; + armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1; + } + armv7m->arm.core_mode = armv7m_algorithm_info->core_mode; return retval; @@ -578,11 +600,8 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) arm->arch_info = armv7m; arm->setup_semihosting = armv7m_setup_semihosting; - /* FIXME remove v7m-specific r/w core_reg functions; - * use the generic ARM core support.. - */ - armv7m->read_core_reg = armv7m_read_core_reg; - armv7m->write_core_reg = armv7m_write_core_reg; + arm->read_core_reg = armv7m_read_core_reg; + arm->write_core_reg = armv7m_write_core_reg; return arm_init_arch_info(target, arm); } @@ -642,7 +661,7 @@ int armv7m_checksum_memory(struct target *target, goto cleanup; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARM_MODE_ANY; + armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); @@ -702,7 +721,7 @@ int armv7m_blank_check_memory(struct target *target, return retval; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARM_MODE_ANY; + armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address);