X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farmv4_5.c;h=d950af366403af53316e86f9cec2daf1a799288d;hb=f0c0256b1f05a04a58d857e9d865a0be0dd1680d;hp=c7b73676aff7ce906839d66508b86c7bb7004d9c;hpb=12c143d5948355b3b54c9c0decc779177b22d5d9;p=openocd.git diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index c7b73676af..d950af3664 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -217,7 +217,7 @@ enum arm_mode armv4_5_number_to_mode(int number) } } -const char *arm_state_strings[] = +static const char *arm_state_strings[] = { "ARM", "Thumb", "Jazelle", "ThumbEE", }; @@ -577,6 +577,7 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) cache->num_regs++; } + arm->pc = reg_list + 15; arm->cpsr = reg_list + ARMV4_5_CPSR; arm->core_cache = cache; return cache; @@ -598,8 +599,7 @@ int arm_arch_state(struct target *target) debug_reason_name(target), arm_mode_name(armv4_5->core_mode), buf_get_u32(armv4_5->cpsr->value, 0, 32), - buf_get_u32(armv4_5->core_cache->reg_list[15].value, - 0, 32), + buf_get_u32(armv4_5->pc->value, 0, 32), armv4_5->is_semihosting ? ", semihosting" : ""); return ERROR_OK; @@ -627,6 +627,12 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) return ERROR_FAIL; } + if (armv4_5->core_type != ARM_MODE_ANY) + { + command_print(CMD_CTX, "Microcontroller Profile not supported - use standard reg cmd"); + return ERROR_OK; + } + if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; @@ -706,6 +712,13 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) return ERROR_FAIL; } + if (armv4_5->core_type == ARM_MODE_THREAD) + { + /* armv7m not supported */ + command_print(CMD_CTX, "Unsupported Command"); + return ERROR_OK; + } + if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "arm") == 0) @@ -723,7 +736,7 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) return ERROR_OK; } -COMMAND_HANDLER(handle_armv4_5_disassemble_command) +COMMAND_HANDLER(handle_arm_disassemble_command) { int retval = ERROR_OK; struct target *target = get_current_target(CMD_CTX); @@ -737,6 +750,12 @@ COMMAND_HANDLER(handle_armv4_5_disassemble_command) return ERROR_FAIL; } + if (arm->core_type == ARM_MODE_THREAD) + { + /* armv7m is always thumb mode */ + thumb = 1; + } + switch (CMD_ARGC) { case 3: if (strcmp(CMD_ARGV[2], "thumb") != 0) @@ -801,11 +820,9 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct arm *arm; int retval; - context = Jim_GetAssocData(interp, "context"); - if (context == NULL) { - LOG_ERROR("%s: no command context", __func__); - return JIM_ERR; - } + context = current_command_context(interp); + assert( context != NULL); + target = get_current_target(context); if (target == NULL) { LOG_ERROR("%s: no current target", __func__); @@ -925,6 +942,49 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } +COMMAND_HANDLER(handle_arm_semihosting_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct arm *arm = target ? target_to_arm(target) : NULL; + + if (!is_arm(arm)) { + command_print(CMD_CTX, "current target isn't an ARM"); + return ERROR_FAIL; + } + + if (!arm->setup_semihosting) + { + command_print(CMD_CTX, "semihosting not supported for current target"); + } + + if (CMD_ARGC > 0) + { + int semihosting; + + COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); + + if (!target_was_examined(target)) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (arm->setup_semihosting(target, semihosting) != ERROR_OK) { + LOG_ERROR("Failed to Configure semihosting"); + return ERROR_FAIL; + } + + /* FIXME never let that "catch" be dropped! */ + arm->is_semihosting = semihosting; + } + + command_print(CMD_CTX, "semihosting is %s", + arm->is_semihosting + ? "enabled" : "disabled"); + + return ERROR_OK; +} + static const struct command_registration arm_exec_command_handlers[] = { { .name = "reg", @@ -941,7 +1001,7 @@ static const struct command_registration arm_exec_command_handlers[] = { }, { .name = "disassemble", - .handler = handle_armv4_5_disassemble_command, + .handler = handle_arm_disassemble_command, .mode = COMMAND_EXEC, .usage = "address [count ['thumb']]", .help = "disassemble instructions ", @@ -959,6 +1019,13 @@ static const struct command_registration arm_exec_command_handlers[] = { .help = "read coprocessor register", .usage = "cpnum op1 CRn op2 CRm", }, + { + "semihosting", + .handler = handle_arm_semihosting_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting operations", + }, COMMAND_REGISTRATION_DONE }; @@ -1018,11 +1085,10 @@ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit } /* fast exit: ARMv5+ code can use BKPT */ - if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value, - 0, 32) != exit_point) + if (exit_point && buf_get_u32(armv4_5->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(armv4_5->core_cache->reg_list[15].value, 0, 32)); + buf_get_u32(armv4_5->pc->value, 0, 32)); return ERROR_TARGET_TIMEOUT; } @@ -1220,16 +1286,17 @@ int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_ /** * Runs ARM code in the target to calculate a CRC32 checksum. * - * \todo On ARMv5+, rely on BKPT termination for reduced overhead. */ int arm_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct arm_algorithm armv4_5_info; + struct arm *armv4_5 = target_to_arm(target); struct reg_param reg_params[2]; int retval; uint32_t i; + uint32_t exit_var = 0; static const uint32_t arm_crc_code[] = { 0xE1A02000, /* mov r2, r0 */ @@ -1255,7 +1322,7 @@ int arm_checksum_memory(struct target *target, 0xE1540003, /* cmp r4, r3 */ 0x1AFFFFF1, /* bne nbyte */ /* end: */ - 0xEAFFFFFE, /* b end */ + 0xe1200070, /* bkpt #0 */ /* CRC32XOR: */ 0x04C11DB7 /* .word 0x04C11DB7 */ }; @@ -1287,9 +1354,13 @@ int arm_checksum_memory(struct target *target, /* 20 second timeout/megabyte */ int timeout = 20000 * (1 + (count / (1024 * 1024))); + /* armv4 must exit using a hardware breakpoint */ + if (armv4_5->is_armv4) + exit_var = crc_algorithm->address + sizeof(arm_crc_code) - 8; + retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, - crc_algorithm->address + sizeof(arm_crc_code) - 8, + exit_var, timeout, &armv4_5_info); if (retval != ERROR_OK) { LOG_ERROR("error executing ARM crc algorithm"); @@ -1314,7 +1385,6 @@ int arm_checksum_memory(struct target *target, * all ones. NOR flash which has been erased, and thus may be written, * holds all ones. * - * \todo On ARMv5+, rely on BKPT termination for reduced overhead. */ int arm_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *blank) @@ -1322,8 +1392,10 @@ int arm_blank_check_memory(struct target *target, struct working_area *check_algorithm; struct reg_param reg_params[3]; struct arm_algorithm armv4_5_info; + struct arm *armv4_5 = target_to_arm(target); int retval; uint32_t i; + uint32_t exit_var = 0; static const uint32_t check_code[] = { /* loop: */ @@ -1332,7 +1404,7 @@ int arm_blank_check_memory(struct target *target, 0xe2511001, /* subs r1, r1, #1 */ 0x1afffffb, /* bne loop */ /* end: */ - 0xeafffffe /* b end */ + 0xe1200070, /* bkpt #0 */ }; /* make sure we have a working area */ @@ -1364,9 +1436,13 @@ int arm_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); + /* armv4 must exit using a hardware breakpoint */ + if (armv4_5->is_armv4) + exit_var = check_algorithm->address + sizeof(check_code) - 4; + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, check_algorithm->address, - check_algorithm->address + sizeof(check_code) - 4, + exit_var, 10000, &armv4_5_info); if (retval != ERROR_OK) { destroy_reg_param(®_params[0]); @@ -1426,10 +1502,12 @@ int arm_init_arch_info(struct target *target, struct arm *armv4_5) armv4_5->target = target; armv4_5->common_magic = ARM_COMMON_MAGIC; - arm_set_cpsr(armv4_5, ARM_MODE_USR); /* core_type may be overridden by subtype logic */ - armv4_5->core_type = ARM_MODE_ANY; + if (armv4_5->core_type != ARM_MODE_THREAD) { + armv4_5->core_type = ARM_MODE_ANY; + arm_set_cpsr(armv4_5, ARM_MODE_USR); + } /* default full_context() has no core-specific optimizations */ if (!armv4_5->full_context && armv4_5->read_core_reg)