#include "command.h"
#include "log.h"
#include "interpreter.h"
-#include "target.h"
#include "stdlib.h"
#include "string.h"
#include <unistd.h>
-
/* note that this is not marked as static as it must be available from outside jtag.c for those
that implement the jtag_xxx() minidriver layer
*/
char* jtag_event_strings[] =
{
- "SRST asserted",
- "TRST asserted",
- "SRST released",
- "TRST released"
+ "JTAG controller reset(tms or TRST)"
};
enum tap_state end_state = TAP_TLR;
/* jtag interfaces (parport, FTDI-USB, TI-USB, ...)
*/
+
+#if BUILD_ECOSBOARD == 1
+ extern jtag_interface_t eCosBoard_interface;
+#endif
+
#if BUILD_PARPORT == 1
extern jtag_interface_t parport_interface;
#endif
#endif
jtag_interface_t *jtag_interfaces[] = {
+#if BUILD_ECOSBOARD == 1
+ &eCosBoard_interface,
+#endif
#if BUILD_PARPORT == 1
&parport_interface,
#endif
/* configuration */
jtag_interface_t *jtag_interface = NULL;
int jtag_speed = 0;
+int jtag_speed_post_reset = 0;
/* forward declarations */
-int jtag_add_statemove(enum tap_state endstate);
-int jtag_add_pathmove(int num_states, enum tap_state *path);
-int jtag_add_runtest(int num_cycles, enum tap_state endstate);
+void jtag_add_statemove(enum tap_state endstate);
+void jtag_add_pathmove(int num_states, enum tap_state *path);
+void jtag_add_runtest(int num_cycles, enum tap_state endstate);
int jtag_add_reset(int trst, int srst);
-int jtag_add_end_state(enum tap_state endstate);
-int jtag_add_sleep(u32 us);
+void jtag_add_end_state(enum tap_state endstate);
+void jtag_add_sleep(u32 us);
int jtag_execute_queue(void);
int jtag_cancel_queue(void);
cmd_queue_pages = NULL;
}
-int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+static void jtag_prelude1()
{
if (jtag_trst == 1)
{
WARNING("JTAG command queued, while TRST is low (TAP in reset)");
jtag_error=ERROR_JTAG_TRST_ASSERTED;
- return ERROR_JTAG_TRST_ASSERTED;
+ return;
}
- if (state != -1)
- cmd_queue_end_state = state;
-
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
if (cmd_queue_end_state == TAP_TLR)
jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+}
+
+static void jtag_prelude(enum tap_state state)
+{
+ jtag_prelude1();
+ if (state != -1)
+ cmd_queue_end_state = state;
+
cmd_queue_cur_state = cmd_queue_end_state;
+}
+
+void jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+ jtag_prelude(state);
int retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state);
if (retval!=ERROR_OK)
jtag_error=retval;
- return retval;
}
int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, enum tap_state state)
(*last_cmd)->cmd.scan->fields[i].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
(*last_cmd)->cmd.scan->fields[i].out_mask = NULL;
device->bypass = 1;
-
+
}
/* update device information */
return ERROR_OK;
}
-int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
{
- if (jtag_trst == 1)
- {
- WARNING("JTAG command queued, while TRST is low (TAP in reset)");
- return jtag_error=ERROR_JTAG_TRST_ASSERTED;
- }
-
- if (state != -1)
- cmd_queue_end_state = state;
-
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
- if (cmd_queue_end_state == TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-
- cmd_queue_cur_state = cmd_queue_end_state;
+ jtag_prelude(state);
- return interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state);
+ int retval=interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
}
int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *fields, enum tap_state state)
return ERROR_OK;
}
-int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+void jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
{
- if (jtag_trst == 1)
- {
- WARNING("JTAG command queued, while TRST is low (TAP in reset)");
- return jtag_error=ERROR_JTAG_TRST_ASSERTED;
- }
+ jtag_prelude(state);
- if (state != -1)
- cmd_queue_end_state = state;
-
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
- if (cmd_queue_end_state == TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-
- cmd_queue_cur_state = cmd_queue_end_state;
-
- return interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state);
+ int retval=interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
}
int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, enum tap_state state)
(*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;
(*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
(*last_cmd)->cmd.scan->end_state = end_state;
-
+
for (i = 0; i < jtag_num_devices; i++)
{
(*last_cmd)->cmd.scan->fields[field_count].device = i;
-
+
if (i == device_num)
{
int j;
-int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
{
- if (jtag_trst == 1)
- {
- WARNING("JTAG command queued, while TRST is low (TAP in reset)");
- return jtag_error=ERROR_JTAG_TRST_ASSERTED;
- }
+ jtag_prelude(state);
- if (state != -1)
- cmd_queue_end_state = state;
-
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
- if (cmd_queue_end_state == TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-
- cmd_queue_cur_state = cmd_queue_end_state;
-
- return interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state);
+ int retval=interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
}
int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *fields, enum tap_state state)
return ERROR_OK;
}
-int jtag_add_statemove(enum tap_state state)
+void jtag_add_statemove(enum tap_state state)
{
- if (jtag_trst == 1)
- {
- WARNING("JTAG command queued, while TRST is low (TAP in reset)");
- return jtag_error=ERROR_JTAG_TRST_ASSERTED;
- }
-
- if (state != -1)
- cmd_queue_end_state = state;
+ jtag_prelude(state);
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
- if (cmd_queue_end_state == TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-
- cmd_queue_cur_state = cmd_queue_end_state;
-
- return interface_jtag_add_statemove(cmd_queue_end_state);
+ int retval;
+ retval=interface_jtag_add_statemove(cmd_queue_end_state);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
}
int MINIDRIVER(interface_jtag_add_statemove)(enum tap_state state)
return ERROR_OK;
}
-int jtag_add_pathmove(int num_states, enum tap_state *path)
+void jtag_add_pathmove(int num_states, enum tap_state *path)
{
- if (jtag_trst == 1)
- {
- WARNING("JTAG command queued, while TRST is low (TAP in reset)");
- return jtag_error=ERROR_JTAG_TRST_ASSERTED;
- }
-
/* the last state has to be a stable state */
if (tap_move_map[path[num_states - 1]] == -1)
{
- ERROR("TAP path doesn't finish in a stable state");
- return jtag_error=ERROR_JTAG_NOT_IMPLEMENTED;
+ ERROR("BUG: TAP path doesn't finish in a stable state");
+ exit(-1);
}
-
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
- if (cmd_queue_end_state == TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-
enum tap_state cur_state=cmd_queue_cur_state;
int i;
cur_state = path[i];
}
+ jtag_prelude1();
+
cmd_queue_cur_state = path[num_states - 1];
- return interface_jtag_add_pathmove(num_states, path);
+ int retval=interface_jtag_add_pathmove(num_states, path);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
}
return ERROR_OK;
}
-int jtag_add_runtest(int num_cycles, enum tap_state state)
+void jtag_add_runtest(int num_cycles, enum tap_state state)
{
- if (jtag_trst == 1)
- {
- jtag_error=ERROR_JTAG_QUEUE_FAILED;
- WARNING("JTAG command queued, while TRST is low (TAP in reset)");
- return ERROR_JTAG_TRST_ASSERTED;
- }
-
- if (state != -1)
- cmd_queue_end_state = state;
-
- if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-
- if (cmd_queue_end_state == TAP_TLR)
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-
- cmd_queue_cur_state = cmd_queue_end_state;
+ jtag_prelude(state);
/* executed by sw or hw fifo */
- return interface_jtag_add_runtest(num_cycles, cmd_queue_end_state);
+ int retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
}
int jtag_add_reset(int req_trst, int req_srst)
/* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */
if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (req_trst == 0))
{
- return jtag_error=ERROR_JTAG_RESET_WOULD_ASSERT_TRST;
+ ERROR("requested reset would assert trst");
+ return ERROR_JTAG_RESET_WOULD_ASSERT_TRST;
}
/* if TRST pulls SRST, we reset with TAP T-L-R */
if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
{
ERROR("requested nSRST assertion, but the current configuration doesn't support this");
- return jtag_error=ERROR_JTAG_RESET_CANT_SRST;
+ return ERROR_JTAG_RESET_CANT_SRST;
}
if (req_trst && !(jtag_reset_config & RESET_HAS_TRST))
if (jtag_srst)
{
- jtag_call_event_callbacks(JTAG_SRST_ASSERTED);
+ DEBUG("SRST line asserted");
}
else
{
- jtag_call_event_callbacks(JTAG_SRST_RELEASED);
+ DEBUG("SRST line released");
if (jtag_nsrst_delay)
jtag_add_sleep(jtag_nsrst_delay * 1000);
}
if (trst_with_tms)
{
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+ DEBUG("JTAG reset with tms instead of TRST");
jtag_add_end_state(TAP_TLR);
jtag_add_statemove(TAP_TLR);
-
+ jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
return ERROR_OK;
}
/* we just asserted nTRST, so we're now in Test-Logic-Reset,
* and inform possible listeners about this
*/
+ DEBUG("TRST line asserted");
cmd_queue_cur_state = TAP_TLR;
jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
}
/* the nTRST line got deasserted, so we're still in Test-Logic-Reset,
* but we might want to add a delay to give the TAP time to settle
*/
+ DEBUG("Now in TAP_TLR - Test-Logic-Reset(either due to TRST line asserted or tms reset)");
if (jtag_ntrst_delay)
jtag_add_sleep(jtag_ntrst_delay * 1000);
}
-
- return retval;
-
+ return ERROR_OK;
}
int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst)
return ERROR_OK;
}
-int MINIDRIVER(interface_jtag_add_end_state)(enum tap_state state)
-{
- jtag_command_t **last_cmd = jtag_get_last_command_p();
-
- /* allocate memory for a new list member */
- *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
- (*last_cmd)->next = NULL;
- last_comand_pointer = &((*last_cmd)->next);
- (*last_cmd)->type = JTAG_END_STATE;
-
- (*last_cmd)->cmd.end_state = cmd_queue_alloc(sizeof(end_state_command_t));
- (*last_cmd)->cmd.end_state->end_state = state;
-
- return ERROR_OK;
-}
-
-int jtag_add_end_state(enum tap_state state)
+void jtag_add_end_state(enum tap_state state)
{
- if (state != -1)
- cmd_queue_end_state = state;
- int retval = interface_jtag_add_end_state(cmd_queue_end_state);
- return retval;
+ cmd_queue_end_state = state;
}
int MINIDRIVER(interface_jtag_add_sleep)(u32 us)
return ERROR_OK;
}
-int jtag_add_sleep(u32 us)
+void jtag_add_sleep(u32 us)
{
- return interface_jtag_add_sleep(us);
+ int retval=interface_jtag_add_sleep(us);
+ if (retval!=ERROR_OK)
+ jtag_error=retval;
+ return;
}
int jtag_scan_size(scan_command_t *cmd)
int retval=interface_jtag_execute_queue();
if (retval==ERROR_OK)
{
- retval=jtag_error;
+ retval=jtag_error;
}
jtag_error=ERROR_OK;
return retval;
/* Try to examine chain layout according to IEEE 1149.1 ยง12
*/
-int jtag_examine_chain(u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4] )
+int jtag_examine_chain()
{
jtag_device_t *device = jtag_devices;
scan_field_t field;
+ u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
int i;
int bit_count;
int device_count = 0;
if (device_count != jtag_num_devices)
{
ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)",
- device_count, jtag_num_devices);
+ device_count, jtag_num_devices);
ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
return ERROR_JTAG_INIT_FAILED;
}
register_command(cmd_ctx, NULL, "interface", handle_interface_command,
COMMAND_CONFIG, NULL);
register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
- COMMAND_ANY, "set jtag speed (if supported) <speed>");
+ COMMAND_ANY, "set jtag speed (if supported) <reset speed> [<post reset speed, default value is reset speed>]");
register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");
register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
return ERROR_OK;
}
-extern int jtag_init_chain(struct command_context_s *cmd_ctx);
-
-static int jtag_sense_handler(void *priv)
-{
- struct command_context_s *cmd_ctx;
- cmd_ctx=(struct command_context_s *)priv;
-
- static int scan_complete = 0;
- if (!scan_complete)
- {
- if (jtag_init_chain(cmd_ctx)==ERROR_OK)
- {
- scan_complete = 1;
- }
- return ERROR_OK;
- }
-
- return ERROR_OK;
-}
-
-/* OpenOCD will start telnet/gdb servers before the JTAG chain has
- * been enumerated. This is to allow e.g. GDB init script to
- * run monitor commands to initialize the target so jtag_init_chain()
- * will succeed.
- *
- * A timer callback is added where sensing is retried once every second
- * until it succeeds.
- */
int jtag_init(struct command_context_s *cmd_ctx)
{
+ int validate_tries = 0;
jtag_device_t *device;
DEBUG("-");
jtag_add_statemove(TAP_TLR);
jtag_execute_queue();
- target_register_timer_callback(jtag_sense_handler, 1000, 1, cmd_ctx);
-
- return ERROR_OK;
- }
-
-static int jtag_test_chain(u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4])
-{
- jtag_add_statemove(TAP_TLR);
- jtag_execute_queue();
-
/* examine chain first, as this could discover the real chain layout */
- if (jtag_examine_chain(idcode_buffer)!=ERROR_OK)
+ if (jtag_examine_chain() != ERROR_OK)
{
- WARNING("trying to validate configured JTAG chain anyway...");
+ ERROR("trying to validate configured JTAG chain anyway...");
}
- return jtag_validate_chain();
-}
-
-/* Unless we can do this successfully 10 times, we're not
- * satisfied with the quality of the JTAG communication.
- *
- * Since we're continously repeating this operation, be a bit
- * wary of filling the log with megabytes of data.
- *
- * Keep increasing the jtag_divisor until we've got a solid
- * result.
- */
-int jtag_init_chain(struct command_context_s *cmd_ctx)
-{
- int i, j;
- int retval;
- for (i=jtag_speed; i<64; i++)
- {
- u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
- jtag_speed=i;
- if ((retval=jtag->speed(jtag_speed))!=ERROR_OK)
- continue;
- for (j=0; j<10; j++)
- {
- u8 idcode_current[JTAG_MAX_CHAIN_SIZE * 4];
- enum log_levels save_log_level=debug_level;
- /* avoid spamming log */
- debug_level=LOG_SILENT;
- retval=jtag_test_chain(idcode_current);
- if (retval==ERROR_OK)
- {
- if (j==0)
- {
- memcpy(idcode_buffer, idcode_current, sizeof(idcode_buffer));
- } else
- {
- retval=(memcmp(idcode_buffer, idcode_current, sizeof(idcode_buffer))==0)?ERROR_OK:ERROR_JTAG_INIT_FAILED;
- }
- }
- debug_level = save_log_level;
- if (retval!=ERROR_OK)
- {
- break;
- }
- }
- if (retval==ERROR_OK)
+ while (jtag_validate_chain() != ERROR_OK)
+ {
+ validate_tries++;
+ if (validate_tries > 5)
{
- /* Print out result */
- INFO("Succeeded jtag chain test jtag_speed=%d", jtag_speed);
- return jtag_test_chain(idcode_buffer);
+ ERROR("Could not validate JTAG chain, exit");
+ return ERROR_JTAG_INVALID_INTERFACE;
}
- DEBUG("Failed jtag chain test, dropping clock rate. Trying jtag_speed=%d\n", i+1);
+ usleep(10000);
}
- return retval;
+
+ return ERROR_OK;
}
+
int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
int i;
jtag_register_event_callback(jtag_reset_callback, (*last_device_p));
jtag_num_devices++;
-
+
return ERROR_OK;
}
int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
- if (argc == 0)
- command_print(cmd_ctx, "jtag_speed: %i", jtag_speed);
+ int cur_speed = 0;
+ if ((argc<1) || (argc>2))
+ return ERROR_COMMAND_SYNTAX_ERROR;
- if (argc > 0)
- {
- jtag_speed = strtoul(args[0], NULL, 0);
- /* this command can be called during CONFIG,
- * in which case jtag isn't initialized */
- if (jtag)
- jtag->speed(jtag_speed);
- }
+ if (argc >= 1)
+ cur_speed = jtag_speed = jtag_speed_post_reset = strtoul(args[0], NULL, 0);
+ if (argc == 2)
+ cur_speed = jtag_speed_post_reset = strtoul(args[1], NULL, 0);
+
+ /* this command can be called during CONFIG,
+ * in which case jtag isn't initialized */
+ if (jtag)
+ jtag->speed(cur_speed);
return ERROR_OK;
}
{
int trst = -1;
int srst = -1;
- int retval;
if (argc < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR;
-
}
if (args[0][0] == '1')
if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)
return ERROR_JTAG_INIT_FAILED;
- if ((retval = jtag_add_reset(trst, srst)) != ERROR_OK)
- {
- switch (retval)
- {
- case ERROR_JTAG_RESET_WOULD_ASSERT_TRST:
- command_print(cmd_ctx, "requested reset would assert trst\nif this is acceptable, use jtag_reset 1 %c", args[1][0]);
- break;
- case ERROR_JTAG_RESET_CANT_SRST:
- command_print(cmd_ctx, "can't assert srst because the current reset_config doesn't support it");
- break;
- default:
- command_print(cmd_ctx, "unknown error");
- }
- }
+ jtag_add_reset(trst, srst);
jtag_execute_queue();
return ERROR_OK;
free(fields[i].out_value);
free(fields);
-
+
return ERROR_OK;
}