Add private src/jtag/interface.h for use by JTAG interface drivers:
[openocd.git] / src / jtag / jtag.h
index 434320b49546b5e119f7911b697b971366b39d0a..a2755022c634675283ce2f27bf17fa619c644b88 100644 (file)
 #ifndef JTAG_H
 #define JTAG_H
 
-#include "types.h"
 #include "binarybuffer.h"
 #include "log.h"
 
-#include "command.h"
-
 
 #ifdef _DEBUG_JTAG_IO_
 #define DEBUG_JTAG_IO(expr ...)                LOG_DEBUG(expr)
@@ -108,159 +105,29 @@ typedef struct tap_transition_s
 //extern tap_transition_t tap_transitions[16];    /* describe the TAP state diagram */
 
 
-/*-----<Cable Helper API>-------------------------------------------*/
-
-/* The "Cable Helper API" is what the cable drivers can use to help implement
- * their "Cable API".  So a Cable Helper API is a set of helper functions used by
- * cable drivers, and this is different from a Cable API.  A "Cable API" is what
- * higher level code used to talk to a cable.
- */
-
-
-/** implementation of wrapper function tap_set_state() */
-void tap_set_state_impl(tap_state_t new_state);
-
-/**
- * Function tap_set_state
- * sets the state of a "state follower" which tracks the state of the TAPs connected to the
- * cable.  The state follower is hopefully always in the same state as the actual
- * TAPs in the jtag chain, and will be so if there are no bugs in the tracking logic within that
- * cable driver. All the cable drivers call this function to indicate the state they think
- * the TAPs attached to their cables are in.  Because this function can also log transitions,
- * it will be helpful to call this function with every transition that the TAPs being manipulated
- * are expected to traverse, not just end points of a multi-step state path.
- * @param new_state is the state we think the TAPs are currently in or are about to enter.
- */
-#if defined(_DEBUG_JTAG_IO_)
-#define tap_set_state(new_state) \
-       do { \
-               LOG_DEBUG( "tap_set_state(%s)", tap_state_name(new_state) ); \
-               tap_set_state_impl(new_state); \
-       } while (0)
-#else
-static inline void tap_set_state(tap_state_t new_state)
-{
-       tap_set_state_impl(new_state);
-}
-
-#endif
-
-/**
- * Function tap_get_state
- * gets the state of the "state follower" which tracks the state of the TAPs connected to
- * the cable.
- * @see tap_set_state
- * @return tap_state_t - The state the TAPs are in now.
- */
-tap_state_t tap_get_state(void);
-
-/**
- * Function tap_set_end_state
- * sets the state of an "end state follower" which tracks the state that any cable driver
- * thinks will be the end (resultant) state of the current TAP SIR or SDR operation.  At completion
- * of that TAP operation this value is copied into the state follower via tap_set_state().
- * @param new_end_state is that state the TAPs should enter at completion of a pending TAP operation.
- */
-void        tap_set_end_state(tap_state_t new_end_state);
-
-/**
- * Function tap_get_end_state
- * @see tap_set_end_state
- * @return tap_state_t - The state the TAPs should be in at completion of the current TAP operation.
- */
-tap_state_t tap_get_end_state(void);
-
-/**
- * Function tap_get_tms_path
- * returns a 7 bit long "bit sequence" indicating what has to be done with TMS
- * during a sequence of seven TAP clock cycles in order to get from
- * state \a "from" to state \a "to".
- * @param from is the starting state
- * @param to is the resultant or final state
- * @return int - a 7 bit sequence, with the first bit in the sequence at bit 0.
- */
-int tap_get_tms_path(tap_state_t from, tap_state_t to);
-
-/**
- * Function tap_move_ndx
- * when given a stable state, returns an index from 0-5.  The index corresponds to a
- * sequence of stable states which are given in this order: <p>
- * { TAP_RESET, TAP_IDLE, TAP_DRSHIFT, TAP_DRPAUSE, TAP_IRSHIFT, TAP_IRPAUSE }
- * <p>
- * This sequence corresponds to look up tables which are used in some of the
- * cable drivers.
- * @param astate is the stable state to find in the sequence.  If a non stable
- *  state is passed, this may cause the program to output an error message
- *  and terminate.
- * @return int - the array (or sequence) index as described above
- */
-int tap_move_ndx(tap_state_t astate);
-
-/**
- * Function tap_is_state_stable
- * returns true if the \a astate is stable.
- */
-bool tap_is_state_stable(tap_state_t astate);
-
-/**
- * Function tap_state_transition
- * takes a current TAP state and returns the next state according to the tms value.
- * @param current_state is the state of a TAP currently.
- * @param tms is either zero or non-zero, just like a real TMS line in a jtag interface.
- * @return tap_state_t - the next state a TAP would enter.
- */
-tap_state_t tap_state_transition(tap_state_t current_state, bool tms);
-
-/**
- * Function tap_state_name
- * Returns a string suitable for display representing the JTAG tap_state
- */
-const char* tap_state_name(tap_state_t state);
-
-#ifdef _DEBUG_JTAG_IO_
-/**
- * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers.
- * @param tms_buf must points to a buffer containing the TMS bitstream.
- * @param tdi_buf must points to a buffer containing the TDI bitstream.
- * @param tap_len must specify the length of the TMS/TDI bitstreams.
- * @param start_tap_state must specify the current TAP state.
- * @returns the final TAP state; pass as @a start_tap_state in following call.
- */
-tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
-               unsigned tap_len, tap_state_t start_tap_state);
-#else
-static inline tap_state_t jtag_debug_state_machine(const void *tms_buf,
-               const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state)
-{
-       return start_tap_state;
-}
-#endif // _DEBUG_JTAG_IO_
-
-/*-----</Cable Helper API>------------------------------------------*/
-
 
 extern tap_state_t cmd_queue_end_state;         /* finish DR scans in dr_end_state */
 extern tap_state_t cmd_queue_cur_state;         /* current TAP state */
 
-typedef void* error_handler_t;  /* Later on we can delete error_handler_t, but keep it for now to make patches more readable */
-
-struct scan_field_s;
-typedef int (*in_handler_t)(u8* in_value, void* priv, struct scan_field_s* field);
-
 typedef struct scan_field_s
 {
        jtag_tap_t* tap;                /* tap pointer this instruction refers to */
        int         num_bits;           /* number of bits this field specifies (up to 32) */
        u8*         out_value;          /* value to be scanned into the device */
-       u8*         out_mask;           /* only masked bits care */
        u8*         in_value;           /* pointer to a 32-bit memory location to take data scanned out */
-       /* in_check_value/mask, in_handler_error_handler, in_handler_priv can be used by the in handler, otherwise they contain garbage  */
-       u8*          in_check_value;    /* used to validate scan results */
-       u8*          in_check_mask;     /* check specified bits against check_value */
-       in_handler_t in_handler;        /* process received buffer using this handler */
-       void*        in_handler_priv;   /* additional information for the in_handler */
+
+       u8*         check_value;        /* Used together with jtag_add_dr_scan_check() to check data clocked
+                                          in */
+       u8*         check_mask;         /* mask to go with check_value */
+
+       /* internal work space */
+       int                     allocated;                      /* in_value has been allocated for the queue */
+       int                     modified;                       /* did we modify the in_value? */
+       u8                      intmp[4];                       /* temporary storage for checking synchronously */
 } scan_field_t;
 
+#ifdef INCLUDE_JTAG_INTERFACE_H
+
 enum scan_type {
        /* IN: from device to host, OUT: from host to device */
        SCAN_IN = 1, SCAN_OUT = 2, SCAN_IO = 3
@@ -268,7 +135,7 @@ enum scan_type {
 
 typedef struct scan_command_s
 {
-       int           ir_scan;      /* instruction/not data scan */
+       bool          ir_scan;      /* instruction/not data scan */
        int           num_fields;   /* number of fields in *fields array */
        scan_field_t* fields;       /* pointer to an array of data scan fields */
        tap_state_t   end_state;    /* TAP state in which JTAG commands should finish */
@@ -331,7 +198,6 @@ enum jtag_command_type {
        JTAG_STATEMOVE    = 2,
        JTAG_RUNTEST      = 3,
        JTAG_RESET        = 4,
-       JTAG_END_STATE    = 5,
        JTAG_PATHMOVE     = 6,
        JTAG_SLEEP        = 7,
        JTAG_STABLECLOCKS = 8
@@ -346,6 +212,16 @@ typedef struct jtag_command_s
 
 extern jtag_command_t* jtag_command_queue;
 
+extern void* cmd_queue_alloc(size_t size);
+extern void cmd_queue_free(void);
+
+extern void jtag_queue_command(jtag_command_t *cmd);
+extern void jtag_command_queue_reset(void);
+
+#include "interface.h"
+
+#endif // INCLUDE_JTAG_INTERFACE_H
+
 /* forward declaration */
 typedef struct jtag_tap_event_action_s jtag_tap_event_action_t;
 
@@ -376,7 +252,6 @@ struct jtag_tap_s
 };
 extern jtag_tap_t* jtag_AllTaps(void);
 extern jtag_tap_t* jtag_TapByPosition(int n);
-extern jtag_tap_t* jtag_TapByPosition(int n);
 extern jtag_tap_t* jtag_TapByString(const char* dotted_name);
 extern jtag_tap_t* jtag_TapByJimObj(Jim_Interp* interp, Jim_Obj* obj);
 extern jtag_tap_t* jtag_TapByAbsPosition(int abs_position);
@@ -416,55 +291,6 @@ enum reset_line_mode {
        LINE_PUSH_PULL  = 0x1,
 };
 
-typedef struct jtag_interface_s
-{
-       char* name;
-
-       /* queued command execution
-        */
-       int (*execute_queue)(void);
-
-       /* interface initalization
-        */
-       int (*speed)(int speed);
-       int (*register_commands)(struct command_context_s* cmd_ctx);
-       int (*init)(void);
-       int (*quit)(void);
-
-       /* returns JTAG maxium speed for KHz. 0=RTCK. The function returns
-        *  a failure if it can't support the KHz/RTCK.
-        *
-        *  WARNING!!!! if RTCK is *slow* then think carefully about
-        *  whether you actually want to support this in the driver.
-        *  Many target scripts are written to handle the absence of RTCK
-        *  and use a fallback kHz TCK.
-        */
-       int (*khz)(int khz, int* jtag_speed);
-
-       /* returns the KHz for the provided JTAG speed. 0=RTCK. The function returns
-        *  a failure if it can't support the KHz/RTCK. */
-       int (*speed_div)(int speed, int* khz);
-
-       /* Read and clear the power dropout flag. Note that a power dropout
-        *  can be transitionary, easily much less than a ms.
-        *
-        *  So to find out if the power is *currently* on, you must invoke
-        *  this method twice. Once to clear the power dropout flag and a
-        *  second time to read the current state.
-        *
-        *  Currently the default implementation is never to detect power dropout.
-        */
-       int (*power_dropout)(int* power_dropout);
-
-       /* Read and clear the srst asserted detection flag.
-        *
-        * NB!!!! like power_dropout this does *not* read the current
-        * state. srst assertion is transitionary and *can* be much
-        * less than 1ms.
-        */
-       int (*srst_asserted)(int* srst_asserted);
-} jtag_interface_t;
-
 enum jtag_event {
        JTAG_TRST_ASSERTED
 };
@@ -497,8 +323,6 @@ typedef struct jtag_event_callback_s
 
 extern jtag_event_callback_t* jtag_event_callbacks;
 
-extern jtag_interface_t*      jtag; /* global pointer to configured JTAG interface */
-
 extern int jtag_speed;
 extern int jtag_speed_post_reset;
 
@@ -520,6 +344,9 @@ extern enum reset_types jtag_reset_config;
  */
 extern int  jtag_interface_init(struct command_context_s* cmd_ctx);
 
+/// Shutdown the JTAG interface upon program exit.
+extern int  jtag_interface_quit(void);
+
 /* initialize JTAG chain using only a RESET reset. If init fails,
  * try reset + init.
  */
@@ -542,21 +369,101 @@ extern int  jtag_register_commands(struct command_context_s* cmd_ctx);
  *
  */
 extern void jtag_add_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_plain_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_plain_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_plain_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_plain_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
+/* same as jtag_add_ir_scan except no verify is performed */
+extern void jtag_add_ir_scan_noverify(int num_fields, const scan_field_t *fields, tap_state_t state);
+extern void jtag_add_dr_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+
+/* set in_value to point to 32 bits of memory to scan into. This function
+ * is a way to handle the case of synchronous and asynchronous
+ * JTAG queues.
+ *
+ * In the event of an asynchronous queue execution the queue buffer
+ * allocation method is used, for the synchronous case the temporary 32 bits come
+ * from the input field itself.
+ */
+extern void jtag_alloc_in_value32(scan_field_t *field);
+
+/* This version of jtag_add_dr_scan() uses the check_value/mask fields */
+extern void jtag_add_dr_scan_check(int num_fields, scan_field_t* fields, tap_state_t endstate);
+extern void jtag_add_plain_ir_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+extern void jtag_add_plain_dr_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+
+
+/* Simplest/typical callback - do some conversion on the data clocked in.
+ * This callback is for such conversion that can not fail.
+ * For conversion types or checks that can
+ * fail, use the jtag_callback_t variant */
+typedef void (*jtag_callback1_t)(u8 *in);
+
+/* A simpler version of jtag_add_callback4 */
+extern void jtag_add_callback(jtag_callback1_t, u8 *in);
+
+
+/* This type can store an integer safely by a normal cast on 64 and
+ * 32 bit systems. */
+typedef intptr_t jtag_callback_data_t;
+
+/* The generic callback mechanism.
+ *
+ * The callback is invoked with three arguments. The first argument is
+ * the pointer to the data clocked in.
+ */
+typedef int (*jtag_callback_t)(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3);
+
+
+/* This callback can be executed immediately the queue has been flushed. Note that
+ * the JTAG queue can either be executed synchronously or asynchronously. Typically
+ * for USB the queue is executed asynchronously. For low latency interfaces, the
+ * queue may be executed synchronously.
+ *
+ * These callbacks are typically executed *after* the *entire* JTAG queue has been
+ * executed for e.g. USB interfaces.
+ *
+ * The callbacks are guaranteeed to be invoked in the order that they were queued.
+ *
+ * The strange name is due to C's lack of overloading using function arguments
+ *
+ * The callback mechansim is very general and does not really make any assumptions
+ * about what the callback does and what the arguments are.
+ *
+ * in - typically used to point to the data to operate on. More often than not
+ * this will be the data clocked in during a shift operation
+ *
+ * data1 - an integer that is big enough to be used either as an 'int' or
+ * cast to/from a pointer
+ *
+ * data2 - an integer that is big enough to be used either as an 'int' or
+ * cast to/from a pointer
+ *
+ * Why stop at 'data2' for arguments? Somewhat historical reasons. This is
+ * sufficient to implement the jtag_check_value_mask(), besides the
+ * line is best drawn somewhere...
+ *
+ * If the execution of the queue fails before the callbacks, then the
+ * callbacks may or may not be invoked depending on driver implementation.
+ */
+extern void jtag_add_callback4(jtag_callback_t, u8 *in,
+               jtag_callback_data_t data1, jtag_callback_data_t data2,
+               jtag_callback_data_t data3);
+
 
 /* run a TAP_RESET reset. End state is TAP_RESET, regardless
  * of start state.
  */
 extern void jtag_add_tlr(void);
-extern int  interface_jtag_add_tlr(void);
 
-/* Do not use jtag_add_pathmove() unless you need to, but do use it
+/* Application code *must* assume that interfaces will
+ * implement transitions between states with different
+ * paths and path lengths through the state diagram. The
+ * path will vary across interface and also across versions
+ * of the same interface over time. Even if the OpenOCD code
+ * is unchanged, the actual path taken may vary over time
+ * and versions of interface firmware or PCB revisions.
+ *
+ * Use jtag_add_pathmove() when specific transition sequences
+ * are required.
+ *
+ * Do not use jtag_add_pathmove() unless you need to, but do use it
  * if you have to.
  *
  * DANGER! If the target is dependent upon a particular sequence
@@ -586,8 +493,7 @@ extern int  interface_jtag_add_tlr(void);
  * a partial implementation of pathmove would have little practical
  * application.
  */
-extern void jtag_add_pathmove(int num_states, tap_state_t* path);
-extern int  interface_jtag_add_pathmove(int num_states, tap_state_t* path);
+extern void jtag_add_pathmove(int num_states, const tap_state_t* path);
 
 /* go to TAP_IDLE, if we're not already there and cycle
  * precisely num_cycles in the TAP_IDLE after which move
@@ -597,7 +503,6 @@ extern int  interface_jtag_add_pathmove(int num_states, tap_state_t* path);
  * to endstate via TAP_IDLE
  */
 extern void jtag_add_runtest(int num_cycles, tap_state_t endstate);
-extern int  interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
 
 /* A reset of the TAP state machine can be requested.
  *
@@ -623,18 +528,8 @@ extern int  interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
  */
 extern void jtag_add_reset(int req_tlr_or_trst, int srst);
 
-/* this drives the actual srst and trst pins. srst will always be 0
- * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for
- * trst.
- *
- * the higher level jtag_add_reset will invoke jtag_add_tlr() if
- * approperiate
- */
-extern int  interface_jtag_add_reset(int trst, int srst);
 extern void jtag_add_end_state(tap_state_t endstate);
-extern int  interface_jtag_add_end_state(tap_state_t endstate);
 extern void jtag_add_sleep(u32 us);
-extern int  interface_jtag_add_sleep(u32 us);
 
 
 /**
@@ -643,7 +538,6 @@ extern int  interface_jtag_add_sleep(u32 us);
  * stable, then queues up clock_count clocks for transmission.
  */
 void jtag_add_clocks(int num_cycles);
-int  interface_jtag_add_clocks(int num_cycles);
 
 
 /*
@@ -668,17 +562,45 @@ int  interface_jtag_add_clocks(int num_cycles);
  */
 extern int            jtag_execute_queue(void);
 
+/* same as jtag_execute_queue() but does not clear the error flag */
+extern void jtag_execute_queue_noclear(void);
+
+/* this flag is set when an error occurs while executing the queue. cleared
+ * by jtag_execute_queue()
+ *
+ * this flag can also be set from application code if some error happens
+ * during processing that should be reported during jtag_execute_queue().
+ */
+extern int jtag_error;
+
+static __inline__ void jtag_set_error(int error)
+{
+       if ((error==ERROR_OK)||(jtag_error!=ERROR_OK))
+       {
+               /* keep first error */
+               return;
+       }
+       jtag_error=error;
+}
+
+
+
 /* can be implemented by hw+sw */
-extern int            interface_jtag_execute_queue(void);
 extern int            jtag_power_dropout(int* dropout);
 extern int            jtag_srst_asserted(int* srst_asserted);
 
 /* JTAG support functions */
-extern void           jtag_set_check_value(scan_field_t* field, u8* value, u8* mask, error_handler_t* in_error_handler);
-extern enum scan_type jtag_scan_type(scan_command_t* cmd);
-extern int            jtag_scan_size(scan_command_t* cmd);
-extern int            jtag_read_buffer(u8* buffer, scan_command_t* cmd);
-extern int            jtag_build_buffer(scan_command_t* cmd, u8** buffer);
+
+/* execute jtag queue and check value and use mask if mask is != NULL. invokes
+ * jtag_set_error() with any error. */
+extern void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask);
+
+#ifdef INCLUDE_JTAG_INTERFACE_H
+extern enum scan_type jtag_scan_type(const scan_command_t* cmd);
+extern int            jtag_scan_size(const scan_command_t* cmd);
+extern int            jtag_read_buffer(u8* buffer, const scan_command_t* cmd);
+extern int            jtag_build_buffer(const scan_command_t* cmd, u8** buffer);
+#endif // INCLUDE_JTAG_INTERFACE_H
 
 extern void           jtag_sleep(u32 us);
 extern int            jtag_call_event_callbacks(enum jtag_event event);
@@ -699,16 +621,10 @@ void jtag_tap_handle_event(jtag_tap_t* tap, enum jtag_tap_event e);
 #define ERROR_JTAG_NOT_STABLE_STATE  (-105)
 #define ERROR_JTAG_DEVICE_ERROR      (-107)
 
-
-/* this allows JTAG devices to implement the entire jtag_xxx() layer in hw/sw */
-#ifdef HAVE_JTAG_MINIDRIVER_H
-/* Here a #define MINIDRIVER() and an inline version of hw fifo interface_jtag_add_dr_out can be defined */
-#include "jtag_minidriver.h"
-#define MINIDRIVER(a) notused ## a
-#else
-#define MINIDRIVER(a) a
-
-/* jtag_add_dr_out() is a faster version of jtag_add_dr_scan()
+/* jtag_add_dr_out() is a version of jtag_add_dr_scan() which
+ * only scans data out. It operates on 32 bit integers instead
+ * of 8 bit, which makes it a better impedance match with
+ * the calling code which often operate on 32 bit integers.
  *
  * Current or end_state can not be TAP_RESET. end_state can be TAP_INVALID
  *
@@ -723,21 +639,24 @@ void jtag_tap_handle_event(jtag_tap_t* tap, enum jtag_tap_event e);
  * return an error. There is no way to determine if there was a failure
  * during this function call.
  *
- * Note that this jtag_add_dr_out can be defined as an inline function.
+ * This is an inline fn to speed up embedded hosts. Also note that
+ * interface_jtag_add_dr_out() can be a *small* inline function for
+ * embedded hosts.
+ *
+ * There is no jtag_add_dr_outin() version of this fn that also allows
+ * clocking data back in. Patches gladly accepted!
  */
-extern void interface_jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
+extern void jtag_add_dr_out(jtag_tap_t* tap,
+               int num_fields, const int* num_bits, const u32* value,
                tap_state_t end_state);
 
-#endif
-
-static __inline__ void jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
-               tap_state_t end_state)
-{
-       if (end_state != TAP_INVALID)
-               cmd_queue_end_state = end_state;
-       cmd_queue_cur_state = cmd_queue_end_state;
-       interface_jtag_add_dr_out(tap, num_fields, num_bits, value, cmd_queue_end_state);
-}
 
+/**
+ * Function jtag_add_statemove
+ * moves from the current state to the goal \a state. This needs
+ * to be handled according to the xsvf spec, see the XSTATE command
+ * description.
+ */
+extern int jtag_add_statemove(tap_state_t goal_state);
 
 #endif /* JTAG_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)