static int jtag_nsrst_delay = 0; /* default to no nSRST delay */
static int jtag_ntrst_delay = 0; /* default to no nTRST delay */
-/* maximum number of JTAG devices expected in the chain
- */
-#define JTAG_MAX_CHAIN_SIZE 20
-
/* callbacks to inform high-level handlers about JTAG state changes */
jtag_event_callback_t *jtag_event_callbacks;
#if BUILD_ECOSBOARD == 1
extern jtag_interface_t zy1000_interface;
-#endif
-
+#elif defined(BUILD_MINIDRIVER_DUMMY)
+ extern jtag_interface_t minidummy_interface;
+#else // standard drivers
#if BUILD_PARPORT == 1
extern jtag_interface_t parport_interface;
#endif
#if BUILD_ARMJTAGEW == 1
extern jtag_interface_t armjtagew_interface;
#endif
+#endif // standard drivers
+/**
+ * The list of built-in JTAG interfaces, containing entries for those
+ * drivers that were enabled by the @c configure script.
+ *
+ * The list should be defined to contain either one minidriver interface
+ * or some number of standard driver interfaces, never both.
+ */
jtag_interface_t *jtag_interfaces[] = {
#if BUILD_ECOSBOARD == 1
&zy1000_interface,
-#endif
+#elif defined(BUILD_MINIDRIVER_DUMMY)
+ &minidummy_interface,
+#else // standard drivers
#if BUILD_PARPORT == 1
&parport_interface,
#endif
#if BUILD_ARMJTAGEW == 1
&armjtagew_interface,
#endif
+#endif // standard drivers
NULL,
};
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-static int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
return __jtag_all_taps;
};
-int jtag_NumTotalTaps(void)
+int jtag_tap_count(void)
{
return jtag_num_taps;
}
-int jtag_NumEnabledTaps(void)
+unsigned jtag_tap_count_enabled(void)
{
jtag_tap_t *t;
- int n;
+ unsigned n;
n = 0;
t = jtag_all_taps();
*tap = t;
}
-jtag_tap_t *jtag_TapByString( const char *s )
+jtag_tap_t *jtag_tap_by_string( const char *s )
{
jtag_tap_t *t;
char *cp;
n = strtol( s, &cp, 0 );
if( (s != cp) && (*cp == 0) ){
/* Then it is... */
- t = jtag_TapByAbsPosition(n);
+ t = jtag_tap_by_abs_position(n);
}
}
return t;
}
-jtag_tap_t * jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o )
+jtag_tap_t * jtag_tap_by_jim_obj( Jim_Interp *interp, Jim_Obj *o )
{
jtag_tap_t *t;
const char *cp;
cp = "(unknown)";
t = NULL;
} else {
- t = jtag_TapByString( cp );
+ t = jtag_tap_by_string( cp );
}
if( t == NULL ){
Jim_SetResult_sprintf(interp,"Tap: %s is unknown", cp );
}
/* returns a pointer to the n-th device in the scan chain */
-jtag_tap_t * jtag_TapByAbsPosition( int n )
+jtag_tap_t * jtag_tap_by_abs_position( int n )
{
int orig_n;
jtag_tap_t *t;
alive_sleep(us/1000);
}
-/* Try to examine chain layout according to IEEE 1149.1 §12
- */
-static int jtag_examine_chain(void)
+/// maximum number of JTAG devices expected in the chain
+#define JTAG_MAX_CHAIN_SIZE 20
+
+#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
+#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
+#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
+
+static int jtag_examine_chain_execute(u8 *idcode_buffer, unsigned num_idcode)
+{
+ scan_field_t field = {
+ .tap = NULL,
+ .num_bits = num_idcode * 32,
+ .out_value = idcode_buffer,
+ .in_value = idcode_buffer,
+ };
+
+ // initialize to the end of chain ID value
+ for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+ buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+
+ jtag_add_plain_dr_scan(1, &field, TAP_RESET);
+ return jtag_execute_queue();
+}
+
+static bool jtag_examine_chain_check(u8 *idcodes, unsigned count)
{
- jtag_tap_t *tap;
- scan_field_t field;
- u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
- int i;
- int bit_count;
- int device_count = 0;
u8 zero_check = 0x0;
u8 one_check = 0xff;
- field.tap = NULL;
- field.num_bits = sizeof(idcode_buffer) * 8;
- field.out_value = idcode_buffer;
-
- field.in_value = idcode_buffer;
+ for (unsigned i = 0; i < count * 4; i++)
+ {
+ zero_check |= idcodes[i];
+ one_check &= idcodes[i];
+ }
+ /* if there wasn't a single non-zero bit or if all bits were one,
+ * the scan is not valid */
+ if (zero_check == 0x00 || one_check == 0xff)
+ {
+ LOG_ERROR("JTAG communication failure: check connection, "
+ "JTAG interface, target power etc.");
+ return false;
+ }
+ return true;
+}
+static void jtag_examine_chain_display(enum log_levels level, const char *msg,
+ const char *name, u32 idcode)
+{
+ log_printf_lf(level, __FILE__, __LINE__, __FUNCTION__,
+ "JTAG tap: %s %16.16s: 0x%08x "
+ "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+ name, msg, idcode,
+ EXTRACT_MFG(idcode), EXTRACT_PART(idcode), EXTRACT_VER(idcode) );
+}
+static bool jtag_idcode_is_final(u32 idcode)
+{
+ return idcode == 0x000000FF || idcode == 0xFFFFFFFF;
+}
- for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+/**
+ * This helper checks that remaining bits in the examined chain data are
+ * all as expected, but a single JTAG device requires only 64 bits to be
+ * read back correctly. This can help identify and diagnose problems
+ * with the JTAG chain earlier, gives more helpful/explicit error messages.
+ */
+static void jtag_examine_chain_end(u8 *idcodes, unsigned count, unsigned max)
+{
+ bool triggered = false;
+ for ( ; count < max - 31; count += 32)
{
- buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+ u32 idcode = buf_get_u32(idcodes, count, 32);
+ // do not trigger the warning if the data looks good
+ if (!triggered && jtag_idcode_is_final(idcode))
+ continue;
+ LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
+ count, idcode);
+ triggered = true;
}
+}
- jtag_add_plain_dr_scan(1, &field, TAP_RESET);
- jtag_execute_queue();
+static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
+{
+ if (0 == tap->expected_ids_cnt)
+ {
+ /// @todo Enable LOG_INFO to ask for reports about unknown TAP IDs.
+#if 0
+ LOG_INFO("Uknown JTAG TAP ID: 0x%08x", tap->idcode)
+ LOG_INFO("Please report the chip name and reported ID code to the openocd project");
+#endif
+ return true;
+ }
- for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
+ /* Loop over the expected identification codes and test for a match */
+ u8 ii;
+ for (ii = 0; ii < tap->expected_ids_cnt; ii++)
{
- zero_check |= idcode_buffer[i];
- one_check &= idcode_buffer[i];
+ if (tap->idcode == tap->expected_ids[ii])
+ break;
}
- /* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */
- if ((zero_check == 0x00) || (one_check == 0xff))
+ /* If none of the expected ids matched, log an error */
+ if (ii != tap->expected_ids_cnt)
{
- LOG_ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
- return ERROR_JTAG_INIT_FAILED;
+ LOG_INFO("JTAG Tap/device matched");
+ return true;
}
+ jtag_examine_chain_display(LOG_LVL_ERROR, "got",
+ tap->dotted_name, tap->idcode);
+ for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+ {
+ char msg[32];
+ snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
+ ii + 1, tap->expected_ids_cnt);
+ jtag_examine_chain_display(LOG_LVL_ERROR, msg,
+ tap->dotted_name, tap->expected_ids[ii]);
+ }
+ return false;
+}
+
+/* Try to examine chain layout according to IEEE 1149.1 §12
+ */
+static int jtag_examine_chain(void)
+{
+ u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+ unsigned device_count = 0;
+
+ jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+
+ if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
+ return ERROR_JTAG_INIT_FAILED;
/* point at the 1st tap */
- tap = jtag_NextEnabledTap(NULL);
- if( tap == NULL ){
+ jtag_tap_t *tap = jtag_tap_next_enabled(NULL);
+ if (tap == NULL)
+ {
LOG_ERROR("JTAG: No taps enabled?");
return ERROR_JTAG_INIT_FAILED;
}
- for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
+ for (unsigned bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
{
u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
if ((idcode & 1) == 0)
{
/* LSB must not be 0, this indicates a device in bypass */
LOG_WARNING("Tap/Device does not have IDCODE");
- idcode=0;
+ idcode = 0;
bit_count += 1;
}
else
{
- u32 manufacturer;
- u32 part;
- u32 version;
-
- /* some devices, such as AVR will output all 1's instead of TDI
- input value at end of chain. */
- if ((idcode == 0x000000FF)||(idcode == 0xFFFFFFFF))
+ /*
+ * End of chain (invalid manufacturer ID) some devices, such
+ * as AVR will output all 1's instead of TDI input value at
+ * end of chain.
+ */
+ if (jtag_idcode_is_final(idcode))
{
- int unexpected=0;
- /* End of chain (invalid manufacturer ID)
- *
- * The JTAG examine is the very first thing that happens
- *
- * A single JTAG device requires only 64 bits to be read back correctly.
- *
- * The code below adds a check that the rest of the data scanned (640 bits)
- * are all as expected. This helps diagnose/catch problems with the JTAG chain
- *
- * earlier and gives more helpful/explicit error messages.
- */
- for (bit_count += 32; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;bit_count += 32)
- {
- idcode = buf_get_u32(idcode_buffer, bit_count, 32);
- if (unexpected||((idcode != 0x000000FF)&&(idcode != 0xFFFFFFFF)))
- {
- LOG_WARNING("Unexpected idcode after end of chain! %d 0x%08x", bit_count, idcode);
- unexpected = 1;
- }
- }
-
+ jtag_examine_chain_end(idcode_buffer,
+ bit_count + 32, JTAG_MAX_CHAIN_SIZE * 32);
break;
}
-#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
- manufacturer = EXTRACT_MFG(idcode);
-#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
- part = EXTRACT_PART(idcode);
-#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
- version = EXTRACT_VER(idcode);
-
- LOG_INFO("JTAG tap: %s tap/device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)",
- ((tap != NULL) ? (tap->dotted_name) : "(not-named)"),
- idcode, manufacturer, part, version);
+ jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
+ tap ? tap->dotted_name : "(not-named)",
+ idcode);
bit_count += 32;
}
- if (tap)
- {
- tap->idcode = idcode;
-
- if (tap->expected_ids_cnt > 0) {
- /* Loop over the expected identification codes and test for a match */
- u8 ii;
- for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
- if( tap->idcode == tap->expected_ids[ii] ){
- break;
- }
- }
+ device_count++;
+ if (!tap)
+ continue;
- /* If none of the expected ids matched, log an error */
- if (ii == tap->expected_ids_cnt) {
- LOG_ERROR("JTAG tap: %s got: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
- tap->dotted_name,
- idcode,
- EXTRACT_MFG( tap->idcode ),
- EXTRACT_PART( tap->idcode ),
- EXTRACT_VER( tap->idcode ) );
- for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
- LOG_ERROR("JTAG tap: %s expected %hhu of %hhu: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
- tap->dotted_name,
- ii + 1,
- tap->expected_ids_cnt,
- tap->expected_ids[ii],
- EXTRACT_MFG( tap->expected_ids[ii] ),
- EXTRACT_PART( tap->expected_ids[ii] ),
- EXTRACT_VER( tap->expected_ids[ii] ) );
- }
+ tap->idcode = idcode;
- return ERROR_JTAG_INIT_FAILED;
- } else {
- LOG_INFO("JTAG Tap/device matched");
- }
- } else {
-#if 0
- LOG_INFO("JTAG TAP ID: 0x%08x - Unknown - please report (A) chipname and (B) idcode to the openocd project",
- tap->idcode);
-#endif
- }
- tap = jtag_NextEnabledTap(tap);
- }
- device_count++;
+ // ensure the TAP ID does matches what was expected
+ if (!jtag_examine_chain_match_tap(tap))
+ return ERROR_JTAG_INIT_FAILED;
+
+ tap = jtag_tap_next_enabled(tap);
}
/* see if number of discovered devices matches configuration */
- if (device_count != jtag_NumEnabledTaps())
+ if (device_count != jtag_tap_count_enabled())
{
- LOG_ERROR("number of discovered devices in JTAG chain (%i) doesn't match (enabled) configuration (%i), total taps: %d",
- device_count, jtag_NumEnabledTaps(), jtag_NumTotalTaps());
- LOG_ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
+ LOG_ERROR("number of discovered devices in JTAG chain (%i) "
+ "does not match (enabled) configuration (%i), total taps: %d",
+ device_count, jtag_tap_count_enabled(), jtag_tap_count());
+ LOG_ERROR("check the config file and ensure proper JTAG communication"
+ " (connections, speed, ...)");
return ERROR_JTAG_INIT_FAILED;
}
tap = NULL;
total_ir_length = 0;
for(;;){
- tap = jtag_NextEnabledTap(tap);
+ tap = jtag_tap_next_enabled(tap);
if( tap == NULL ){
break;
}
chain_pos = 0;
int val;
for(;;){
- tap = jtag_NextEnabledTap(tap);
+ tap = jtag_tap_next_enabled(tap);
if( tap == NULL ){
break;
}
{
jtag_tap_t *t;
- t = jtag_TapByJimObj( goi.interp, goi.argv[0] );
+ t = jtag_tap_by_jim_obj( goi.interp, goi.argv[0] );
if( t == NULL ){
return JIM_ERR;
}
jtag_tap_t *t;
Jim_GetOpt_Obj(&goi, &o);
- t = jtag_TapByJimObj( goi.interp, o );
+ t = jtag_tap_by_jim_obj( goi.interp, o );
if( t == NULL ){
return JIM_ERR;
}
jtag_tap_t *t;
Jim_GetOpt_Obj(&goi, &o);
- t = jtag_TapByJimObj( goi.interp, o );
+ t = jtag_tap_by_jim_obj( goi.interp, o );
if( t == NULL ){
return JIM_ERR;
}
register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
COMMAND_EXEC, "print current scan chain configuration");
- register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,
- COMMAND_EXEC, "finish JTAG operations in <tap_state>");
register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
COMMAND_EXEC, "toggle reset lines <trst> <srst>");
register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
LOG_DEBUG("Init JTAG chain");
- tap = jtag_NextEnabledTap(NULL);
+ tap = jtag_tap_next_enabled(NULL);
if( tap == NULL ){
LOG_ERROR("There are no enabled taps?");
return ERROR_JTAG_INIT_FAILED;
newargs[0] = Jim_NewStringObj( interp, "jtag", -1 );
newargs[1] = Jim_NewStringObj( interp, "newtap", -1 );
- sprintf( buf, "chip%d", jtag_NumTotalTaps() );
+ sprintf( buf, "chip%d", jtag_tap_count() );
newargs[2] = Jim_NewStringObj( interp, buf, -1 );
- sprintf( buf, "tap%d", jtag_NumTotalTaps() );
+ sprintf( buf, "tap%d", jtag_tap_count() );
newargs[3] = Jim_NewStringObj( interp, buf, -1 );
newargs[4] = Jim_NewStringObj( interp, "-irlen", -1 );
newargs[5] = Jim_NewStringObj( interp, args[0], -1 );
return ERROR_OK;
}
-static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx,
+ char *cmd, char **args, int argc)
{
- if (argc < 1)
- {
- LOG_ERROR("jtag_nsrst_delay <ms> command takes one required argument");
- exit(-1);
- }
- else
- {
+ if (argc > 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ if (argc == 1)
jtag_set_nsrst_delay(strtoul(args[0], NULL, 0));
- }
-
+ command_print(cmd_ctx, "jtag_nsrst_delay: %u", jtag_get_nsrst_delay());
return ERROR_OK;
}
-static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx,
+ char *cmd, char **args, int argc)
{
- if (argc < 1)
- {
- LOG_ERROR("jtag_ntrst_delay <ms> command takes one required argument");
- exit(-1);
- }
- else
- {
+ if (argc > 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ if (argc == 1)
jtag_set_ntrst_delay(strtoul(args[0], NULL, 0));
- }
-
+ command_print(cmd_ctx, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
return ERROR_OK;
}
-
static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
- int retval=ERROR_OK;
+ int retval = ERROR_OK;
+ if (argc > 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
if (argc == 1)
{
LOG_DEBUG("handle jtag speed");
/* this command can be called during CONFIG,
* in which case jtag isn't initialized */
if (jtag)
- {
- retval=jtag->speed(cur_speed);
- }
- } else if (argc == 0)
- {
- } else
- {
- return ERROR_COMMAND_SYNTAX_ERROR;
+ retval = jtag->speed(cur_speed);
}
command_print(cmd_ctx, "jtag_speed: %d", jtag_speed);
static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
- int retval=ERROR_OK;
- LOG_DEBUG("handle jtag khz");
+ if (argc > 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ int retval = ERROR_OK;
int cur_speed = 0;
- if(argc == 1)
+ if (argc == 1)
{
+ LOG_DEBUG("handle jtag khz");
+
jtag_set_speed_khz(strtoul(args[0], NULL, 0));
if (jtag != NULL)
{
LOG_DEBUG("have interface set up");
int speed_div1;
- if ((retval=jtag->khz(jtag_get_speed_khz(), &speed_div1))!=ERROR_OK)
+ retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
+ if (ERROR_OK != retval)
{
jtag_set_speed_khz(0);
return retval;
}
-
cur_speed = jtag_speed = speed_div1;
- retval=jtag->speed(cur_speed);
- } else
- {
- hasKHz = true;
+ retval = jtag->speed(cur_speed);
}
- } else if (argc==0)
- {
- } else
- {
- return ERROR_COMMAND_SYNTAX_ERROR;
+ else
+ hasKHz = true;
}
- cur_speed = jtag_get_speed_khz();
- if (jtag!=NULL)
+ cur_speed = jtag_get_speed_khz();
+ if (jtag != NULL)
{
- if ((retval=jtag->speed_div(jtag_speed, &cur_speed))!=ERROR_OK)
+ retval = jtag->speed_div(jtag_speed, &cur_speed);
+ if (ERROR_OK != retval)
return retval;
}
}
-static int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
- tap_state_t state;
-
- if (argc < 1)
- {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- else
- {
- state = tap_state_by_name( args[0] );
- if( state < 0 ){
- command_print( cmd_ctx, "Invalid state name: %s\n", args[0] );
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- jtag_set_end_state(state);
- jtag_execute_queue();
- }
- command_print(cmd_ctx, "current endstate: %s", tap_state_name(cmd_queue_end_state));
-
- return ERROR_OK;
-}
-
static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
int trst = -1;
for (i = 0; i < num_fields; i++)
{
- tap = jtag_TapByString( args[i*2] );
+ tap = jtag_tap_by_string( args[i*2] );
if (tap==NULL)
{
command_print( cmd_ctx, "Tap: %s unknown", args[i*2] );
}
} /* validate args */
- tap = jtag_TapByJimObj( interp, args[1] );
+ tap = jtag_tap_by_jim_obj( interp, args[1] );
if( tap == NULL ){
return JIM_ERR;
}
{
jtag_nsrst_delay = delay;
}
+unsigned jtag_get_nsrst_delay(void)
+{
+ return jtag_nsrst_delay;
+}
void jtag_set_ntrst_delay(unsigned delay)
{
jtag_ntrst_delay = delay;
}
-
-
+unsigned jtag_get_ntrst_delay(void)
+{
+ return jtag_ntrst_delay;
+}