cmd: add missing usage vars
[fw/openocd] / src / target / armv4_5.c
index 6941c1619a8a60f31e6b6b971513b61948252f0f..3e3fea03ccc56d867c885e0d401c0fd90c411975 100644 (file)
@@ -27,6 +27,7 @@
 #include "config.h"
 #endif
 
+#include "arm.h"
 #include "armv4_5.h"
 #include "arm_jtag.h"
 #include "breakpoints.h"
@@ -216,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",
 };
@@ -533,7 +534,7 @@ static const struct reg_arch_type arm_reg_type = {
        .set = armv4_5_set_core_reg,
 };
 
-struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
+struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
 {
        int num_regs = ARRAY_SIZE(arm_core_regs);
        struct reg_cache *cache = malloc(sizeof(struct reg_cache));
@@ -557,7 +558,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
        {
                /* Skip registers this core doesn't expose */
                if (arm_core_regs[i].mode == ARM_MODE_MON
-                               && armv4_5_common->core_type != ARM_MODE_MON)
+                               && arm->core_type != ARM_MODE_MON)
                        continue;
 
                /* REVISIT handle Cortex-M, which only shadows R13/SP */
@@ -565,7 +566,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
                arch_info[i].num = arm_core_regs[i].cookie;
                arch_info[i].mode = arm_core_regs[i].mode;
                arch_info[i].target = target;
-               arch_info[i].armv4_5_common = armv4_5_common;
+               arch_info[i].armv4_5_common = arm;
 
                reg_list[i].name = (char *) arm_core_regs[i].name;
                reg_list[i].size = 32;
@@ -576,12 +577,13 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
                cache->num_regs++;
        }
 
-       armv4_5_common->cpsr = reg_list + ARMV4_5_CPSR;
-       armv4_5_common->core_cache = cache;
+       arm->pc = reg_list + 15;
+       arm->cpsr = reg_list + ARMV4_5_CPSR;
+       arm->core_cache = cache;
        return cache;
 }
 
-int armv4_5_arch_state(struct target *target)
+int arm_arch_state(struct target *target)
 {
        struct arm *armv4_5 = target_to_arm(target);
 
@@ -593,13 +595,11 @@ int armv4_5_arch_state(struct target *target)
 
        LOG_USER("target halted in %s state due to %s, current mode: %s\n"
                        "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
-                        arm_state_strings[armv4_5->core_state],
-                        Jim_Nvp_value2name_simple(nvp_target_debug_reason,
-                                       target->debug_reason)->name,
-                        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),
+                       arm_state_strings[armv4_5->core_state],
+                       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->pc->value, 0, 32),
                        armv4_5->is_semihosting ? ", semihosting" : "");
 
        return ERROR_OK;
@@ -612,7 +612,6 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct arm *armv4_5 = target_to_arm(target);
-       unsigned num_regs;
        struct reg *regs;
 
        if (!is_arm(armv4_5))
@@ -627,8 +626,17 @@ 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))
+       {
+               LOG_ERROR("not a valid arm core mode - communication failure?");
                return ERROR_FAIL;
+       }
 
        if (!armv4_5->full_context) {
                command_print(CMD_CTX, "error: target doesn't support %s",
@@ -636,7 +644,6 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
                return ERROR_FAIL;
        }
 
-       num_regs = armv4_5->core_cache->num_regs;
        regs = armv4_5->core_cache->reg_list;
 
        for (unsigned mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) {
@@ -706,6 +713,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,11 +737,17 @@ 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);
-       struct arm *arm = target ? target_to_arm(target) : NULL;
+
+       if (target == NULL) {
+               LOG_ERROR("No target selected");
+               return ERROR_FAIL;
+       }
+
+       struct arm *arm = target_to_arm(target);
        uint32_t address;
        int count = 1;
        int thumb = 0;
@@ -737,6 +757,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)
@@ -758,10 +784,8 @@ COMMAND_HANDLER(handle_armv4_5_disassemble_command)
                break;
        default:
 usage:
-               command_print(CMD_CTX,
-                       "usage: arm disassemble <address> [<count> ['thumb']]");
                count = 0;
-               retval = ERROR_FAIL;
+               retval = ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        while (count-- > 0) {
@@ -801,11 +825,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,25 +947,76 @@ 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;
+}
+
 static const struct command_registration arm_exec_command_handlers[] = {
        {
                .name = "reg",
-               .handler = &handle_armv4_5_reg_command,
+               .handler = handle_armv4_5_reg_command,
                .mode = COMMAND_EXEC,
                .help = "display ARM core registers",
+               .usage = "",
        },
        {
                .name = "core_state",
-               .handler = &handle_armv4_5_core_state_command,
+               .handler = handle_armv4_5_core_state_command,
                .mode = COMMAND_EXEC,
-               .usage = "<arm | thumb>",
+               .usage = "['arm'|'thumb']",
                .help = "display/change ARM core state",
        },
        {
                .name = "disassemble",
-               .handler = &handle_armv4_5_disassemble_command,
+               .handler = handle_arm_disassemble_command,
                .mode = COMMAND_EXEC,
-               .usage = "<address> [<count> ['thumb']]",
+               .usage = "address [count ['thumb']]",
                .help = "disassemble instructions ",
        },
        {
@@ -959,6 +1032,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
 };
@@ -967,18 +1047,23 @@ const struct command_registration arm_command_handlers[] = {
                .name = "arm",
                .mode = COMMAND_ANY,
                .help = "ARM command group",
+               .usage = "",
                .chain = arm_exec_command_handlers,
        },
        COMMAND_REGISTRATION_DONE
 };
 
-int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
+int arm_get_gdb_reg_list(struct target *target,
+               struct reg **reg_list[], int *reg_list_size)
 {
        struct arm *armv4_5 = target_to_arm(target);
        int i;
 
        if (!is_arm_mode(armv4_5->core_mode))
+       {
+               LOG_ERROR("not a valid arm core mode - communication failure?");
                return ERROR_FAIL;
+       }
 
        *reg_list_size = 26;
        *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
@@ -1017,11 +1102,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;
        }
 
@@ -1037,7 +1121,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
                                int timeout_ms, void *arch_info))
 {
        struct arm *armv4_5 = target_to_arm(target);
-       struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
+       struct arm_algorithm *arm_algorithm_info = arch_info;
        enum arm_state core_state = armv4_5->core_state;
        uint32_t context[17];
        uint32_t cpsr;
@@ -1047,7 +1131,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
 
        LOG_DEBUG("Running algorithm");
 
-       if (armv4_5_algorithm_info->common_magic != ARM_COMMON_MAGIC)
+       if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC)
        {
                LOG_ERROR("current target isn't an ARMV4/5 target");
                return ERROR_TARGET_INVALID;
@@ -1060,7 +1144,10 @@ int armv4_5_run_algorithm_inner(struct target *target,
        }
 
        if (!is_arm_mode(armv4_5->core_mode))
+       {
+               LOG_ERROR("not a valid arm core mode - communication failure?");
                return ERROR_FAIL;
+       }
 
        /* armv5 and later can terminate with BKPT instruction; less overhead */
        if (!exit_point && armv4_5->is_armv4)
@@ -1077,10 +1164,10 @@ int armv4_5_run_algorithm_inner(struct target *target,
                struct reg *r;
 
                r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                               armv4_5_algorithm_info->core_mode, i);
+                               arm_algorithm_info->core_mode, i);
                if (!r->valid)
                        armv4_5->read_core_reg(target, r, i,
-                                       armv4_5_algorithm_info->core_mode);
+                                       arm_algorithm_info->core_mode);
                context[i] = buf_get_u32(r->value, 0, 32);
        }
        cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
@@ -1099,13 +1186,13 @@ int armv4_5_run_algorithm_inner(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;
                }
 
                if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
@@ -1114,7 +1201,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
                }
        }
 
-       armv4_5->core_state = armv4_5_algorithm_info->core_state;
+       armv4_5->core_state = arm_algorithm_info->core_state;
        if (armv4_5->core_state == ARM_STATE_ARM)
                exit_breakpoint_size = 4;
        else if (armv4_5->core_state == ARM_STATE_THUMB)
@@ -1122,15 +1209,15 @@ int armv4_5_run_algorithm_inner(struct target *target,
        else
        {
                LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       if (armv4_5_algorithm_info->core_mode != ARM_MODE_ANY)
+       if (arm_algorithm_info->core_mode != ARM_MODE_ANY)
        {
                LOG_DEBUG("setting core_mode: 0x%2.2x",
-                               armv4_5_algorithm_info->core_mode);
+                               arm_algorithm_info->core_mode);
                buf_set_u32(armv4_5->cpsr->value, 0, 5,
-                               armv4_5_algorithm_info->core_mode);
+                               arm_algorithm_info->core_mode);
                armv4_5->cpsr->dirty = 1;
                armv4_5->cpsr->valid = 1;
        }
@@ -1174,14 +1261,14 @@ int armv4_5_run_algorithm_inner(struct target *target,
                        if (!reg)
                        {
                                LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
-                               retval = ERROR_INVALID_ARGUMENTS;
+                               retval = ERROR_COMMAND_SYNTAX_ERROR;
                                continue;
                        }
 
                        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);
-                               retval = ERROR_INVALID_ARGUMENTS;
+                               retval = ERROR_COMMAND_SYNTAX_ERROR;
                                continue;
                        }
 
@@ -1193,13 +1280,13 @@ int armv4_5_run_algorithm_inner(struct target *target,
        for (i = 0; i <= 16; i++)
        {
                uint32_t regvalue;
-               regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
+               regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, arm_algorithm_info->core_mode, i).value, 0, 32);
                if (regvalue != context[i])
                {
-                       LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, context[i]);
-                       buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
-                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
-                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
+                       LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, arm_algorithm_info->core_mode, i).name, context[i]);
+                       buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
+                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, arm_algorithm_info->core_mode, i).valid = 1;
+                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, arm_algorithm_info->core_mode, i).dirty = 1;
                }
        }
 
@@ -1219,16 +1306,19 @@ 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 armv4_5_algorithm armv4_5_info;
+       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;
+
+       /* see contib/loaders/checksum/armv4_5_crc.s for src */
 
        static const uint32_t arm_crc_code[] = {
                0xE1A02000,             /* mov          r2, r0 */
@@ -1254,7 +1344,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 */
        };
@@ -1286,9 +1376,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");
@@ -1313,16 +1407,17 @@ 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)
 {
        struct working_area *check_algorithm;
        struct reg_param reg_params[3];
-       struct armv4_5_algorithm armv4_5_info;
+       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: */
@@ -1331,7 +1426,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 */
@@ -1363,9 +1458,13 @@ int arm_blank_check_memory(struct target *target,
        init_reg_param(&reg_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(&reg_params[0]);
@@ -1419,16 +1518,18 @@ static int arm_default_mcr(struct target *target, int cpnum,
        return ERROR_FAIL;
 }
 
-int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
+int arm_init_arch_info(struct target *target, struct arm *armv4_5)
 {
        target->arch_info = 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)