X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv4_5.c;h=53a6b2229014884813ffb6dccba41d0ede551d78;hp=a6fadaa0b969b6e33599bd8d24612745fde7a6f6;hb=5fbf4d4cc3f67ec8b2fb3d8a789117583a84e1a1;hpb=f18ca510b3430a515f28f19ea6c6731a40022fb6 diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index a6fadaa0b9..53a6b22290 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -8,6 +8,9 @@ * Copyright (C) 2008 by Oyvind Harboe * * oyvind.harboe@zylin.com * * * + * Copyright (C) 2018 by Liviu Ionescu * + * * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -34,6 +37,7 @@ #include #include "algorithm.h" #include "register.h" +#include "semihosting_common.h" /* offsets into armv4_5 core register cache */ enum { @@ -430,8 +434,8 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) */ if (arm->cpsr) { buf_set_u32(arm->cpsr->value, 0, 32, cpsr); - arm->cpsr->valid = 1; - arm->cpsr->dirty = 0; + arm->cpsr->valid = true; + arm->cpsr->dirty = false; } arm->core_mode = mode; @@ -522,7 +526,7 @@ static struct reg_feature arm_gdb_dummy_fp_features = { struct reg arm_gdb_dummy_fp_reg = { .name = "GDB dummy FPA register", .value = (uint8_t *) arm_gdb_dummy_fp_value, - .valid = 1, + .valid = true, .size = 96, .exist = false, .number = 16, @@ -539,7 +543,7 @@ static const uint8_t arm_gdb_dummy_fps_value[4]; struct reg arm_gdb_dummy_fps_reg = { .name = "GDB dummy FPA status register", .value = (uint8_t *) arm_gdb_dummy_fps_value, - .valid = 1, + .valid = true, .size = 32, .exist = false, .number = 24, @@ -569,8 +573,8 @@ static int armv4_5_get_core_reg(struct reg *reg) retval = reg_arch_info->arm->read_core_reg(target, reg, reg_arch_info->num, reg_arch_info->mode); if (retval == ERROR_OK) { - reg->valid = 1; - reg->dirty = 0; + reg->valid = true; + reg->dirty = false; } return retval; @@ -615,9 +619,9 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) value = buf_get_u32(buf + 4, 0, 32); buf_set_u32(reg->value + 4, 0, 32, value); } - reg->valid = 1; + reg->valid = true; } - reg->dirty = 1; + reg->dirty = true; return ERROR_OK; } @@ -748,7 +752,7 @@ int arm_arch_state(struct target *target) } /* avoid filling log waiting for fileio reply */ - if (arm->semihosting_hit_fileio) + if (target->semihosting && target->semihosting->hit_fileio) return ERROR_OK; LOG_USER("target halted in %s state due to %s, current mode: %s\n" @@ -758,8 +762,8 @@ int arm_arch_state(struct target *target) arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), - arm->is_semihosting ? ", semihosting" : "", - arm->is_semihosting_fileio ? " fileio" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : "", + (target->semihosting && target->semihosting->is_fileio) ? " fileio" : ""); return ERROR_OK; } @@ -774,17 +778,17 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) struct reg *regs; if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); + command_print(CMD, "current target isn't an ARM"); return ERROR_FAIL; } if (target->state != TARGET_HALTED) { - command_print(CMD_CTX, "error: target must be halted for register accesses"); + command_print(CMD, "error: target must be halted for register accesses"); return ERROR_FAIL; } if (arm->core_type != ARM_MODE_ANY) { - command_print(CMD_CTX, + command_print(CMD, "Microcontroller Profile not supported - use standard reg cmd"); return ERROR_OK; } @@ -795,7 +799,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) } if (!arm->full_context) { - command_print(CMD_CTX, "error: target doesn't support %s", + command_print(CMD, "error: target doesn't support %s", CMD_NAME); return ERROR_FAIL; } @@ -824,7 +828,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) shadow = "shadow "; break; } - command_print(CMD_CTX, "%s%s mode %sregisters", + command_print(CMD, "%s%s mode %sregisters", sep, name, shadow); /* display N rows of up to 4 registers each */ @@ -851,7 +855,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) "%8s: %8.8" PRIx32 " ", reg->name, value); } - command_print(CMD_CTX, "%s", output); + command_print(CMD, "%s", output); } } @@ -864,13 +868,13 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) struct arm *arm = target_to_arm(target); if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); + command_print(CMD, "current target isn't an ARM"); return ERROR_FAIL; } if (arm->core_type == ARM_MODE_THREAD) { /* armv7m not supported */ - command_print(CMD_CTX, "Unsupported Command"); + command_print(CMD, "Unsupported Command"); return ERROR_OK; } @@ -881,7 +885,7 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) arm->core_state = ARM_STATE_THUMB; } - command_print(CMD_CTX, "core state: %s", arm_state_strings[arm->core_state]); + command_print(CMD, "core state: %s", arm_state_strings[arm->core_state]); return ERROR_OK; } @@ -902,7 +906,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) int thumb = 0; if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); + command_print(CMD, "current target isn't an ARM"); return ERROR_FAIL; } @@ -924,7 +928,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); if (address & 0x01) { if (!thumb) { - command_print(CMD_CTX, "Disassemble as Thumb"); + command_print(CMD, "Disassemble as Thumb"); thumb = 1; } address &= ~1; @@ -959,7 +963,7 @@ usage: if (retval != ERROR_OK) break; } - command_print(CMD_CTX, "%s", cur_instruction.text); + command_print(CMD, "%s", cur_instruction.text); address += cur_instruction.instruction_size; } @@ -1094,119 +1098,10 @@ 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); - - if (target == NULL) { - LOG_ERROR("No target selected"); - return ERROR_FAIL; - } - - struct arm *arm = target_to_arm(target); - - 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"); - return ERROR_FAIL; - } - - 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; -} - -COMMAND_HANDLER(handle_arm_semihosting_fileio_command) -{ - struct target *target = get_current_target(CMD_CTX); - - if (target == NULL) { - LOG_ERROR("No target selected"); - return ERROR_FAIL; - } - - struct arm *arm = target_to_arm(target); - - if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); - return ERROR_FAIL; - } - - if (!arm->is_semihosting) { - command_print(CMD_CTX, "semihosting is not enabled"); - return ERROR_FAIL; - } - - if (CMD_ARGC > 0) - COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm->is_semihosting_fileio); - - command_print(CMD_CTX, "semihosting fileio is %s", - arm->is_semihosting_fileio - ? "enabled" : "disabled"); - - return ERROR_OK; -} - -COMMAND_HANDLER(handle_arm_semihosting_cmdline) -{ - struct target *target = get_current_target(CMD_CTX); - unsigned int i; - - if (target == NULL) { - LOG_ERROR("No target selected"); - return ERROR_FAIL; - } - - struct arm *arm = target_to_arm(target); - - 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"); - return ERROR_FAIL; - } - - free(arm->semihosting_cmdline); - arm->semihosting_cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL; - - for (i = 1; i < CMD_ARGC; i++) { - char *cmdline = alloc_printf("%s %s", arm->semihosting_cmdline, CMD_ARGV[i]); - if (cmdline == NULL) - break; - free(arm->semihosting_cmdline); - arm->semihosting_cmdline = cmdline; - } - - return ERROR_OK; -} +extern __COMMAND_HANDLER(handle_common_semihosting_command); +extern __COMMAND_HANDLER(handle_common_semihosting_fileio_command); +extern __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command); +extern __COMMAND_HANDLER(handle_common_semihosting_cmdline); static const struct command_registration arm_exec_command_handlers[] = { { @@ -1239,32 +1134,39 @@ static const struct command_registration arm_exec_command_handlers[] = { }, { .name = "mrc", + .mode = COMMAND_EXEC, .jim_handler = &jim_mcrmrc, .help = "read coprocessor register", .usage = "cpnum op1 CRn CRm op2", }, { - "semihosting", - .handler = handle_arm_semihosting_command, + .name = "semihosting", + .handler = handle_common_semihosting_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting operations", }, { - "semihosting_cmdline", - .handler = handle_arm_semihosting_cmdline, + .name = "semihosting_cmdline", + .handler = handle_common_semihosting_cmdline, .mode = COMMAND_EXEC, .usage = "arguments", .help = "command line arguments to be passed to program", }, { - "semihosting_fileio", - .handler = handle_arm_semihosting_fileio_command, + .name = "semihosting_fileio", + .handler = handle_common_semihosting_fileio_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting fileio operations", }, - + { + .name = "semihosting_resexit", + .handler = handle_common_semihosting_resumable_exit_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting resumable exit", + }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm_command_handlers[] = { @@ -1278,6 +1180,20 @@ const struct command_registration arm_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +/* + * gdb for arm targets (e.g. arm-none-eabi-gdb) supports several variants + * of arm architecture. You can list them using the autocompletion of gdb + * command prompt by typing "set architecture " and then press TAB key. + * The default, selected automatically, is "arm". + * Let's use the default value, here, to make gdb-multiarch behave in the + * same way as a gdb for arm. This can be changed later on. User can still + * set the specific architecture variant with the gdb command. + */ +const char *arm_get_gdb_arch(struct target *target) +{ + return "arm"; +} + int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) @@ -1439,6 +1355,8 @@ int armv4_5_run_algorithm_inner(struct target *target, cpsr = buf_get_u32(arm->cpsr->value, 0, 32); for (i = 0; i < num_mem_params; i++) { + if (mem_params[i].direction == PARAM_IN) + continue; retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); if (retval != ERROR_OK) @@ -1446,6 +1364,9 @@ int armv4_5_run_algorithm_inner(struct target *target, } for (i = 0; i < num_reg_params; i++) { + if (reg_params[i].direction == PARAM_IN) + continue; + struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0); if (!reg) { LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); @@ -1478,8 +1399,8 @@ int armv4_5_run_algorithm_inner(struct target *target, arm_algorithm_info->core_mode); buf_set_u32(arm->cpsr->value, 0, 5, arm_algorithm_info->core_mode); - arm->cpsr->dirty = 1; - arm->cpsr->valid = 1; + arm->cpsr->dirty = true; + arm->cpsr->valid = true; } /* terminate using a hardware or (ARMv5+) software breakpoint */ @@ -1549,14 +1470,14 @@ int armv4_5_run_algorithm_inner(struct target *target, buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).value, 0, 32, context[i]); ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, - i).valid = 1; + i).valid = true; ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, - i).dirty = 1; + i).dirty = true; } } arm_set_cpsr(arm, cpsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; arm->core_state = core_state; @@ -1663,7 +1584,7 @@ cleanup: * */ int arm_blank_check_memory(struct target *target, - target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) + struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value) { struct working_area *check_algorithm; struct reg_param reg_params[3]; @@ -1706,10 +1627,10 @@ int arm_blank_check_memory(struct target *target, arm_algo.core_state = ARM_STATE_ARM; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - buf_set_u32(reg_params[1].value, 0, 32, count); + buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, erased_value); @@ -1724,7 +1645,7 @@ int arm_blank_check_memory(struct target *target, 10000, &arm_algo); if (retval == ERROR_OK) - *blank = buf_get_u32(reg_params[2].value, 0, 32); + blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -1733,7 +1654,10 @@ int arm_blank_check_memory(struct target *target, cleanup: target_free_working_area(target, check_algorithm); - return retval; + if (retval != ERROR_OK) + return retval; + + return 1; /* only one block has been checked */ } static int arm_full_context(struct target *target)