target: "mcr" and "mrc" are ARM-specific
authorDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 1 Dec 2009 08:48:53 +0000 (00:48 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 1 Dec 2009 08:48:53 +0000 (00:48 -0800)
Switch "mrc" and "mcr" commands to be toplevel ARM operations,
as they should initially have been.

Correct the usage message for both commands:  it matches ARM
documentation (as one wants!) instead of reordering them to
match the funky mrc() and mcr() method usage (sigh).

For Cortex-A8: restore a line that got accidentally dropped,
so the secure monitor mode shadow registers will show again.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/arm11.c
src/target/arm720t.c
src/target/arm920t.c
src/target/arm926ejs.c
src/target/armv4_5.c
src/target/armv4_5.h
src/target/cortex_a8.c
src/target/target.c
src/target/target_type.h

index daba3b847cc4cfb88a0b1d36dda73e947179bb4c..30dbedb93975cbe2cc84a693617d160a5e5ad62e 100644 (file)
@@ -1219,6 +1219,13 @@ static int arm11_remove_watchpoint(struct target *target,
        return ERROR_FAIL;
 }
 
+static int arm11_mrc(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm, uint32_t *value);
+static int arm11_mcr(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2, uint32_t CRn,
+               uint32_t CRm, uint32_t value);
+
 static int arm11_target_create(struct target *target, Jim_Interp *interp)
 {
        struct arm11_common *arm11;
@@ -1238,6 +1245,9 @@ static int arm11_target_create(struct target *target, Jim_Interp *interp)
 
        armv4_5_init_arch_info(target, &arm11->arm);
 
+       arm11->arm.mrc = arm11_mrc;
+       arm11->arm.mcr = arm11_mcr;
+
        arm11->target = target;
 
        arm11->jtag_info.tap = target->tap;
@@ -1679,7 +1689,4 @@ struct target_type arm11_target = {
        .target_create =        arm11_target_create,
        .init_target =          arm11_init_target,
        .examine =              arm11_examine,
-
-       .mrc =                  arm11_mrc,
-       .mcr =                  arm11_mcr,
 };
index bae2561aea1679e3feecd689422f9ef040add7e8..d900d8ae23981fab090b127b0a69d40920deeaba 100644 (file)
@@ -378,11 +378,24 @@ static int arm720t_init_target(struct command_context *cmd_ctx, struct target *t
        return arm7tdmi_init_target(cmd_ctx, target);
 }
 
+/* FIXME remove forward decls */
+static int arm720t_mrc(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm,
+               uint32_t *value);
+static int arm720t_mcr(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm,
+               uint32_t value);
+
 static int arm720t_init_arch_info(struct target *target,
                struct arm720t_common *arm720t, struct jtag_tap *tap)
 {
        struct arm7_9_common *arm7_9 = &arm720t->arm7_9_common;
 
+       arm7_9->armv4_5_common.mrc = arm720t_mrc;
+       arm7_9->armv4_5_common.mcr = arm720t_mcr;
+
        arm7tdmi_init_arch_info(target, arm7_9, tap);
 
        arm720t->common_magic = ARM720T_COMMON_MAGIC;
@@ -556,6 +569,4 @@ struct target_type arm720t_target =
        .target_create = arm720t_target_create,
        .init_target = arm720t_init_target,
        .examine = arm7_9_examine,
-       .mrc = arm720t_mrc,
-       .mcr = arm720t_mcr,
 };
index e6c2eed82d48928055667124e8abf97e9484b1c0..17e7a55ae4429e74f529a78cdedb976d246e64b5 100644 (file)
@@ -624,10 +624,23 @@ int arm920t_soft_reset_halt(struct target *target)
        return ERROR_OK;
 }
 
+/* FIXME remove forward decls */
+static int arm920t_mrc(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm,
+               uint32_t *value);
+static int arm920t_mcr(struct target *target, int cpnum,
+               uint32_t op1, uint32_t op2,
+               uint32_t CRn, uint32_t CRm,
+               uint32_t value);
+
 int arm920t_init_arch_info(struct target *target, struct arm920t_common *arm920t, struct jtag_tap *tap)
 {
        struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
 
+       arm7_9->armv4_5_common.mrc = arm920t_mrc;
+       arm7_9->armv4_5_common.mcr = arm920t_mcr;
+
        /* initialize arm7/arm9 specific info (including armv4_5) */
        arm9tdmi_init_arch_info(target, arm7_9, tap);
 
@@ -1452,6 +1465,4 @@ struct target_type arm920t_target =
        .target_create = arm920t_target_create,
        .init_target = arm9tdmi_init_target,
        .examine = arm7_9_examine,
-       .mrc = arm920t_mrc,
-       .mcr = arm920t_mcr,
 };
index 408ede9debeb7bf82db75e9f625bbc8fed612ae9..ca420aa69d68585cba97bb3ce9e0916d5a512cd3 100644 (file)
@@ -673,6 +673,9 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm
 {
        struct arm7_9_common *arm7_9 = &arm926ejs->arm7_9_common;
 
+       arm7_9->armv4_5_common.mrc = arm926ejs_mrc;
+       arm7_9->armv4_5_common.mcr = arm926ejs_mcr;
+
        /* initialize arm7/arm9 specific info (including armv4_5) */
        arm9tdmi_init_arch_info(target, arm7_9, tap);
 
@@ -822,6 +825,4 @@ struct target_type arm926ejs_target =
 
        .read_phys_memory = arm926ejs_read_phys_memory,
        .write_phys_memory = arm926ejs_write_phys_memory,
-       .mrc = arm926ejs_mrc,
-       .mcr = arm926ejs_mcr,
 };
index b5e33ff5466fdf2ec010349c24e2db57830c97e0..d047b1b6fa14102c26cc4120d6a23e1bd31181b6 100644 (file)
@@ -790,6 +790,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",
@@ -811,6 +942,20 @@ 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
 };
 const struct command_registration arm_command_handlers[] = {
@@ -1252,6 +1397,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;
@@ -1267,5 +1430,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;
 }
index 822d14393b2eb94c00ca7573fe907fab8bd9e88d..7229a6c0bdbeba1080a9cc3cd29eee3b49c80737 100644 (file)
@@ -112,11 +112,26 @@ struct arm
        /** Handle for the Embedded Trace Module, if one is present. */
        struct etm_context *etm;
 
+       /* FIXME all these methods should take "struct arm *" not target */
+
        int (*full_context)(struct target *target);
        int (*read_core_reg)(struct target *target, struct reg *reg,
                        int num, enum armv4_5_mode mode);
        int (*write_core_reg)(struct target *target, struct reg *reg,
                        int num, enum armv4_5_mode mode, uint32_t value);
+
+       /** Read coprocessor register.  */
+       int (*mrc)(struct target *target, int cpnum,
+                       uint32_t op1, uint32_t op2,
+                       uint32_t CRn, uint32_t CRm,
+                       uint32_t *value);
+
+       /* Write coprocessor register.  */
+       int (*mcr)(struct target *target, int cpnum,
+                       uint32_t op1, uint32_t op2,
+                       uint32_t CRn, uint32_t CRm,
+                       uint32_t value);
+
        void *arch_info;
 };
 
index 652efa9353ac5036076516e62bc8a233c7b17165..9ce6b2bad31159d6b78a4e78d33fd27f08d0973c 100644 (file)
@@ -936,7 +936,7 @@ static void cortex_a8_post_debug_entry(struct target *target)
        int retval;
 
        /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
-       retval = target->type->mrc(target, 15,
+       retval = armv7a->armv4_5_common.mrc(target, 15,
                        0, 0,   /* op1, op2 */
                        1, 0,   /* CRn, CRm */
                        &cortex_a8->cp15_control_reg);
@@ -947,7 +947,7 @@ static void cortex_a8_post_debug_entry(struct target *target)
                uint32_t cache_type_reg;
 
                /* MRC p15,0,<Rt>,c0,c0,1 ; Read CP15 Cache Type Register */
-               retval = target->type->mrc(target, 15,
+               retval = armv7a->armv4_5_common.mrc(target, 15,
                                0, 1,   /* op1, op2 */
                                0, 0,   /* CRn, CRm */
                                &cache_type_reg);
@@ -1535,6 +1535,7 @@ static int cortex_a8_examine_first(struct target *target)
        LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
        LOG_DEBUG("didr = 0x%08" PRIx32, didr);
 
+       armv7a->armv4_5_common.core_type = ARM_MODE_MON;
        cortex_a8_dpm_setup(cortex_a8, didr);
 
        /* Setup Breakpoint Register Pairs */
@@ -1611,6 +1612,9 @@ static int cortex_a8_init_arch_info(struct target *target,
        cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC;
        armv4_5->arch_info = armv7a;
 
+       armv4_5->mrc = cortex_a8_mrc,
+       armv4_5->mcr = cortex_a8_mcr,
+
        /* prepare JTAG information for the new target */
        cortex_a8->jtag_info.tap = tap;
        cortex_a8->jtag_info.scann_size = 4;
@@ -1626,7 +1630,6 @@ static int cortex_a8_init_arch_info(struct target *target,
 
        cortex_a8->fast_reg_read = 0;
 
-
        /* register arch-specific functions */
        armv7a->examine_debug_reason = NULL;
 
@@ -1752,6 +1755,4 @@ struct target_type cortexa8_target = {
        .target_create = cortex_a8_target_create,
        .init_target = cortex_a8_init_target,
        .examine = cortex_a8_examine,
-       .mrc = cortex_a8_mrc,
-       .mcr = cortex_a8_mcr,
 };
index 31734b8f1bb30db61142ebfb1009b43f87118068..88931b5badfb922ecafae90193e97cc8ea23703b 100644 (file)
@@ -44,8 +44,6 @@
 #include "jtag.h"
 
 
-static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-
 static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv);
 static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv);
 
@@ -665,84 +663,6 @@ static void target_reset_examined(struct target *target)
        target->examined = false;
 }
 
-
-
-static int default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
-
-static int default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
-{
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
-
-static int arm_cp_check(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm)
-{
-       /* basic check */
-       if (!target_was_examined(target))
-       {
-               LOG_ERROR("Target not examined yet");
-               return ERROR_FAIL;
-       }
-
-       if ((cpnum <0) || (cpnum > 15))
-       {
-               LOG_ERROR("Illegal co-processor %d", cpnum);
-               return ERROR_FAIL;
-       }
-
-       if (op1 > 7)
-       {
-               LOG_ERROR("Illegal op1");
-               return ERROR_FAIL;
-       }
-
-       if (op2 > 7)
-       {
-               LOG_ERROR("Illegal op2");
-               return ERROR_FAIL;
-       }
-
-       if (CRn > 15)
-       {
-               LOG_ERROR("Illegal CRn");
-               return ERROR_FAIL;
-       }
-
-       if (CRm > 15)
-       {
-               LOG_ERROR("Illegal CRm");
-               return ERROR_FAIL;
-       }
-
-       return ERROR_OK;
-}
-
-int target_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
-       int retval;
-
-       retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return target->type->mrc(target, cpnum, op1, op2, CRn, CRm, value);
-}
-
-int target_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
-{
-       int retval;
-
-       retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return target->type->mcr(target, cpnum, op1, op2, CRn, CRm, value);
-}
-
 static int
 err_read_phys_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
@@ -781,39 +701,6 @@ int target_init(struct command_context *cmd_ctx)
                        return retval;
                }
 
-               /**
-                * @todo MCR/MRC are ARM-specific; don't require them in
-                * all targets, or for ARMs without coprocessors.
-                */
-               if (target->type->mcr == NULL)
-               {
-                       target->type->mcr = default_mcr;
-               } else
-               {
-                       const struct command_registration mcr_cmd = {
-                               .name = "mcr",
-                               .mode = COMMAND_EXEC,
-                               .jim_handler = &jim_mcrmrc,
-                               .help = "write coprocessor",
-                               .usage = "<cpnum> <op1> <op2> <CRn> <CRm> <value>",
-                       };
-                       register_command(cmd_ctx, NULL, &mcr_cmd);
-               }
-
-               if (target->type->mrc == NULL)
-               {
-                       target->type->mrc = default_mrc;
-               } else
-               {
-                       const struct command_registration mrc_cmd = {
-                               .name = "mrc",
-                               .jim_handler = &jim_mcrmrc,
-                               .help = "read coprocessor",
-                               .usage = "<cpnum> <op1> <op2> <CRn> <CRm>",
-                       };
-                       register_command(cmd_ctx, NULL, &mrc_cmd);
-               }
-
 
                /**
                 * @todo get rid of those *memory_imp() methods, now that all
@@ -4883,92 +4770,6 @@ COMMAND_HANDLER(handle_fast_load_command)
        return retval;
 }
 
-static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       struct command_context *context;
-       struct target *target;
-       int retval;
-
-       context = Jim_GetAssocData(interp, "context");
-       if (context == NULL) {
-               LOG_ERROR("array2mem: no command context");
-               return JIM_ERR;
-       }
-       target = get_current_target(context);
-       if (target == NULL) {
-               LOG_ERROR("array2mem: no current target");
-               return JIM_ERR;
-       }
-
-       if ((argc < 6) || (argc > 7))
-       {
-               return JIM_ERR;
-       }
-
-       int cpnum;
-       uint32_t op1;
-       uint32_t op2;
-       uint32_t CRn;
-       uint32_t CRm;
-       uint32_t value;
-
-       int e;
-       long l;
-       e = Jim_GetLong(interp, argv[1], &l);
-       if (e != JIM_OK) {
-               return e;
-       }
-       cpnum = l;
-
-       e = Jim_GetLong(interp, argv[2], &l);
-       if (e != JIM_OK) {
-               return e;
-       }
-       op1 = l;
-
-       e = Jim_GetLong(interp, argv[3], &l);
-       if (e != JIM_OK) {
-               return e;
-       }
-       CRn = l;
-
-       e = Jim_GetLong(interp, argv[4], &l);
-       if (e != JIM_OK) {
-               return e;
-       }
-       CRm = l;
-
-       e = Jim_GetLong(interp, argv[5], &l);
-       if (e != JIM_OK) {
-               return e;
-       }
-       op2 = l;
-
-       value = 0;
-
-       if (argc == 7)
-       {
-               e = Jim_GetLong(interp, argv[6], &l);
-               if (e != JIM_OK) {
-                       return e;
-               }
-               value = l;
-
-               retval = target_mcr(target, cpnum, op1, op2, CRn, CRm, value);
-               if (retval != ERROR_OK)
-                       return JIM_ERR;
-       } else
-       {
-               retval = target_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 target_command_handlers[] = {
        {
                .name = "targets",
index d141608b41409f6e8b847658961ac85a09a71f21..15cf66be85bf18ef8c576d342c112e82ecefe764 100644 (file)
@@ -213,11 +213,6 @@ struct target_type
 
        int (*mmu)(struct target *target, int *enabled);
 
-       /* Read coprocessor - arm specific. Default implementation returns error. */
-       int (*mrc)(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value);
-
-       /* Write coprocessor. Default implementation returns error.  */
-       int (*mcr)(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value);
 };
 
 #endif // TARGET_TYPE_H

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)