Audit and eliminate redundant #include directives in src/{pld,svf,xsvf}.
[openocd.git] / src / xsvf / xsvf.c
index d69c1a9394c45ea2052bf84c18f415e0937cb031..b62de349d5d68466c29e2ba1e879ffffd8bb3e68 100644 (file)
@@ -9,7 +9,7 @@
  *      peter.hettkamp@htp-tel.de                                                                                         *
  *                                                                                                                                                *
  *      Copyright (C) 2009 SoftPLC Corporation. http://softplc.com             *
- *      dick@softplc.com                                                                                                  *
+ *      Dick Hollenbeck <dick@softplc.com>                                                                        *
  *                                                                          *
  *      This program is free software; you can redistribute it and/or modify   *
  *      it under the terms of the GNU General Public License as published by   *
 #endif
 
 #include "xsvf.h"
-
 #include "jtag.h"
-#include "command.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
 
-#include <sys/time.h>
-#include <time.h>
+#include <assert.h>
 
 
 /* XSVF commands, from appendix B of xapp503.pdf  */
@@ -141,7 +130,7 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 static int xsvf_fd = 0;
 
 
-/* map xsvf tap state to an openocd "enum tap_state" */
+/* map xsvf tap state to an openocd "tap_state_t" */
 static tap_state_t xsvf_to_tap( int xsvf_state )
 {
        tap_state_t     ret;
@@ -173,46 +162,92 @@ static tap_state_t xsvf_to_tap( int xsvf_state )
 }
 
 
-/* xsvf has it's own definition of a statemove. This needs
- * to be handled according to the xsvf spec, which has nothing
- * to do with the JTAG spec or OpenOCD as such.
- *
- * Implemented via jtag_add_pathmove().
+/**
+ * Function xsvf_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.
  */
-static void xsvf_add_statemove(tap_state_t state)
+static int xsvf_add_statemove(tap_state_t goal_state)
 {
-       tap_state_t moves[7];   /* max # of transitions */
-       tap_state_t curstate = cmd_queue_cur_state;
+       int retval = ERROR_OK;
+
+       tap_state_t moves[8];
+       tap_state_t cur_state = cmd_queue_cur_state;
        int i;
+       int tms_bits;
+       int     tms_count;
+
+       LOG_DEBUG( "cur_state=%s goal_state=%s",
+               tap_state_name(cur_state),
+               tap_state_name(goal_state) );
 
-       u8 move = TAP_MOVE(cmd_queue_cur_state, state);
 
-       if (state != TAP_RESET  &&  state==cmd_queue_cur_state)
-               return;
+       /*      From the XSVF spec, pertaining to XSTATE:
 
-       if(state==TAP_RESET)
+               For special states known as stable states (Test-Logic-Reset,
+               Run-Test/Idle, Pause-DR, Pause- IR), an XSVF interpreter follows
+               predefined TAP state paths when the starting state is a stable state and
+               when the XSTATE specifies a new stable state (see the STATE command in
+               the [Ref 5] for the TAP state paths between stable states). For
+               non-stable states, XSTATE should specify a state that is only one TAP
+               state transition distance from the current TAP state to avoid undefined
+               TAP state paths. A sequence of multiple XSTATE commands can be issued to
+               transition the TAP through a specific state path.
+       */
+
+       if (goal_state==cur_state )
+               ;       /* nothing to do */
+
+       else if( goal_state==TAP_RESET )
        {
                jtag_add_tlr();
-               return;
        }
 
-       for (i=0; i<7; i++)
+       else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) )
        {
-               int j = (move >> i) & 1;
-               if (j)
-               {
-                       curstate = tap_transitions[curstate].high;
-               }
-               else
+               /*      note: unless tms_bits holds a path that agrees with [Ref 5] in above
+                       spec, then this code is not fully conformant to the xsvf spec.  This
+                       puts a burden on tap_get_tms_path() function from the xsvf spec.
+                       If in doubt, you should confirm that that burden is being met.
+               */
+
+               tms_bits  = tap_get_tms_path(cur_state, goal_state);
+               tms_count = tap_get_tms_path_len(cur_state, goal_state);
+
+               assert( (unsigned) tms_count < DIM(moves) );
+
+               for (i=0;   i<tms_count;   i++, tms_bits>>=1)
                {
-                       curstate = tap_transitions[curstate].low;
+                       bool bit = tms_bits & 1;
+
+                       cur_state = tap_state_transition(cur_state, bit);
+                       moves[i] = cur_state;
                }
-               moves[i] = curstate;
+
+               jtag_add_pathmove(tms_count, moves);
+       }
+
+       /*      else state must be immediately reachable in one clock cycle, and does not
+               need to be a stable state.
+       */
+       else if( tap_state_transition(cur_state, true)  == goal_state
+               ||   tap_state_transition(cur_state, false) == goal_state )
+       {
+               /* move a single state */
+               moves[0] = goal_state;
+               jtag_add_pathmove( 1, moves );
+       }
+
+       else
+       {
+               retval = ERROR_FAIL;
        }
 
-       jtag_add_pathmove(7, moves);
+       return retval;
 }
 
+
 int xsvf_register_commands(struct command_context_s *cmd_ctx)
 {
        register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,
@@ -236,38 +271,6 @@ static int xsvf_read_buffer(int num_bits, int fd, u8* buf)
 }
 
 
-static int xsvf_read_xstates(int fd, tap_state_t *path, int max_path, int *path_len)
-{
-       char c;
-       u8   uc;
-
-       while ((read(fd, &c, 1) > 0) && (c == XSTATE))
-       {
-               tap_state_t     mystate;
-
-               if (*path_len > max_path)
-               {
-                       LOG_WARNING("XSTATE path longer than max_path");
-                       break;
-               }
-               if (read(fd, &uc, 1) < 0)
-               {
-                       return ERROR_XSVF_EOF;
-               }
-
-               mystate = xsvf_to_tap(uc);
-
-               LOG_DEBUG("XSTATE %02X %s", uc, jtag_state_name(mystate) );
-
-               path[(*path_len)++] = mystate;
-       }
-
-       lseek(fd, -1, SEEK_CUR);
-
-       return ERROR_OK;
-}
-
-
 static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        u8 *dr_out_buf = NULL;                          /* from host to device (TDI) */
@@ -352,659 +355,649 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 
                switch (opcode)
                {
-                       case XCOMPLETE:
-                               LOG_DEBUG("XCOMPLETE");
+               case XCOMPLETE:
+                       LOG_DEBUG("XCOMPLETE");
+
+                       result = jtag_execute_queue();
+                       if (result != ERROR_OK)
+                       {
+                               tdo_mismatch = 1;
+                               break;
+                       }
+                       break;
+
+               case XTDOMASK:
+                       LOG_DEBUG("XTDOMASK");
+                       if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
+                               do_abort = 1;
+                       break;
 
-                               result = jtag_execute_queue();
-                               if (result != ERROR_OK)
+               case XRUNTEST:
+                       {
+                               u8      xruntest_buf[4];
+
+                               if (read(xsvf_fd, xruntest_buf, 4) < 0)
                                {
-                                       tdo_mismatch = 1;
+                                       do_abort = 1;
                                        break;
                                }
-                               break;
 
-                       case XTDOMASK:
-                               LOG_DEBUG("XTDOMASK");
-                               if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
-                                       do_abort = 1;
-                               break;
+                               xruntest = be_to_h_u32(xruntest_buf);
+                               LOG_DEBUG("XRUNTEST %d 0x%08X", xruntest, xruntest);
+                       }
+                       break;
 
-                       case XRUNTEST:
+               case XREPEAT:
+                       {
+                               u8 myrepeat;
+
+                               if (read(xsvf_fd, &myrepeat, 1) < 0)
+                                       do_abort = 1;
+                               else
                                {
-                                       u8      xruntest_buf[4];
+                                       xrepeat = myrepeat;
+                                       LOG_DEBUG("XREPEAT %d", xrepeat );
+                               }
+                       }
+                       break;
 
-                                       if (read(xsvf_fd, xruntest_buf, 4) < 0)
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+               case XSDRSIZE:
+                       {
+                               u8      xsdrsize_buf[4];
 
-                                       xruntest = be_to_h_u32(xruntest_buf);
-                                       LOG_DEBUG("XRUNTEST %d 0x%08X", xruntest, xruntest);
+                               if (read(xsvf_fd, xsdrsize_buf, 4) < 0)
+                               {
+                                       do_abort = 1;
+                                       break;
                                }
-                               break;
 
-                       case XREPEAT:
-                               {
-                                       u8 myrepeat;
+                               xsdrsize = be_to_h_u32(xsdrsize_buf);
+                               LOG_DEBUG("XSDRSIZE %d", xsdrsize);
 
-                                       if (read(xsvf_fd, &myrepeat, 1) < 0)
-                                               do_abort = 1;
-                                       else
-                                       {
-                                               xrepeat = myrepeat;
-                                               LOG_DEBUG("XREPEAT %d", xrepeat );
-                                       }
-                               }
-                               break;
+                               if( dr_out_buf ) free(dr_out_buf);
+                               if( dr_in_buf)   free(dr_in_buf);
+                               if( dr_in_mask)  free(dr_in_mask);
+
+                               dr_out_buf = malloc((xsdrsize + 7) / 8);
+                               dr_in_buf = malloc((xsdrsize + 7) / 8);
+                               dr_in_mask = malloc((xsdrsize + 7) / 8);
+                       }
+                       break;
+
+               case XSDR:              /* these two are identical except for the dr_in_buf */
+               case XSDRTDO:
+                       {
+                               int limit = xrepeat;
+                               int     matched = 0;
+                               int attempt;
+
+                               const char* op_name = (opcode == XSDR ? "XSDR" : "XSDRTDO");
 
-                       case XSDRSIZE:
+                               if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
                                {
-                                       u8      xsdrsize_buf[4];
+                                       do_abort = 1;
+                                       break;
+                               }
 
-                                       if (read(xsvf_fd, xsdrsize_buf, 4) < 0)
+                               if (opcode == XSDRTDO)
+                               {
+                                       if(xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf)  != ERROR_OK )
                                        {
                                                do_abort = 1;
                                                break;
                                        }
+                               }
 
-                                       xsdrsize = be_to_h_u32(xsdrsize_buf);
-                                       LOG_DEBUG("XSDRSIZE %d", xsdrsize);
-
-                                       if( dr_out_buf ) free(dr_out_buf);
-                                       if( dr_in_buf)   free(dr_in_buf);
-                                       if( dr_in_mask)  free(dr_in_mask);
+                               if (limit < 1)
+                                       limit = 1;
 
-                                       dr_out_buf = malloc((xsdrsize + 7) / 8);
-                                       dr_in_buf = malloc((xsdrsize + 7) / 8);
-                                       dr_in_mask = malloc((xsdrsize + 7) / 8);
-                               }
-                               break;
+                               LOG_DEBUG("%s %d", op_name, xsdrsize);
 
-                       case XSDR:              /* these two are identical except for the dr_in_buf */
-                       case XSDRTDO:
+                               for( attempt=0; attempt<limit;  ++attempt )
                                {
-                                       int limit = xrepeat;
-                                       int     matched = 0;
-                                       int attempt;
-
-                                       const char* op_name = (opcode == XSDR ? "XSDR" : "XSDRTDO");
+                                       scan_field_t field;
 
-                                       if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
+                                       if( attempt>0 )
                                        {
-                                               do_abort = 1;
-                                               break;
+                                               /* perform the XC9500 exception handling sequence shown in xapp067.pdf and
+                                                  illustrated in psuedo code at end of this file.  We start from state
+                                                  DRPAUSE:
+                                                  go to Exit2-DR
+                                                  go to Shift-DR
+                                                  go to Exit1-DR
+                                                  go to Update-DR
+                                                  go to Run-Test/Idle
+
+                                                  This sequence should be harmless for other devices, and it
+                                                  will be skipped entirely if xrepeat is set to zero.
+                                               */
+
+                                               static tap_state_t exception_path[] = {
+                                                       TAP_DREXIT2,
+                                                       TAP_DRSHIFT,
+                                                       TAP_DREXIT1,
+                                                       TAP_DRUPDATE,
+                                                       TAP_IDLE,
+                                               };
+
+                                               jtag_add_pathmove( DIM(exception_path), exception_path );
+
+                                               if (verbose)
+                                                       LOG_USER("%s mismatch, xsdrsize=%d retry=%d", op_name, xsdrsize, attempt);
                                        }
 
-                                       if (opcode == XSDRTDO)
-                                       {
-                                               if(xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf)  != ERROR_OK )
-                                               {
-                                                       do_abort = 1;
-                                                       break;
-                                               }
-                                       }
+                                       field.tap = tap;
+                                       field.num_bits = xsdrsize;
+                                       field.out_value = dr_out_buf;
+                                       field.in_value = calloc(CEIL(field.num_bits, 8), 1);
 
-                                       if (limit < 1)
-                                               limit = 1;
+                                       if (tap == NULL)
+                                               jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
+                                       else
+                                               jtag_add_dr_scan(1, &field, TAP_DRPAUSE);
 
-                                       LOG_DEBUG("%s %d", op_name, xsdrsize);
+                                       jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
 
-                                       for( attempt=0; attempt<limit;  ++attempt )
-                                       {
-                                               scan_field_t field;
-
-                                               if( attempt>0 )
-                                               {
-                                                       /* perform the XC9500 exception handling sequence shown in xapp067.pdf and
-                                                          illustrated in psuedo code at end of this file.  We start from state
-                                                          DRPAUSE:
-                                                          go to Exit2-DR
-                                                          go to Shift-DR
-                                                          go to Exit1-DR
-                                                          go to Update-DR
-                                                          go to Run-Test/Idle
-
-                                                          This sequence should be harmless for other devices, and it
-                                                          will be skipped entirely if xrepeat is set to zero.
-                                                       */
-
-                                                       static tap_state_t exception_path[] = {
-                                                               TAP_DREXIT2,
-                                                               TAP_DRSHIFT,
-                                                               TAP_DREXIT1,
-                                                               TAP_DRUPDATE,
-                                                               TAP_IDLE,
-                                                       };
-
-                                                       jtag_add_pathmove( sizeof(exception_path)/sizeof(exception_path[0]), exception_path);
-
-                                                       if (verbose)
-                                                               LOG_USER("%s %d retry %d", op_name, xsdrsize, attempt);
-                                               }
-
-                                               field.tap = tap;
-                                               field.num_bits = xsdrsize;
-                                               field.out_value = dr_out_buf;
-                                               field.out_mask = NULL;
-                                               field.in_value = NULL;
-
-                                               jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
-
-                                               if (tap == NULL)
-                                                       jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
-                                               else
-                                                       jtag_add_dr_scan(1, &field, TAP_DRPAUSE);
-
-                                               /* LOG_DEBUG("FLUSHING QUEUE"); */
-                                               result = jtag_execute_queue();
-                                               if (result == ERROR_OK)
-                                               {
-                                                       matched = 1;
-                                                       break;
-                                               }
-                                       }
+                                       free(field.in_value);
 
-                                       if (!matched)
+
+                                       /* LOG_DEBUG("FLUSHING QUEUE"); */
+                                       result = jtag_execute_queue();
+                                       if (result == ERROR_OK)
                                        {
-                                               LOG_USER( "%s mismatch", op_name);
-                                               tdo_mismatch = 1;
+                                               matched = 1;
                                                break;
                                        }
+                               }
 
-                                       /* See page 19 of XSVF spec regarding opcode "XSDR" */
-                                       if (xruntest)
-                                       {
-                                               xsvf_add_statemove(TAP_IDLE);
+                               if (!matched)
+                               {
+                                       LOG_USER( "%s mismatch", op_name);
+                                       tdo_mismatch = 1;
+                                       break;
+                               }
 
-                                               if (runtest_requires_tck)
-                                                       jtag_add_clocks(xruntest);
-                                               else
-                                                       jtag_add_sleep(xruntest);
-                                       }
-                                       else if (xendir != TAP_DRPAUSE) /* we are already in TAP_DRPAUSE */
-                                               xsvf_add_statemove(xenddr);
+                               /* See page 19 of XSVF spec regarding opcode "XSDR" */
+                               if (xruntest)
+                               {
+                                       xsvf_add_statemove(TAP_IDLE);
+
+                                       if (runtest_requires_tck)
+                                               jtag_add_clocks(xruntest);
+                                       else
+                                               jtag_add_sleep(xruntest);
                                }
-                               break;
+                               else if (xendir != TAP_DRPAUSE) /* we are already in TAP_DRPAUSE */
+                                       xsvf_add_statemove(xenddr);
+                       }
+                       break;
 
-                       case XSETSDRMASKS:
-                               LOG_ERROR("unsupported XSETSDRMASKS\n");
-                               unsupported = 1;
-                               break;
+               case XSETSDRMASKS:
+                       LOG_ERROR("unsupported XSETSDRMASKS\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRINC:
-                               LOG_ERROR("unsupported XSDRINC\n");
-                               unsupported = 1;
-                               break;
+               case XSDRINC:
+                       LOG_ERROR("unsupported XSDRINC\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRB:
-                               LOG_ERROR("unsupported XSDRB\n");
-                               unsupported = 1;
-                               break;
+               case XSDRB:
+                       LOG_ERROR("unsupported XSDRB\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRC:
-                               LOG_ERROR("unsupported XSDRC\n");
-                               unsupported = 1;
-                               break;
+               case XSDRC:
+                       LOG_ERROR("unsupported XSDRC\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRE:
-                               LOG_ERROR("unsupported XSDRE\n");
-                               unsupported = 1;
-                               break;
+               case XSDRE:
+                       LOG_ERROR("unsupported XSDRE\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRTDOB:
-                               LOG_ERROR("unsupported XSDRTDOB\n");
-                               unsupported = 1;
-                               break;
+               case XSDRTDOB:
+                       LOG_ERROR("unsupported XSDRTDOB\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRTDOC:
-                               LOG_ERROR("unsupported XSDRTDOC\n");
-                               unsupported = 1;
-                               break;
+               case XSDRTDOC:
+                       LOG_ERROR("unsupported XSDRTDOC\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSDRTDOE:
-                               LOG_ERROR("unsupported XSDRTDOE\n");
-                               unsupported = 1;
-                               break;
+               case XSDRTDOE:
+                       LOG_ERROR("unsupported XSDRTDOE\n");
+                       unsupported = 1;
+                       break;
 
-                       case XSTATE:
+               case XSTATE:
+                       {
+                               tap_state_t     mystate;
+                               u8                      uc;
+
+                               if (read(xsvf_fd, &uc, 1) < 0)
                                {
-                                       tap_state_t     mystate;
-                                       tap_state_t *path;
-                                       int path_len;
+                                       do_abort = 1;
+                                       break;
+                               }
 
-                                       if (read(xsvf_fd, &uc, 1) < 0)
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+                               mystate = xsvf_to_tap(uc);
 
-                                       mystate = xsvf_to_tap(uc);
+                               LOG_DEBUG("XSTATE 0x%02X %s", uc, tap_state_name(mystate) );
 
-                                       LOG_DEBUG("XSTATE 0x%02X %s", uc, jtag_state_name(mystate) );
+                               /*      there is no need for the lookahead code that was here since we
+                                       queue up the jtag commands anyway.  This is a simple way to handle
+                                       the XSTATE.
+                               */
 
-                                       path = calloc(XSTATE_MAX_PATH, 4);
-                                       path_len = 1;
+                               if( xsvf_add_statemove( mystate ) != ERROR_OK )
+                               {
+                                       /*      For special states known as stable states
+                                               (Test-Logic-Reset, Run-Test/Idle, Pause-DR, Pause- IR),
+                                               an XSVF interpreter follows predefined TAP state paths
+                                               when the starting state is a stable state and when the
+                                               XSTATE specifies a new stable state (see the STATE
+                                               command in the [Ref 5] for the TAP state paths between
+                                               stable states). For non-stable states, XSTATE should
+                                               specify a state that is only one TAP state transition
+                                               distance from the current TAP state to avoid undefined
+                                               TAP state paths. A sequence of multiple XSTATE commands
+                                               can be issued to transition the TAP through a specific
+                                               state path.
+                                       */
 
-                                       path[0] = mystate;
-                                       if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)
-                                               do_abort = 1;
-                                       else
-                                       {
-                                               int i,lasti;
-
-                                               /* here the trick is that jtag_add_pathmove() must end in a stable
-                                                * state, so we must only invoke jtag_add_tlr() when we absolutely
-                                                * have to
-                                                */
-                                               for(i=0,lasti=0;  i<path_len;  i++)
-                                               {
-                                                       if(path[i]==TAP_RESET)
-                                                       {
-                                                               if(i>lasti)
-                                                               {
-                                                                       jtag_add_pathmove(i-lasti,path+lasti);
-                                                               }
-                                                               lasti=i+1;
-                                                               jtag_add_tlr();
-                                                       }
-                                               }
-                                               if(i>=lasti)
-                                               {
-                                                       jtag_add_pathmove(i-lasti, path+lasti);
-                                               }
-                                       }
-                                       free(path);
+                                       LOG_ERROR("XSTATE %s is not reachable from current state %s in one clock cycle",
+                                               tap_state_name(mystate),
+                                               tap_state_name(cmd_queue_cur_state)
+                                               );
                                }
+                       }
+                       break;
+
+               case XENDIR:
+
+                       if (read(xsvf_fd, &uc, 1) < 0)
+                       {
+                               do_abort = 1;
+                               break;
+                       }
+
+                       /* see page 22 of XSVF spec */
+                       if( uc == 0 )
+                               xendir = TAP_IDLE;
+                       else if( uc == 1 )
+                               xendir = TAP_IRPAUSE;
+                       else
+                       {
+                               LOG_ERROR("illegial XENDIR argument: 0x%02X", uc);
+                               unsupported = 1;
                                break;
+                       }
 
-                       case XENDIR:
-                               {
-                                       tap_state_t      mystate;
+                       LOG_DEBUG("XENDIR 0x%02X %s", uc, tap_state_name(xendir));
+                       break;
 
-                                       if (read(xsvf_fd, &uc, 1) < 0)
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+               case XENDDR:
 
-                                       /* see page 22 of XSVF spec */
-                                       mystate = uc == 1 ? TAP_IRPAUSE : TAP_IDLE;
+                       if (read(xsvf_fd, &uc, 1) < 0)
+                       {
+                               do_abort = 1;
+                               break;
+                       }
+
+                       /* see page 22 of XSVF spec */
+                       if( uc == 0 )
+                               xenddr = TAP_IDLE;
+                       else if( uc == 1 )
+                               xenddr = TAP_DRPAUSE;
+                       else
+                       {
+                               LOG_ERROR("illegial XENDDR argument: 0x%02X", uc);
+                               unsupported = 1;
+                               break;
+                       }
 
-                                       LOG_DEBUG("XENDIR 0x%02X %s", uc, jtag_state_name(mystate));
+                       LOG_DEBUG("XENDDR %02X %s", uc, tap_state_name(xenddr));
+                       break;
 
-                                       /* assuming that the XRUNTEST comes from SVF RUNTEST, then only these states
-                                        * should come here because the SVF spec only allows these with a RUNTEST
-                                        */
-                                       if (mystate != TAP_IRPAUSE && mystate != TAP_DRPAUSE && mystate != TAP_RESET && mystate != TAP_IDLE )
+               case XSIR:
+               case XSIR2:
+                       {
+                               u8      short_buf[2];
+                               u8*     ir_buf;
+                               int bitcount;
+                               tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir;
+
+                               if( opcode == XSIR )
+                               {
+                                       /* one byte bitcount */
+                                       if (read(xsvf_fd, short_buf, 1) < 0)
                                        {
-                                               LOG_ERROR("illegal XENDIR endstate: \"%s\"", jtag_state_name(mystate));
-                                               unsupported = 1;
+                                               do_abort = 1;
                                                break;
                                        }
-                                       xendir = mystate;
+                                       bitcount = short_buf[0];
+                                       LOG_DEBUG("XSIR %d", bitcount);
                                }
-                               break;
-
-                       case XENDDR:
+                               else
                                {
-                                       tap_state_t      mystate;
-
-                                       if (read(xsvf_fd, &uc, 1) < 0)
+                                       if (read(xsvf_fd, short_buf, 2) < 0)
                                        {
                                                do_abort = 1;
                                                break;
                                        }
+                                       bitcount = be_to_h_u16(short_buf);
+                                       LOG_DEBUG("XSIR2 %d", bitcount);
+                               }
+
+                               ir_buf = malloc((bitcount+7) / 8);
+
+                               if (xsvf_read_buffer(bitcount, xsvf_fd, ir_buf) != ERROR_OK)
+                                       do_abort = 1;
+                               else
+                               {
+                                       scan_field_t field;
 
-                                       /* see page 22 of XSVF spec */
-                                       mystate = uc == 1 ? TAP_DRPAUSE : TAP_IDLE;
+                                       field.tap = tap;
+                                       field.num_bits = bitcount;
+                                       field.out_value = ir_buf;
 
-                                       LOG_DEBUG("XENDDR %02X %s", uc, jtag_state_name(mystate));
+                                       field.in_value = NULL;
 
-                                       if (mystate != TAP_IRPAUSE && mystate != TAP_DRPAUSE && mystate != TAP_RESET && mystate != TAP_IDLE )
-                                       {
-                                               LOG_ERROR("illegal XENDDR endstate: \"%s\"", jtag_state_name( mystate ));
-                                               unsupported = 1;
-                                               break;
-                                       }
-                                       xenddr = mystate;
-                               }
-                               break;
 
-                       case XSIR:
-                       case XSIR2:
-                               {
-                                       u8      short_buf[2];
-                                       u8*     ir_buf;
-                                       int bitcount;
-                                       tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir;
+                                       
 
-                                       if( opcode == XSIR )
-                                       {
-                                               /* one byte bitcount */
-                                               if (read(xsvf_fd, short_buf, 1) < 0)
-                                               {
-                                                       do_abort = 1;
-                                                       break;
-                                               }
-                                               bitcount = short_buf[0];
-                                               LOG_DEBUG("XSIR %d", bitcount);
-                                       }
+                                       if (tap == NULL)
+                                               jtag_add_plain_ir_scan(1, &field, my_end_state);
                                        else
+                                               jtag_add_ir_scan(1, &field, my_end_state);
+
+                                       if (xruntest)
                                        {
-                                               if (read(xsvf_fd, short_buf, 2) < 0)
-                                               {
-                                                       do_abort = 1;
-                                                       break;
-                                               }
-                                               bitcount = be_to_h_u16(short_buf);
-                                               LOG_DEBUG("XSIR2 %d", bitcount);
+                                               if (runtest_requires_tck)
+                                                       jtag_add_clocks(xruntest);
+                                               else
+                                                       jtag_add_sleep(xruntest);
                                        }
 
-                                       ir_buf = malloc((bitcount+7) / 8);
+                                       /* Note that an -irmask of non-zero in your config file
+                                        * can cause this to fail.  Setting -irmask to zero cand work
+                                        * around the problem.
+                                        */
 
-                                       if (xsvf_read_buffer(bitcount, xsvf_fd, ir_buf) != ERROR_OK)
-                                               do_abort = 1;
-                                       else
+                                       /* LOG_DEBUG("FLUSHING QUEUE"); */
+                                       result = jtag_execute_queue();
+                                       if(result != ERROR_OK)
                                        {
-                                               scan_field_t field;
-
-                                               field.tap = tap;
-                                               field.num_bits = bitcount;
-                                               field.out_value = ir_buf;
-                                               field.out_mask = NULL;
-                                               field.in_value = NULL;
-                                               field.in_check_value = NULL;
-                                               field.in_check_mask = NULL;
-                                               field.in_handler = NULL;
-                                               field.in_handler_priv = NULL;
-
-                                               if (tap == NULL)
-                                                       jtag_add_plain_ir_scan(1, &field, my_end_state);
-                                               else
-                                                       jtag_add_ir_scan(1, &field, my_end_state);
-
-                                               if (xruntest)
-                                               {
-                                                       if (runtest_requires_tck)
-                                                               jtag_add_clocks(xruntest);
-                                                       else
-                                                               jtag_add_sleep(xruntest);
-                                               }
-
-                                               /* Note that an -irmask of non-zero in your config file
-                                                * can cause this to fail.  Setting -irmask to zero cand work
-                                                * around the problem.
-                                                */
-
-                                               /* LOG_DEBUG("FLUSHING QUEUE"); */
-                                               result = jtag_execute_queue();
-                                               if(result != ERROR_OK)
-                                               {
-                                                       tdo_mismatch = 1;
-                                               }
+                                               tdo_mismatch = 1;
                                        }
-                                       free(ir_buf);
                                }
-                               break;
+                               free(ir_buf);
+                       }
+                       break;
 
-                       case XCOMMENT:
-                               {
-                                       int             ndx = 0;
-                                       char    comment[128];
+               case XCOMMENT:
+                       {
+                               unsigned int ndx = 0;
+                               char    comment[128];
 
-                                       do
+                               do
+                               {
+                                       if (read(xsvf_fd, &uc, 1) < 0)
                                        {
-                                               if (read(xsvf_fd, &uc, 1) < 0)
-                                               {
-                                                       do_abort = 1;
-                                                       break;
-                                               }
+                                               do_abort = 1;
+                                               break;
+                                       }
 
-                                               if ( ndx < sizeof(comment)-1 )
-                                                       comment[ndx++] = uc;
+                                       if ( ndx < sizeof(comment)-1 )
+                                               comment[ndx++] = uc;
 
-                                       } while (uc != 0);
+                               } while (uc != 0);
 
-                                       comment[sizeof(comment)-1] = 0;         /* regardless, terminate */
-                                       if (verbose)
-                                               LOG_USER(comment);
-                               }
-                               break;
+                               comment[sizeof(comment)-1] = 0;         /* regardless, terminate */
+                               if (verbose)
+                                       LOG_USER("# %s", comment);
+                       }
+                       break;
 
-                       case XWAIT:
-                               {
-                                       /* expected in stream:
-                                          XWAIT <u8 wait_state> <u8 end_state> <u32 usecs>
-                                       */
+               case XWAIT:
+                       {
+                               /* expected in stream:
+                                  XWAIT <u8 wait_state> <u8 end_state> <u32 usecs>
+                               */
 
-                                       u8      wait;
-                                       u8      end;
-                                       u8      delay_buf[4];
+                               u8      wait;
+                               u8      end;
+                               u8      delay_buf[4];
 
-                                       tap_state_t wait_state;
-                                       tap_state_t end_state;
-                                       int     delay;
+                               tap_state_t wait_state;
+                               tap_state_t end_state;
+                               int     delay;
 
-                                       if ( read(xsvf_fd, &wait, 1) < 0
-                                         || read(xsvf_fd, &end, 1) < 0
-                                         || read(xsvf_fd, delay_buf, 4) < 0)
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+                               if ( read(xsvf_fd, &wait, 1) < 0
+                                 || read(xsvf_fd, &end, 1) < 0
+                                 || read(xsvf_fd, delay_buf, 4) < 0)
+                               {
+                                       do_abort = 1;
+                                       break;
+                               }
 
-                                       wait_state = xsvf_to_tap(wait);
-                                       end_state  = xsvf_to_tap(end);
-                                       delay      = be_to_h_u32(delay_buf);
+                               wait_state = xsvf_to_tap(wait);
+                               end_state  = xsvf_to_tap(end);
+                               delay      = be_to_h_u32(delay_buf);
 
-                                       LOG_DEBUG("XWAIT %s %s usecs:%d", jtag_state_name(wait_state), jtag_state_name(end_state), delay);
+                               LOG_DEBUG("XWAIT %s %s usecs:%d", tap_state_name(wait_state), tap_state_name(end_state), delay);
 
-                                       if (runtest_requires_tck && wait_state == TAP_IDLE )
-                                       {
-                                               jtag_add_runtest(delay, end_state);
-                                       }
-                                       else
-                                       {
-                                               xsvf_add_statemove( wait_state );
-                                               jtag_add_sleep(delay);
-                                               xsvf_add_statemove( end_state );
-                                       }
+                               if (runtest_requires_tck && wait_state == TAP_IDLE )
+                               {
+                                       jtag_add_runtest(delay, end_state);
                                }
-                               break;
+                               else
+                               {
+                                       xsvf_add_statemove( wait_state );
+                                       jtag_add_sleep(delay);
+                                       xsvf_add_statemove( end_state );
+                               }
+                       }
+                       break;
 
-                       case XWAITSTATE:
+               case XWAITSTATE:
+                       {
+                               /* expected in stream:
+                                  XWAITSTATE <u8 wait_state> <u8 end_state> <u32 clock_count> <u32 usecs>
+                               */
+
+                               u8  clock_buf[4];
+                               u8      usecs_buf[4];
+                               u8      wait;
+                               u8      end;
+                               tap_state_t wait_state;
+                               tap_state_t end_state;
+                               int clock_count;
+                               int usecs;
+
+                               if ( read(xsvf_fd, &wait, 1) < 0
+                                ||  read(xsvf_fd, &end, 1) < 0
+                                ||  read(xsvf_fd, clock_buf, 4) < 0
+                                ||  read(xsvf_fd, usecs_buf, 4) < 0 )
                                {
-                                       /* expected in stream:
-                                          XWAITSTATE <u8 wait_state> <u8 end_state> <u32 clock_count> <u32 usecs>
-                                       */
+                                       do_abort = 1;
+                                       break;
+                               }
 
-                                       u8  clock_buf[4];
-                                       u8      usecs_buf[4];
-                                       u8      wait;
-                                       u8      end;
-                                       tap_state_t wait_state;
-                                       tap_state_t end_state;
-                                       int clock_count;
-                                       int usecs;
-
-                                       if ( read(xsvf_fd, &wait, 1) < 0
-                                        ||  read(xsvf_fd, &end, 1) < 0
-                                        ||  read(xsvf_fd, clock_buf, 4) < 0
-                                        ||  read(xsvf_fd, usecs_buf, 4) < 0 )
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+                               wait_state = xsvf_to_tap( wait );
+                               end_state  = xsvf_to_tap( end );
 
-                                       wait_state = xsvf_to_tap( wait );
-                                       end_state  = xsvf_to_tap( end );
+                               clock_count = be_to_h_u32(clock_buf);
+                               usecs       = be_to_h_u32(usecs_buf);
 
-                                       clock_count = be_to_h_u32(clock_buf);
-                                       usecs       = be_to_h_u32(usecs_buf);
+                               LOG_DEBUG("XWAITSTATE %s %s clocks:%i usecs:%i",
+                                       tap_state_name(wait_state),
+                                       tap_state_name(end_state),
+                                       clock_count, usecs);
 
-                                       LOG_DEBUG("XWAITSTATE %s %s clocks:%i usecs:%i",
-                                               jtag_state_name(wait_state),
-                                               jtag_state_name(end_state),
-                                               clock_count, usecs);
+                               /* the following states are 'stable', meaning that they have a transition
+                                * in the state diagram back to themselves.  This is necessary because we will
+                                * be issuing a number of clocks in this state.  This set of allowed states is also
+                                * determined by the SVF RUNTEST command's allowed states.
+                                */
+                               if (wait_state != TAP_IRPAUSE && wait_state != TAP_DRPAUSE && wait_state != TAP_RESET && wait_state != TAP_IDLE)
+                               {
+                                       LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"", tap_state_name( wait_state ));
+                                       unsupported = 1;
+                               }
 
-                                       /* the following states are 'stable', meaning that they have a transition
-                                        * in the state diagram back to themselves.  This is necessary because we will
-                                        * be issuing a number of clocks in this state.  This set of allowed states is also
-                                        * determined by the SVF RUNTEST command's allowed states.
-                                        */
-                                       if (wait_state != TAP_IRPAUSE && wait_state != TAP_DRPAUSE && wait_state != TAP_RESET && wait_state != TAP_IDLE)
-                                       {
-                                               LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"", jtag_state_name( wait_state ));
-                                               unsupported = 1;
-                                       }
+                               xsvf_add_statemove( wait_state );
 
-                                       xsvf_add_statemove( wait_state );
+                               jtag_add_clocks( clock_count );
 
-                                       jtag_add_clocks( clock_count );
+                               jtag_add_sleep( usecs );
 
-                                       jtag_add_sleep( usecs );
+                               xsvf_add_statemove( end_state );
+                       }
+                       break;
 
-                                       xsvf_add_statemove( end_state );
-                               }
-                               break;
+               case LCOUNT:
+                       {
+                               /* expected in stream:
+                                  LCOUNT <u32 loop_count>
+                               */
+                               u8  count_buf[4];
 
-                       case LCOUNT:
+                               if ( read(xsvf_fd, count_buf, 4) < 0 )
                                {
-                                       /* expected in stream:
-                                          LCOUNT <u32 loop_count>
-                                       */
-                                       u8  count_buf[4];
+                                       do_abort = 1;
+                                       break;
+                               }
 
-                                       if ( read(xsvf_fd, count_buf, 4) < 0 )
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+                               loop_count = be_to_h_u32(count_buf);
+                               LOG_DEBUG("LCOUNT %d", loop_count);
+                       }
+                       break;
 
-                                       loop_count = be_to_h_u32(count_buf);
-                                       LOG_DEBUG("LCOUNT %d", loop_count);
+               case LDELAY:
+                       {
+                               /* expected in stream:
+                                  LDELAY <u8 wait_state> <u32 clock_count> <u32 usecs_to_sleep>
+                               */
+                               u8      state;
+                               u8  clock_buf[4];
+                               u8  usecs_buf[4];
+
+                               if ( read(xsvf_fd, &state, 1) < 0
+                                 || read(xsvf_fd, clock_buf, 4) < 0
+                                 ||     read(xsvf_fd, usecs_buf, 4) < 0 )
+                               {
+                                       do_abort = 1;
+                                       break;
                                }
-                               break;
 
-                       case LDELAY:
-                               {
-                                       /* expected in stream:
-                                          LDELAY <u8 wait_state> <u32 clock_count> <u32 usecs_to_sleep>
-                                       */
-                                       u8      state;
-                                       u8  clock_buf[4];
-                                       u8  usecs_buf[4];
+                               loop_state  = xsvf_to_tap(state);
+                               loop_clocks = be_to_h_u32(clock_buf);
+                               loop_usecs  = be_to_h_u32(usecs_buf);
 
-                                       if ( read(xsvf_fd, &state, 1) < 0
-                                         || read(xsvf_fd, clock_buf, 4) < 0
-                                         ||     read(xsvf_fd, usecs_buf, 4) < 0 )
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+                               LOG_DEBUG("LDELAY %s clocks:%d usecs:%d", tap_state_name(loop_state), loop_clocks, loop_usecs);
+                       }
+                       break;
 
-                                       loop_state  = xsvf_to_tap(state);
-                                       loop_clocks = be_to_h_u32(clock_buf);
-                                       loop_usecs  = be_to_h_u32(usecs_buf);
+               /* LSDR is more like XSDRTDO than it is like XSDR.  It uses LDELAY which
+                * comes with clocks !AND! sleep requirements.
+                */
+               case LSDR:
+                       {
+                               int limit = loop_count;
+                               int matched = 0;
+                               int attempt;
 
-                                       LOG_DEBUG("LDELAY %s clocks:%d usecs:%d", jtag_state_name(loop_state), loop_clocks, loop_usecs);
-                               }
-                               break;
+                               LOG_DEBUG("LSDR");
 
-                       /* LSDR is more like XSDRTDO than it is like XSDR.  It uses LDELAY which
-                        * comes with clocks !AND! sleep requirements.
-                        */
-                       case LSDR:
+                               if ( xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK
+                                 || xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK )
                                {
-                                       int limit = loop_count;
-                                       int matched = 0;
-                                       int attempt;
+                                       do_abort = 1;
+                                       break;
+                               }
 
-                                       LOG_DEBUG("LSDR");
+                               if (limit < 1)
+                                       limit = 1;
 
-                                       if ( xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK
-                                         || xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK )
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+                               for( attempt=0; attempt<limit;  ++attempt )
+                               {
+                                       scan_field_t field;
 
-                                       if (limit < 1)
-                                               limit = 1;
+                                       xsvf_add_statemove( loop_state );
+                                       jtag_add_clocks(loop_clocks);
+                                       jtag_add_sleep(loop_usecs);
 
-                                       for( attempt=0; attempt<limit;  ++attempt )
-                                       {
-                                               scan_field_t field;
+                                       field.tap = tap;
+                                       field.num_bits = xsdrsize;
+                                       field.out_value = dr_out_buf;
+                                       field.in_value = calloc(CEIL(field.num_bits, 8), 1);
 
-                                               xsvf_add_statemove( loop_state );
-                                               jtag_add_clocks(loop_clocks);
-                                               jtag_add_sleep(loop_usecs);
+                                       if (attempt > 0 && verbose)
+                                               LOG_USER("LSDR retry %d", attempt);
 
-                                               field.tap = tap;
-                                               field.num_bits = xsdrsize;
-                                               field.out_value = dr_out_buf;
-                                               field.out_mask = NULL;
-                                               field.in_value = NULL;
+                                       if (tap == NULL)
+                                               jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
+                                       else
+                                               jtag_add_dr_scan(1, &field, TAP_DRPAUSE);
 
-                                               if (attempt > 0 && verbose)
-                                                       LOG_USER("LSDR retry %d", attempt);
+                                       jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
+
+                                       free(field.in_value);
 
-                                               jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
-                                               if (tap == NULL)
-                                                       jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
-                                               else
-                                                       jtag_add_dr_scan(1, &field, TAP_DRPAUSE);
-
-                                               /* LOG_DEBUG("FLUSHING QUEUE"); */
-                                               result = jtag_execute_queue();
-                                               if(result == ERROR_OK)
-                                               {
-                                                       matched = 1;
-                                                       break;
-                                               }
-                                       }
 
-                                       if (!matched )
+                                       /* LOG_DEBUG("FLUSHING QUEUE"); */
+                                       result = jtag_execute_queue();
+                                       if(result == ERROR_OK)
                                        {
-                                               LOG_USER( "LSDR mismatch" );
-                                               tdo_mismatch = 1;
+                                               matched = 1;
                                                break;
                                        }
                                }
-                               break;
 
-                       case XTRST:
+                               if (!matched )
                                {
-                                       u8      trst_mode;
+                                       LOG_USER( "LSDR mismatch" );
+                                       tdo_mismatch = 1;
+                                       break;
+                               }
+                       }
+                       break;
 
-                                       if (read(xsvf_fd, &trst_mode, 1) < 0)
-                                       {
-                                               do_abort = 1;
-                                               break;
-                                       }
+               case XTRST:
+                       {
+                               u8      trst_mode;
 
-                                       switch( trst_mode )
-                                       {
-                                       case XTRST_ON:
-                                               jtag_add_reset(1, 0);
-                                               break;
-                                       case XTRST_OFF:
-                                       case XTRST_Z:
-                                               jtag_add_reset(0, 0);
-                                               break;
-                                       case XTRST_ABSENT:
-                                               break;
-                                       default:
-                                               LOG_ERROR( "XTRST mode argument (0x%02X) out of range", trst_mode );
-                                               do_abort = 1;
-                                       }
+                               if (read(xsvf_fd, &trst_mode, 1) < 0)
+                               {
+                                       do_abort = 1;
+                                       break;
                                }
-                               break;
 
-                       default:
-                               LOG_ERROR("unknown xsvf command (0x%02X)\n", uc);
-                               unsupported = 1;
+                               switch( trst_mode )
+                               {
+                               case XTRST_ON:
+                                       jtag_add_reset(1, 0);
+                                       break;
+                               case XTRST_OFF:
+                               case XTRST_Z:
+                                       jtag_add_reset(0, 0);
+                                       break;
+                               case XTRST_ABSENT:
+                                       break;
+                               default:
+                                       LOG_ERROR( "XTRST mode argument (0x%02X) out of range", trst_mode );
+                                       do_abort = 1;
+                               }
+                       }
+                       break;
+
+               default:
+                       LOG_ERROR("unknown xsvf command (0x%02X)\n", uc);
+                       unsupported = 1;
                }
 
                if (do_abort || unsupported || tdo_mismatch)
@@ -1058,7 +1051,9 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha
 }
 
 
-/* PSUEDO-Code from Xilinx Appnote XAPP067.pdf:
+#if 0   /* this comment style used to try and keep uncrustify from adding * at begin of line */
+
+PSUEDO-Code from Xilinx Appnote XAPP067.pdf:
 
 the following pseudo code clarifies the intent of the xrepeat support.  The
 flow given is for the entire processing of an SVF file, not an XSVF file.
@@ -1106,4 +1101,4 @@ else if RUNTEST record then
    store <TCK value> as <current pause time>
 end if
 
-*/
+#endif

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)