ETM: use new toplevel ETM handle
[openocd.git] / src / target / etm.c
index 91c73a232db44e7a73f68b06c6aa8a930be91195..53d31a1538421beb59d7381ad13fd53129d84e6e 100644 (file)
@@ -68,6 +68,7 @@ struct etm_reg_info {
 
 /*
  * Registers 0..0x7f are JTAG-addressable using scanchain 6.
+ * (Or on some processors, through coprocessor operations.)
  * Newer versions of ETM make some W/O registers R/W, and
  * provide definitions for some previously-unused bits.
  */
@@ -75,47 +76,46 @@ struct etm_reg_info {
 /* basic registers that are always there given the right ETM version */
 static const struct etm_reg_info etm_core[] = {
        /* NOTE: we "know" ETM_CONFIG is listed first */
-       { ETM_CONFIG, 32, RO, 0x10, "ETM_CONFIG", },
+       { ETM_CONFIG, 32, RO, 0x10, "ETM_config", },
 
        /* ETM Trace Registers */
-       { ETM_CTRL, 32, RW, 0x10, "ETM_CTRL", },
-       { ETM_TRIG_EVENT, 17, WO, 0x10, "ETM_TRIG_EVENT", },
-       { ETM_ASIC_CTRL,  8, WO, 0x10, "ETM_ASIC_CTRL", },
-       { ETM_STATUS,  3, RO, 0x11, "ETM_STATUS", },
-       { ETM_SYS_CONFIG,  9, RO, 0x12, "ETM_SYS_CONFIG", },
+       { ETM_CTRL, 32, RW, 0x10, "ETM_ctrl", },
+       { ETM_TRIG_EVENT, 17, WO, 0x10, "ETM_trig_event", },
+       { ETM_ASIC_CTRL,  8, WO, 0x10, "ETM_asic_ctrl", },
+       { ETM_STATUS,  3, RO, 0x11, "ETM_status", },
+       { ETM_SYS_CONFIG,  9, RO, 0x12, "ETM_sys_config", },
 
        /* TraceEnable configuration */
-       { ETM_TRACE_RESOURCE_CTRL, 32, WO, 0x12, "ETM_TRACE_RESOURCE_CTRL", },
-       { ETM_TRACE_EN_CTRL2, 16, WO, 0x12, "ETM_TRACE_EN_CTRL2", },
-       { ETM_TRACE_EN_EVENT, 17, WO, 0x10, "ETM_TRACE_EN_EVENT", },
-       { ETM_TRACE_EN_CTRL1, 26, WO, 0x10, "ETM_TRACE_EN_CTRL1", },
+       { ETM_TRACE_RESOURCE_CTRL, 32, WO, 0x12, "ETM_trace_resource_ctrl", },
+       { ETM_TRACE_EN_CTRL2, 16, WO, 0x12, "ETM_trace_en_ctrl2", },
+       { ETM_TRACE_EN_EVENT, 17, WO, 0x10, "ETM_trace_en_event", },
+       { ETM_TRACE_EN_CTRL1, 26, WO, 0x10, "ETM_trace_en_ctrl1", },
 
        /* ViewData configuration (data trace) */
-       { ETM_VIEWDATA_EVENT, 17, WO, 0x10, "ETM_VIEWDATA_EVENT", },
-       { ETM_VIEWDATA_CTRL1, 32, WO, 0x10, "ETM_VIEWDATA_CTRL1", },
-       { ETM_VIEWDATA_CTRL2, 32, WO, 0x10, "ETM_VIEWDATA_CTRL2", },
-       { ETM_VIEWDATA_CTRL3, 17, WO, 0x10, "ETM_VIEWDATA_CTRL3", },
+       { ETM_VIEWDATA_EVENT, 17, WO, 0x10, "ETM_viewdata_event", },
+       { ETM_VIEWDATA_CTRL1, 32, WO, 0x10, "ETM_viewdata_ctrl1", },
+       { ETM_VIEWDATA_CTRL2, 32, WO, 0x10, "ETM_viewdata_ctrl2", },
+       { ETM_VIEWDATA_CTRL3, 17, WO, 0x10, "ETM_viewdata_ctrl3", },
 
        /* REVISIT exclude VIEWDATA_CTRL2 when it's not there */
 
-       { 0x78, 12, WO, 0x20, "ETM_SYNC_FREQ", },
-       { 0x79, 32, RO, 0x20, "ETM_ID", },
+       { 0x78, 12, WO, 0x20, "ETM_sync_freq", },
+       { 0x79, 32, RO, 0x20, "ETM_id", },
 };
 
 static const struct etm_reg_info etm_fifofull[] = {
        /* FIFOFULL configuration */
-       { ETM_FIFOFULL_REGION, 25, WO, 0x10, "ETM_FIFOFULL_REGION", },
-       { ETM_FIFOFULL_LEVEL,  8, WO, 0x10, "ETM_FIFOFULL_LEVEL", },
+       { ETM_FIFOFULL_REGION, 25, WO, 0x10, "ETM_fifofull_region", },
+       { ETM_FIFOFULL_LEVEL,  8, WO, 0x10, "ETM_fifofull_level", },
 };
 
 static const struct etm_reg_info etm_addr_comp[] = {
        /* Address comparator register pairs */
 #define ADDR_COMPARATOR(i) \
-               { ETM_ADDR_COMPARATOR_VALUE + (i), 32, WO, 0x10, \
-                               "ETM_ADDR_COMPARATOR_VALUE" #i, }, \
-               { ETM_ADDR_ACCESS_TYPE + (i),  7, WO, 0x10, \
-                               "ETM_ADDR_ACCESS_TYPE" #i, }
-       ADDR_COMPARATOR(0),
+               { ETM_ADDR_COMPARATOR_VALUE + (i) - 1, 32, WO, 0x10, \
+                               "ETM_addr_" #i "_comparator_value", }, \
+               { ETM_ADDR_ACCESS_TYPE + (i) - 1,  7, WO, 0x10, \
+                               "ETM_addr_" #i "_access_type", }
        ADDR_COMPARATOR(1),
        ADDR_COMPARATOR(2),
        ADDR_COMPARATOR(3),
@@ -123,8 +123,8 @@ static const struct etm_reg_info etm_addr_comp[] = {
        ADDR_COMPARATOR(5),
        ADDR_COMPARATOR(6),
        ADDR_COMPARATOR(7),
-
        ADDR_COMPARATOR(8),
+
        ADDR_COMPARATOR(9),
        ADDR_COMPARATOR(10),
        ADDR_COMPARATOR(11),
@@ -132,17 +132,17 @@ static const struct etm_reg_info etm_addr_comp[] = {
        ADDR_COMPARATOR(13),
        ADDR_COMPARATOR(14),
        ADDR_COMPARATOR(15),
+       ADDR_COMPARATOR(16),
 #undef ADDR_COMPARATOR
 };
 
 static const struct etm_reg_info etm_data_comp[] = {
        /* Data Value Comparators (NOTE: odd addresses are reserved) */
 #define DATA_COMPARATOR(i) \
-               { ETM_DATA_COMPARATOR_VALUE + 2*(i), 32, WO, 0x10, \
-                               "ETM_DATA_COMPARATOR_VALUE" #i, }, \
-               { ETM_DATA_COMPARATOR_MASK + 2*(i), 32, WO, 0x10, \
-                               "ETM_DATA_COMPARATOR_MASK" #i, }
-       DATA_COMPARATOR(0),
+               { ETM_DATA_COMPARATOR_VALUE + 2*(i) - 1, 32, WO, 0x10, \
+                               "ETM_data_" #i "_comparator_value", }, \
+               { ETM_DATA_COMPARATOR_MASK + 2*(i) - 1, 32, WO, 0x10, \
+                               "ETM_data_" #i "_comparator_mask", }
        DATA_COMPARATOR(1),
        DATA_COMPARATOR(2),
        DATA_COMPARATOR(3),
@@ -150,61 +150,62 @@ static const struct etm_reg_info etm_data_comp[] = {
        DATA_COMPARATOR(5),
        DATA_COMPARATOR(6),
        DATA_COMPARATOR(7),
+       DATA_COMPARATOR(8),
 #undef DATA_COMPARATOR
 };
 
 static const struct etm_reg_info etm_counters[] = {
-#define COUNTER(i) \
-               { ETM_COUNTER_RELOAD_VALUE + (i), 16, WO, 0x10, \
-                               "ETM_COUNTER_RELOAD_VALUE" #i, }, \
-               { ETM_COUNTER_ENABLE + (i), 18, WO, 0x10, \
-                               "ETM_COUNTER_ENABLE" #i, }, \
-               { ETM_COUNTER_RELOAD_EVENT + (i), 17, WO, 0x10, \
-                               "ETM_COUNTER_RELOAD_EVENT" #i, }, \
-               { ETM_COUNTER_VALUE + (i), 16, RO, 0x10, \
-                               "ETM_COUNTER_VALUE" #i, }
-       COUNTER(0),
-       COUNTER(1),
-       COUNTER(2),
-       COUNTER(3),
-#undef COUNTER
+#define ETM_COUNTER(i) \
+               { ETM_COUNTER_RELOAD_VALUE + (i) - 1, 16, WO, 0x10, \
+                               "ETM_counter_" #i "_reload_value", }, \
+               { ETM_COUNTER_ENABLE + (i) - 1, 18, WO, 0x10, \
+                               "ETM_counter_" #i "_enable", }, \
+               { ETM_COUNTER_RELOAD_EVENT + (i) - 1, 17, WO, 0x10, \
+                               "ETM_counter_" #i "_reload_event", }, \
+               { ETM_COUNTER_VALUE + (i) - 1, 16, RO, 0x10, \
+                               "ETM_counter_" #i "_value", }
+       ETM_COUNTER(1),
+       ETM_COUNTER(2),
+       ETM_COUNTER(3),
+       ETM_COUNTER(4),
+#undef ETM_COUNTER
 };
 
 static const struct etm_reg_info etm_sequencer[] = {
-#define SEQ(i) \
+#define ETM_SEQ(i) \
                { ETM_SEQUENCER_EVENT + (i), 17, WO, 0x10, \
-                               "ETM_SEQUENCER_EVENT" #i, }
-       SEQ(0),                         /* 1->2 */
-       SEQ(1),                         /* 2->1 */
-       SEQ(2),                         /* 2->3 */
-       SEQ(3),                         /* 3->1 */
-       SEQ(4),                         /* 3->2 */
-       SEQ(5),                         /* 1->3 */
-#undef SEQ
+                               "ETM_sequencer_event" #i, }
+       ETM_SEQ(0),                             /* 1->2 */
+       ETM_SEQ(1),                             /* 2->1 */
+       ETM_SEQ(2),                             /* 2->3 */
+       ETM_SEQ(3),                             /* 3->1 */
+       ETM_SEQ(4),                             /* 3->2 */
+       ETM_SEQ(5),                             /* 1->3 */
+#undef ETM_SEQ
        /* 0x66 reserved */
-       { ETM_SEQUENCER_STATE,  2, RO, 0x10, "ETM_SEQUENCER_STATE", },
+       { ETM_SEQUENCER_STATE,  2, RO, 0x10, "ETM_sequencer_state", },
 };
 
 static const struct etm_reg_info etm_outputs[] = {
-#define OUT(i) \
-               { ETM_EXTERNAL_OUTPUT + (i), 17, WO, 0x10, \
-                               "ETM_EXTERNAL_OUTPUT" #i, }
-
-       OUT(0),
-       OUT(1),
-       OUT(2),
-       OUT(3),
-#undef OUT
+#define ETM_OUTPUT(i) \
+               { ETM_EXTERNAL_OUTPUT + (i) - 1, 17, WO, 0x10, \
+                               "ETM_external_output" #i, }
+
+       ETM_OUTPUT(1),
+       ETM_OUTPUT(2),
+       ETM_OUTPUT(3),
+       ETM_OUTPUT(4),
+#undef ETM_OUTPUT
 };
 
 #if 0
        /* registers from 0x6c..0x7f were added after ETMv1.3 */
 
        /* Context ID Comparators */
-       { 0x6c, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_VALUE1", }
-       { 0x6d, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_VALUE1", }
-       { 0x6e, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_VALUE1", }
-       { 0x6f, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_MASK", }
+       { 0x6c, 32, RO, 0x20, "ETM_contextid_comparator_value1", }
+       { 0x6d, 32, RO, 0x20, "ETM_contextid_comparator_value2", }
+       { 0x6e, 32, RO, 0x20, "ETM_contextid_comparator_value3", }
+       { 0x6f, 32, RO, 0x20, "ETM_contextid_comparator_mask", }
 #endif
 
 static int etm_reg_arch_type = -1;
@@ -409,9 +410,8 @@ int etm_setup(target_t *target)
 {
        int retval;
        uint32_t etm_ctrl_value;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-       etm_context_t *etm_ctx = arm7_9->etm_ctx;
+       struct arm *arm = target_to_arm(target);
+       etm_context_t *etm_ctx = arm->etm;
        reg_t *etm_ctrl_reg;
 
        etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
@@ -670,12 +670,12 @@ static int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instructi
        else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
        {
                LOG_ERROR("BUG: tracing of jazelle code not supported");
-               exit(-1);
+               return ERROR_FAIL;
        }
        else
        {
                LOG_ERROR("BUG: unknown core state encountered");
-               exit(-1);
+               return ERROR_FAIL;
        }
 
        return ERROR_OK;
@@ -976,8 +976,7 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
                                        break;
                                default:        /* reserved */
                                        LOG_ERROR("BUG: branch reason code 0x%" PRIx32 " is reserved", ctx->last_branch_reason);
-                                       exit(-1);
-                                       break;
+                                       return ERROR_FAIL;
                        }
 
                        /* if we got here the branch was a normal PC change
@@ -1154,106 +1153,117 @@ static int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd
        return ERROR_OK;
 }
 
-static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_tracemode_command_update(
+               struct command_context_s *cmd_ctx,
+               char **args, etmv1_tracemode_t *mode)
 {
-       target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
        etmv1_tracemode_t tracemode;
 
-       target = get_current_target(cmd_ctx);
+       /* what parts of data access are traced? */
+       if (strcmp(args[0], "none") == 0)
+               tracemode = ETMV1_TRACE_NONE;
+       else if (strcmp(args[0], "data") == 0)
+               tracemode = ETMV1_TRACE_DATA;
+       else if (strcmp(args[0], "address") == 0)
+               tracemode = ETMV1_TRACE_ADDR;
+       else if (strcmp(args[0], "all") == 0)
+               tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
+       else
+       {
+               command_print(cmd_ctx, "invalid option '%s'", args[0]);
+               return ERROR_INVALID_ARGUMENTS;
+       }
 
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       uint8_t context_id;
+       COMMAND_PARSE_NUMBER(u8, args[1], context_id);
+       switch (context_id)
+       {
+       case 0:
+               tracemode |= ETMV1_CONTEXTID_NONE;
+               break;
+       case 8:
+               tracemode |= ETMV1_CONTEXTID_8;
+               break;
+       case 16:
+               tracemode |= ETMV1_CONTEXTID_16;
+               break;
+       case 32:
+               tracemode |= ETMV1_CONTEXTID_32;
+               break;
+       default:
+               command_print(cmd_ctx, "invalid option '%s'", args[1]);
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       if (strcmp(args[2], "enable") == 0)
+               tracemode |= ETMV1_CYCLE_ACCURATE;
+       else if (strcmp(args[2], "disable") == 0)
+               tracemode |= 0;
+       else
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "invalid option '%s'", args[2]);
+               return ERROR_INVALID_ARGUMENTS;
        }
 
-       if (!arm7_9->etm_ctx)
+       if (strcmp(args[3], "enable") == 0)
+               tracemode |= ETMV1_BRANCH_OUTPUT;
+       else if (strcmp(args[3], "disable") == 0)
+               tracemode |= 0;
+       else
        {
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               command_print(cmd_ctx, "invalid option '%s'", args[3]);
+               return ERROR_INVALID_ARGUMENTS;
        }
 
-       tracemode = arm7_9->etm_ctx->tracemode;
+       /* IGNORED:
+        *  - CPRT tracing (coprocessor register transfers)
+        *  - debug request (causes debug entry on trigger)
+        *  - stall on FIFOFULL (preventing tracedata lossage)
+        */
+       *mode = tracemode;
 
-       if (argc == 4)
-       {
-               if (strcmp(args[0], "none") == 0)
-               {
-                       tracemode = ETMV1_TRACE_NONE;
-               }
-               else if (strcmp(args[0], "data") == 0)
-               {
-                       tracemode = ETMV1_TRACE_DATA;
-               }
-               else if (strcmp(args[0], "address") == 0)
-               {
-                       tracemode = ETMV1_TRACE_ADDR;
-               }
-               else if (strcmp(args[0], "all") == 0)
-               {
-                       tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
-               }
-               else
-               {
-                       command_print(cmd_ctx, "invalid option '%s'", args[0]);
-                       return ERROR_OK;
-               }
+       return ERROR_OK;
+}
 
-               switch (strtol(args[1], NULL, 0))
-               {
-                       case 0:
-                               tracemode |= ETMV1_CONTEXTID_NONE;
-                               break;
-                       case 8:
-                               tracemode |= ETMV1_CONTEXTID_8;
-                               break;
-                       case 16:
-                               tracemode |= ETMV1_CONTEXTID_16;
-                               break;
-                       case 32:
-                               tracemode |= ETMV1_CONTEXTID_32;
-                               break;
-                       default:
-                               command_print(cmd_ctx, "invalid option '%s'", args[1]);
-                               return ERROR_OK;
-               }
+static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       struct arm *arm = target_to_arm(target);
+       struct etm *etm;
 
-               if (strcmp(args[2], "enable") == 0)
-               {
-                       tracemode |= ETMV1_CYCLE_ACCURATE;
-               }
-               else if (strcmp(args[2], "disable") == 0)
-               {
-                       tracemode |= 0;
-               }
-               else
-               {
-                       command_print(cmd_ctx, "invalid option '%s'", args[2]);
-                       return ERROR_OK;
-               }
+       if (!is_arm(arm)) {
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
+       }
 
-               if (strcmp(args[3], "enable") == 0)
-               {
-                       tracemode |= ETMV1_BRANCH_OUTPUT;
-               }
-               else if (strcmp(args[3], "disable") == 0)
-               {
-                       tracemode |= 0;
-               }
-               else
-               {
-                       command_print(cmd_ctx, "invalid option '%s'", args[2]);
-                       return ERROR_OK;
-               }
+       etm = arm->etm;
+       if (!etm) {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_FAIL;
        }
-       else if (argc != 0)
+
+       etmv1_tracemode_t tracemode = etm->tracemode;
+
+       switch (argc)
        {
-               command_print(cmd_ctx, "usage: configure trace mode <none | data | address | all> <context id bits> <cycle accurate> <branch output>");
-               return ERROR_OK;
+       case 0:
+               break;
+       case 4:
+               handle_etm_tracemode_command_update(cmd_ctx, args, &tracemode);
+               break;
+       default:
+               command_print(cmd_ctx, "usage: configure trace mode "
+                               "<none | data | address | all> "
+                               "<context id bits> <cycle accurate> <branch output>");
+               return ERROR_FAIL;
        }
 
+       /**
+        * todo: fail if parameters were invalid for this hardware,
+        * or couldn't be written; display actual hardware state...
+        */
+
        command_print(cmd_ctx, "current tracemode configuration:");
 
        switch (tracemode & ETMV1_TRACE_MASK)
@@ -1307,13 +1317,13 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char
        }
 
        /* only update ETM_CTRL register if tracemode changed */
-       if (arm7_9->etm_ctx->tracemode != tracemode)
+       if (etm->tracemode != tracemode)
        {
                reg_t *etm_ctrl_reg;
 
-               etm_ctrl_reg = etm_reg_lookup(arm7_9->etm_ctx, ETM_CTRL);
+               etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL);
                if (!etm_ctrl_reg)
-                       return ERROR_OK;
+                       return ERROR_FAIL;
 
                etm_get_reg(etm_ctrl_reg);
 
@@ -1323,52 +1333,50 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char
                buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);
                etm_store_reg(etm_ctrl_reg);
 
-               arm7_9->etm_ctx->tracemode = tracemode;
+               etm->tracemode = tracemode;
 
                /* invalidate old trace data */
-               arm7_9->etm_ctx->capture_status = TRACE_IDLE;
-               if (arm7_9->etm_ctx->trace_depth > 0)
+               etm->capture_status = TRACE_IDLE;
+               if (etm->trace_depth > 0)
                {
-                       free(arm7_9->etm_ctx->trace_data);
-                       arm7_9->etm_ctx->trace_data = NULL;
+                       free(etm->trace_data);
+                       etm->trace_data = NULL;
                }
-               arm7_9->etm_ctx->trace_depth = 0;
+               etm->trace_depth = 0;
        }
 
        return ERROR_OK;
 }
 
-static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_config_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_portmode_t portmode = 0x0;
-       etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));
+       struct etm *etm_ctx;
        int i;
 
        if (argc != 5)
-       {
-               free(etm_ctx);
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
        target = get_target(args[0]);
        if (!target)
        {
                LOG_ERROR("target '%s' not defined", args[0]);
-               free(etm_ctx);
                return ERROR_FAIL;
        }
 
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-       {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               free(etm_ctx);
+       arm = target_to_arm(target);
+       if (!is_arm(arm)) {
+               command_print(cmd_ctx, "target '%s' is '%s'; not an ARM",
+                               target->cmd_name, target_get_name(target));
                return ERROR_FAIL;
        }
 
-       switch (strtoul(args[1], NULL, 0))
+       uint8_t port_width;
+       COMMAND_PARSE_NUMBER(u8, args[1], port_width);
+       switch (port_width)
        {
                case 4:
                        portmode |= ETM_PORT_4BIT;
@@ -1381,7 +1389,6 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cm
                        break;
                default:
                        command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);
-                       free(etm_ctx);
                        return ERROR_FAIL;
        }
 
@@ -1400,7 +1407,6 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cm
        else
        {
                command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);
-               free(etm_ctx);
                return ERROR_FAIL;
        }
 
@@ -1415,7 +1421,12 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cm
        else
        {
                command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);
-               free(etm_ctx);
+               return ERROR_FAIL;
+       }
+
+       etm_ctx = calloc(1, sizeof(etm_context_t));
+       if (!etm_ctx) {
+               LOG_DEBUG("out of memory");
                return ERROR_FAIL;
        }
 
@@ -1447,22 +1458,10 @@ static int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cm
        etm_ctx->target = target;
        etm_ctx->trigger_percent = 50;
        etm_ctx->trace_data = NULL;
-       etm_ctx->trace_depth = 0;
        etm_ctx->portmode = portmode;
-       etm_ctx->tracemode = 0x0;
        etm_ctx->core_state = ARMV4_5_STATE_ARM;
-       etm_ctx->image = NULL;
-       etm_ctx->pipe_index = 0;
-       etm_ctx->data_index = 0;
-       etm_ctx->current_pc = 0x0;
-       etm_ctx->pc_ok = 0;
-       etm_ctx->last_branch = 0x0;
-       etm_ctx->last_branch_reason = 0x0;
-       etm_ctx->last_ptr = 0x0;
-       etm_ctx->ptr_ok = 0x0;
-       etm_ctx->last_instruction = 0;
-
-       arm7_9->etm_ctx = etm_ctx;
+
+       arm->etm = etm_ctx;
 
        return etm_register_user_commands(cmd_ctx);
 }
@@ -1471,54 +1470,52 @@ static int handle_etm_info_command(struct command_context_s *cmd_ctx,
                char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm;
        reg_t *etm_sys_config_reg;
-
        int max_port_size;
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       etm = arm7_9->etm_ctx;
+       etm = arm->etm;
        if (!etm)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        command_print(cmd_ctx, "ETM v%d.%d",
                        etm->bcd_vers >> 4, etm->bcd_vers & 0xf);
        command_print(cmd_ctx, "pairs of address comparators: %i",
-                       (etm->config >> 0) & 0x0f);
+                       (int) (etm->config >> 0) & 0x0f);
        command_print(cmd_ctx, "data comparators: %i",
-                       (etm->config >> 4) & 0x0f);
+                       (int) (etm->config >> 4) & 0x0f);
        command_print(cmd_ctx, "memory map decoders: %i",
-                       (etm->config >> 8) & 0x1f);
+                       (int) (etm->config >> 8) & 0x1f);
        command_print(cmd_ctx, "number of counters: %i",
-                       (etm->config >> 13) & 0x07);
+                       (int) (etm->config >> 13) & 0x07);
        command_print(cmd_ctx, "sequencer %spresent",
-                       (etm->config & (1 << 16)) ? "" : "not ");
+                       (int) (etm->config & (1 << 16)) ? "" : "not ");
        command_print(cmd_ctx, "number of ext. inputs: %i",
-                       (etm->config >> 17) & 0x07);
+                       (int) (etm->config >> 17) & 0x07);
        command_print(cmd_ctx, "number of ext. outputs: %i",
-                       (etm->config >> 20) & 0x07);
+                       (int) (etm->config >> 20) & 0x07);
        command_print(cmd_ctx, "FIFO full %spresent",
-                       (etm->config & (1 << 23)) ? "" : "not ");
+                       (int) (etm->config & (1 << 23)) ? "" : "not ");
        if (etm->bcd_vers < 0x20)
                command_print(cmd_ctx, "protocol version: %i",
-                               (etm->config >> 28) & 0x07);
+                               (int) (etm->config >> 28) & 0x07);
        else {
                command_print(cmd_ctx, "trace start/stop %spresent",
                                (etm->config & (1 << 26)) ? "" : "not ");
                command_print(cmd_ctx, "number of context comparators: %i",
-                               (etm->config >> 24) & 0x03);
+                               (int) (etm->config >> 24) & 0x03);
        }
 
        /* SYS_CONFIG isn't present before ETMv1.2 */
@@ -1541,7 +1538,7 @@ static int handle_etm_info_command(struct command_context_s *cmd_ctx,
                        break;
                default:
                        LOG_ERROR("Illegal max_port_size");
-                       exit(-1);
+                       return ERROR_FAIL;
        }
        command_print(cmd_ctx, "max. port size: %i", max_port_size);
 
@@ -1561,79 +1558,109 @@ static int handle_etm_info_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_status_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
+       etm_context_t *etm;
        trace_status_t trace_status;
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!arm7_9->etm_ctx)
+       etm = arm->etm;
+       if (!etm)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
-       trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);
+       /* ETM status */
+       if (etm->bcd_vers >= 0x11) {
+               reg_t *reg;
 
+               reg = etm_reg_lookup(etm, ETM_STATUS);
+               if (!reg)
+                       return ERROR_FAIL;
+               if (etm_get_reg(reg) == ERROR_OK) {
+                       unsigned s = buf_get_u32(reg->value, 0, reg->size);
+
+                       command_print(cmd_ctx, "etm: %s%s%s%s",
+                               /* bit(1) == progbit */
+                               (etm->bcd_vers >= 0x12)
+                                       ? ((s & (1 << 1))
+                                               ? "disabled" : "enabled")
+                                       : "?",
+                               ((s & (1 << 3)) && etm->bcd_vers >= 0x31)
+                                       ? " triggered" : "",
+                               ((s & (1 << 2)) && etm->bcd_vers >= 0x12)
+                                       ? " start/stop" : "",
+                               ((s & (1 << 0)) && etm->bcd_vers >= 0x11)
+                                       ? " untraced-overflow" : "");
+               } /* else ignore and try showing trace port status */
+       }
+
+       /* Trace Port Driver status */
+       trace_status = etm->capture_driver->status(etm);
        if (trace_status == TRACE_IDLE)
        {
-               command_print(cmd_ctx, "tracing is idle");
+               command_print(cmd_ctx, "%s: idle", etm->capture_driver->name);
        }
        else
        {
                static char *completed = " completed";
                static char *running = " is running";
-               static char *overflowed = ", trace overflowed";
-               static char *triggered = ", trace triggered";
+               static char *overflowed = ", overflowed";
+               static char *triggered = ", triggered";
 
-               command_print(cmd_ctx, "trace collection%s%s%s",
+               command_print(cmd_ctx, "%s: trace collection%s%s%s",
+                       etm->capture_driver->name,
                        (trace_status & TRACE_RUNNING) ? running : completed,
                        (trace_status & TRACE_OVERFLOWED) ? overflowed : "",
                        (trace_status & TRACE_TRIGGERED) ? triggered : "");
 
-               if (arm7_9->etm_ctx->trace_depth > 0)
+               if (etm->trace_depth > 0)
                {
-                       command_print(cmd_ctx, "%i frames of trace data read", (int)(arm7_9->etm_ctx->trace_depth));
+                       command_print(cmd_ctx, "%i frames of trace data read",
+                                       (int)(etm->trace_depth));
                }
        }
 
        return ERROR_OK;
 }
 
-static int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_image_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
 
        if (argc < 1)
        {
                command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (etm_ctx->image)
@@ -1651,7 +1678,7 @@ static int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd
        if (argc >= 2)
        {
                etm_ctx->image->base_address_set = 1;
-               etm_ctx->image->base_address = strtoul(args[1], NULL, 0);
+               COMMAND_PARSE_NUMBER(int, args[1], etm_ctx->image->base_address);
        }
        else
        {
@@ -1662,39 +1689,40 @@ static int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd
        {
                free(etm_ctx->image);
                etm_ctx->image = NULL;
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        return ERROR_OK;
 }
 
-static int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_dump_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        fileio_t file;
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
        uint32_t i;
 
        if (argc != 1)
        {
                command_print(cmd_ctx, "usage: etm dump <file>");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (etm_ctx->capture_driver->status == TRACE_IDLE)
@@ -1707,7 +1735,7 @@ static int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd,
        {
                /* TODO: if on-the-fly capture is to be supported, this needs to be changed */
                command_print(cmd_ctx, "trace capture not completed");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        /* read the trace data if it wasn't read already */
@@ -1716,7 +1744,7 @@ static int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd,
 
        if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        fileio_write_u32(&file, etm_ctx->capture_status);
@@ -1736,51 +1764,52 @@ static int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd,
        return ERROR_OK;
 }
 
-static int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_load_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        fileio_t file;
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
        uint32_t i;
 
        if (argc != 1)
        {
                command_print(cmd_ctx, "usage: etm load <file>");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
        {
                command_print(cmd_ctx, "trace capture running, stop first");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
        {
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (file.size % 4)
        {
                command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");
                fileio_close(&file);
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (etm_ctx->trace_depth > 0)
@@ -1801,7 +1830,7 @@ static int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd,
        {
                command_print(cmd_ctx, "not enough memory to perform operation");
                fileio_close(&file);
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        for (i = 0; i < etm_ctx->trace_depth; i++)
@@ -1820,30 +1849,32 @@ static int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd,
        return ERROR_OK;
 }
 
-static int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if (argc > 0)
        {
-               uint32_t new_value = strtoul(args[0], NULL, 0);
+               uint32_t new_value;
+               COMMAND_PARSE_NUMBER(u32, args[0], new_value);
 
                if ((new_value < 2) || (new_value > 100))
                {
@@ -1860,40 +1891,41 @@ static int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-static int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_start_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
        reg_t *etm_ctrl_reg;
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        /* invalidate old tracing data */
-       arm7_9->etm_ctx->capture_status = TRACE_IDLE;
-       if (arm7_9->etm_ctx->trace_depth > 0)
+       etm_ctx->capture_status = TRACE_IDLE;
+       if (etm_ctx->trace_depth > 0)
        {
-               free(arm7_9->etm_ctx->trace_data);
-               arm7_9->etm_ctx->trace_data = NULL;
+               free(etm_ctx->trace_data);
+               etm_ctx->trace_data = NULL;
        }
-       arm7_9->etm_ctx->trace_depth = 0;
+       etm_ctx->trace_depth = 0;
 
        etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
        if (!etm_ctrl_reg)
-               return ERROR_OK;
+               return ERROR_FAIL;
 
        etm_get_reg(etm_ctrl_reg);
 
@@ -1908,31 +1940,32 @@ static int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd
        return ERROR_OK;
 }
 
-static int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_stop_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
        reg_t *etm_ctrl_reg;
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
        if (!etm_ctrl_reg)
-               return ERROR_OK;
+               return ERROR_FAIL;
 
        etm_get_reg(etm_ctrl_reg);
 
@@ -1947,26 +1980,27 @@ static int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd,
        return ERROR_OK;
 }
 
-static int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_etm_analyze_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
        target_t *target;
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
+       struct arm *arm;
        etm_context_t *etm_ctx;
        int retval;
 
        target = get_current_target(cmd_ctx);
-
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       arm = target_to_arm(target);
+       if (!is_arm(arm))
        {
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-               return ERROR_OK;
+               command_print(cmd_ctx, "ETM: current target isn't an ARM");
+               return ERROR_FAIL;
        }
 
-       if (!(etm_ctx = arm7_9->etm_ctx))
+       etm_ctx = arm->etm;
+       if (!etm_ctx)
        {
                command_print(cmd_ctx, "current target doesn't have an ETM configured");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
 
        if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)
@@ -1987,7 +2021,7 @@ static int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *c
                }
        }
 
-       return ERROR_OK;
+       return retval;
 }
 
 int etm_register_commands(struct command_context_s *cmd_ctx)

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)