split NOR and NAND flash headers
[openocd.git] / src / target / armv4_5.c
index dfb7094b6635e262932669801766939332516a7a..412b829012a7cb5fe45f86a7f3c1f6e6c8d39d55 100644 (file)
@@ -31,7 +31,7 @@
 #include "arm_jtag.h"
 #include "breakpoints.h"
 #include "arm_disassembler.h"
-#include "binarybuffer.h"
+#include <helper/binarybuffer.h>
 #include "algorithm.h"
 #include "register.h"
 
@@ -281,20 +281,20 @@ static const struct {
        { .name = "r11_fiq", .cookie = 11, .mode = ARMV4_5_MODE_FIQ, },
        { .name = "r12_fiq", .cookie = 12, .mode = ARMV4_5_MODE_FIQ, },
 
-       { .name = "lr_fiq", .cookie = 13, .mode = ARMV4_5_MODE_FIQ, },
-       { .name = "sp_fiq", .cookie = 14, .mode = ARMV4_5_MODE_FIQ, },
+       { .name = "sp_fiq", .cookie = 13, .mode = ARMV4_5_MODE_FIQ, },
+       { .name = "lr_fiq", .cookie = 14, .mode = ARMV4_5_MODE_FIQ, },
 
-       { .name = "lr_irq", .cookie = 13, .mode = ARMV4_5_MODE_IRQ, },
-       { .name = "sp_irq", .cookie = 14, .mode = ARMV4_5_MODE_IRQ, },
+       { .name = "sp_irq", .cookie = 13, .mode = ARMV4_5_MODE_IRQ, },
+       { .name = "lr_irq", .cookie = 14, .mode = ARMV4_5_MODE_IRQ, },
 
-       { .name = "lr_svc", .cookie = 13, .mode = ARMV4_5_MODE_SVC, },
-       { .name = "sp_svc", .cookie = 14, .mode = ARMV4_5_MODE_SVC, },
+       { .name = "sp_svc", .cookie = 13, .mode = ARMV4_5_MODE_SVC, },
+       { .name = "lr_svc", .cookie = 14, .mode = ARMV4_5_MODE_SVC, },
 
-       { .name = "lr_abt", .cookie = 13, .mode = ARMV4_5_MODE_ABT, },
-       { .name = "sp_abt", .cookie = 14, .mode = ARMV4_5_MODE_ABT, },
+       { .name = "sp_abt", .cookie = 13, .mode = ARMV4_5_MODE_ABT, },
+       { .name = "lr_abt", .cookie = 14, .mode = ARMV4_5_MODE_ABT, },
 
-       { .name = "lr_und", .cookie = 13, .mode = ARMV4_5_MODE_UND, },
-       { .name = "sp_und", .cookie = 14, .mode = ARMV4_5_MODE_UND, },
+       { .name = "sp_und", .cookie = 13, .mode = ARMV4_5_MODE_UND, },
+       { .name = "lr_und", .cookie = 14, .mode = ARMV4_5_MODE_UND, },
 
        { .name = "cpsr", .cookie = 16, .mode = ARMV4_5_MODE_ANY, },
        { .name = "spsr_fiq", .cookie = 16, .mode = ARMV4_5_MODE_FIQ, },
@@ -303,8 +303,8 @@ static const struct {
        { .name = "spsr_abt", .cookie = 16, .mode = ARMV4_5_MODE_ABT, },
        { .name = "spsr_und", .cookie = 16, .mode = ARMV4_5_MODE_UND, },
 
-       { .name = "lr_mon", .cookie = 13, .mode = ARM_MODE_MON, },
-       { .name = "sp_mon", .cookie = 14, .mode = ARM_MODE_MON, },
+       { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, },
+       { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, },
        { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, },
 };
 
@@ -390,6 +390,10 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
                        state = ARMV4_5_STATE_ARM;
        }
        arm->core_state = state;
+
+       LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
+                       arm_mode_name(mode),
+                       armv4_5_state_strings[arm->core_state]);
 }
 
 /**
@@ -583,16 +587,20 @@ int armv4_5_arch_state(struct target *target)
 
        if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
        {
-               LOG_ERROR("BUG: called for a non-ARMv4/5 target");
+               LOG_ERROR("BUG: called for a non-ARM target");
                return ERROR_FAIL;
        }
 
-       LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
+       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",
                         armv4_5_state_strings[armv4_5->core_state],
-                        Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
+                        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));
+                       buf_get_u32(armv4_5->core_cache->reg_list[15].value,
+                                       0, 32),
+                       armv4_5->is_semihosting ? ", semihosting" : "");
 
        return ERROR_OK;
 }
@@ -786,6 +794,137 @@ usage:
        return retval;
 }
 
+static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       struct command_context *context;
+       struct target *target;
+       struct arm *arm;
+       int retval;
+
+       context = Jim_GetAssocData(interp, "context");
+       if (context == NULL) {
+               LOG_ERROR("%s: no command context", __func__);
+               return JIM_ERR;
+       }
+       target = get_current_target(context);
+       if (target == NULL) {
+               LOG_ERROR("%s: no current target", __func__);
+               return JIM_ERR;
+       }
+       if (!target_was_examined(target)) {
+               LOG_ERROR("%s: not yet examined", target_name(target));
+               return JIM_ERR;
+       }
+       arm = target_to_arm(target);
+       if (!is_arm(arm)) {
+               LOG_ERROR("%s: not an ARM", target_name(target));
+               return JIM_ERR;
+       }
+
+       if ((argc < 6) || (argc > 7)) {
+               /* FIXME use the command name to verify # params... */
+               LOG_ERROR("%s: wrong number of arguments", __func__);
+               return JIM_ERR;
+       }
+
+       int cpnum;
+       uint32_t op1;
+       uint32_t op2;
+       uint32_t CRn;
+       uint32_t CRm;
+       uint32_t value;
+       long l;
+
+       /* NOTE:  parameter sequence matches ARM instruction set usage:
+        *      MCR     pNUM, op1, rX, CRn, CRm, op2    ; write CP from rX
+        *      MRC     pNUM, op1, rX, CRn, CRm, op2    ; read CP into rX
+        * The "rX" is necessarily omitted; it uses Tcl mechanisms.
+        */
+       retval = Jim_GetLong(interp, argv[1], &l);
+       if (retval != JIM_OK)
+               return retval;
+       if (l & ~0xf) {
+               LOG_ERROR("%s: %s %d out of range", __func__,
+                               "coprocessor", (int) l);
+               return JIM_ERR;
+       }
+       cpnum = l;
+
+       retval = Jim_GetLong(interp, argv[2], &l);
+       if (retval != JIM_OK)
+               return retval;
+       if (l & ~0x7) {
+               LOG_ERROR("%s: %s %d out of range", __func__,
+                               "op1", (int) l);
+               return JIM_ERR;
+       }
+       op1 = l;
+
+       retval = Jim_GetLong(interp, argv[3], &l);
+       if (retval != JIM_OK)
+               return retval;
+       if (l & ~0xf) {
+               LOG_ERROR("%s: %s %d out of range", __func__,
+                               "CRn", (int) l);
+               return JIM_ERR;
+       }
+       CRn = l;
+
+       retval = Jim_GetLong(interp, argv[4], &l);
+       if (retval != JIM_OK)
+               return retval;
+       if (l & ~0xf) {
+               LOG_ERROR("%s: %s %d out of range", __func__,
+                               "CRm", (int) l);
+               return JIM_ERR;
+       }
+       CRm = l;
+
+       retval = Jim_GetLong(interp, argv[5], &l);
+       if (retval != JIM_OK)
+               return retval;
+       if (l & ~0x7) {
+               LOG_ERROR("%s: %s %d out of range", __func__,
+                               "op2", (int) l);
+               return JIM_ERR;
+       }
+       op2 = l;
+
+       value = 0;
+
+       /* FIXME don't assume "mrc" vs "mcr" from the number of params;
+        * that could easily be a typo!  Check both...
+        *
+        * FIXME change the call syntax here ... simplest to just pass
+        * the MRC() or MCR() instruction to be executed.  That will also
+        * let us support the "mrc2" and "mcr2" opcodes (toggling one bit)
+        * if that's ever needed.
+        */
+       if (argc == 7) {
+               retval = Jim_GetLong(interp, argv[6], &l);
+               if (retval != JIM_OK) {
+                       return retval;
+               }
+               value = l;
+
+               /* NOTE: parameters reordered! */
+               // ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2)
+               retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value);
+               if (retval != ERROR_OK)
+                       return JIM_ERR;
+       } else {
+               /* NOTE: parameters reordered! */
+               // ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2)
+               retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value);
+               if (retval != ERROR_OK)
+                       return JIM_ERR;
+
+               Jim_SetResult(interp, Jim_NewIntObj(interp, value));
+       }
+
+       return JIM_OK;
+}
+
 static const struct command_registration arm_exec_command_handlers[] = {
        {
                .name = "reg",
@@ -807,9 +946,23 @@ static const struct command_registration arm_exec_command_handlers[] = {
                .usage = "<address> [<count> ['thumb']]",
                .help = "disassemble instructions ",
        },
+       {
+               .name = "mcr",
+               .mode = COMMAND_EXEC,
+               .jim_handler = &jim_mcrmrc,
+               .help = "write coprocessor register",
+               .usage = "cpnum op1 CRn op2 CRm value",
+       },
+       {
+               .name = "mrc",
+               .jim_handler = &jim_mcrmrc,
+               .help = "read coprocessor register",
+               .usage = "cpnum op1 CRn op2 CRm",
+       },
+
        COMMAND_REGISTRATION_DONE
 };
-static const struct command_registration arm_command_handlers[] = {
+const struct command_registration arm_command_handlers[] = {
        {
                .name = "arm",
                .mode = COMMAND_ANY,
@@ -819,11 +972,6 @@ static const struct command_registration arm_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
-int armv4_5_register_commands(struct command_context *cmd_ctx)
-{
-       return register_commands(cmd_ctx, NULL, arm_command_handlers);
-}
-
 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
 {
        struct arm *armv4_5 = target_to_armv4_5(target);
@@ -880,7 +1028,13 @@ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit
        return ERROR_OK;
 }
 
-int armv4_5_run_algorithm_inner(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, int (*run_it)(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info))
+int armv4_5_run_algorithm_inner(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,
+               int (*run_it)(struct target *target, uint32_t exit_point,
+                               int timeout_ms, void *arch_info))
 {
        struct arm *armv4_5 = target_to_armv4_5(target);
        struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
@@ -890,6 +1044,7 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
        int exit_breakpoint_size = 0;
        int i;
        int retval = ERROR_OK;
+
        LOG_DEBUG("Running algorithm");
 
        if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
@@ -1246,6 +1401,24 @@ static int arm_full_context(struct target *target)
        return retval;
 }
 
+static int arm_default_mrc(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm,
+               uint32_t *value)
+{
+       LOG_ERROR("%s doesn't implement MRC", target_type_name(target));
+       return ERROR_FAIL;
+}
+
+static int arm_default_mcr(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm,
+               uint32_t value)
+{
+       LOG_ERROR("%s doesn't implement MCR", target_type_name(target));
+       return ERROR_FAIL;
+}
+
 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
 {
        target->arch_info = armv4_5;
@@ -1261,5 +1434,10 @@ int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
        if (!armv4_5->full_context && armv4_5->read_core_reg)
                armv4_5->full_context = arm_full_context;
 
+       if (!armv4_5->mrc)
+               armv4_5->mrc = arm_default_mrc;
+       if (!armv4_5->mcr)
+               armv4_5->mcr = arm_default_mcr;
+
        return ERROR_OK;
 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)