X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=90d52d0f0093c0a91e1b8da51c9ad06616b2156c;hb=68c598e88d5e09728ea845a81ab279c615bbaf0f;hp=2b1a56fb8df92505e5e512dada98fa05d6ab7e5f;hpb=b06f254b248db04c71f685c811e4371ea8ae8ff3;p=openocd.git diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 2b1a56fb8d..90d52d0f00 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -2,6 +2,9 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * + * Copyright (C) 2007,2008 Øyvind Harboe * + * oyvind.harboe@zylin.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 * * the Free Software Foundation; either version 2 of the License, or * @@ -32,9 +35,6 @@ #include "string.h" #include -#include "openocd_tcl.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 */ @@ -143,7 +143,7 @@ int jtag_ntrst_delay = 0; /* default to no nTRST delay */ jtag_event_callback_t *jtag_event_callbacks; /* speed in kHz*/ -static int speed1 = 0, speed2 = 0; +static int speed_khz = 0; /* flag if the kHz speed was defined */ static int hasKHz = 0; @@ -243,7 +243,7 @@ jtag_interface_t *jtag = NULL; /* configuration */ jtag_interface_t *jtag_interface = NULL; int jtag_speed = 0; -int jtag_speed_post_reset = 0; + /* forward declarations */ @@ -252,7 +252,7 @@ void jtag_add_runtest(int num_cycles, enum tap_state endstate); 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); + /* jtag commands */ int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -401,7 +401,7 @@ void* cmd_queue_alloc(size_t size) return t + offset; } -void cmd_queue_free() +void cmd_queue_free(void) { cmd_queue_page_t *page = cmd_queue_pages; @@ -416,7 +416,7 @@ void cmd_queue_free() cmd_queue_pages = NULL; } -static void jtag_prelude1() +static void jtag_prelude1(void) { if (jtag_trst == 1) { @@ -764,9 +764,6 @@ void MINIDRIVER(interface_jtag_add_dr_out)(int device_num, } } - - - void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state) { int retval; @@ -814,7 +811,7 @@ int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *f return ERROR_OK; } -void jtag_add_tlr() +void jtag_add_tlr(void) { jtag_prelude(TAP_TLR); @@ -857,6 +854,11 @@ void jtag_add_pathmove(int num_states, enum tap_state *path) for (i=0; icmd.reset->trst = req_trst; (*last_cmd)->cmd.reset->srst = req_srst; - return ERROR_OK; } void jtag_add_end_state(enum tap_state state) { cmd_queue_end_state = state; - if ((cmd_queue_end_state == TAP_SD)||(cmd_queue_end_state == TAP_SD)) + if ((cmd_queue_end_state == TAP_SD)||(cmd_queue_end_state == TAP_SI)) { LOG_ERROR("BUG: TAP_SD/SI can't be end state. Calling code should use a larger scan field"); } @@ -1074,6 +1074,7 @@ int MINIDRIVER(interface_jtag_add_sleep)(u32 us) void jtag_add_sleep(u32 us) { + keep_alive(); /* we might be running on a very slow JTAG clk */ int retval=interface_jtag_add_sleep(us); if (retval!=ERROR_OK) jtag_error=retval; @@ -1122,7 +1123,6 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) } return bit_count; - } int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) @@ -1311,12 +1311,12 @@ int jtag_reset_callback(enum jtag_event event, void *priv) void jtag_sleep(u32 us) { - usleep(us); + alive_sleep(us/1000); } /* Try to examine chain layout according to IEEE 1149.1 §12 */ -int jtag_examine_chain() +int jtag_examine_chain(void) { jtag_device_t *device = jtag_devices; scan_field_t field; @@ -1364,7 +1364,8 @@ int jtag_examine_chain() if ((idcode & 1) == 0) { /* LSB must not be 0, this indicates a device in bypass */ - device_count++; + LOG_WARNING("Device does not have IDCODE"); + idcode=0; bit_count += 1; } @@ -1376,17 +1377,31 @@ int jtag_examine_chain() if (idcode == 0x000000FF) { - /* End of chain (invalid manufacturer ID) */ + 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)) + { + LOG_WARNING("Unexpected idcode after end of chain! %d 0x%08x", bit_count, idcode); + unexpected = 1; + } + } + break; } - if (device) - { - device->idcode = idcode; - device = device->next; - } - device_count++; - manufacturer = (idcode & 0xffe) >> 1; part = (idcode & 0xffff000) >> 12; version = (idcode & 0xf0000000) >> 28; @@ -1396,6 +1411,12 @@ int jtag_examine_chain() bit_count += 32; } + if (device) + { + device->idcode = idcode; + device = device->next; + } + device_count++; } /* see if number of discovered devices matches configuration */ @@ -1410,7 +1431,7 @@ int jtag_examine_chain() return ERROR_OK; } -int jtag_validate_chain() +int jtag_validate_chain(void) { jtag_device_t *device = jtag_devices; int total_ir_length = 0; @@ -1470,12 +1491,73 @@ int jtag_validate_chain() return ERROR_OK; } + +static int +jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) +{ + Jim_GetOptInfo goi; + int e; + Jim_Nvp *n; + struct command_context_s *context; + + enum { + JTAG_CMD_INTERFACE, + JTAG_CMD_INIT_RESET, + }; + + const Jim_Nvp jtag_cmds[] = { + { .name = "interface" , .value = JTAG_CMD_INTERFACE }, + { .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET }, + + { .name = NULL, .value = -1 }, + }; + + context = Jim_GetAssocData(interp, "context"); + // go past the command + Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 ); + + e = Jim_GetOpt_Nvp( &goi, jtag_cmds, &n ); + if( e != JIM_OK ){ + Jim_GetOpt_NvpUnknown( &goi, jtag_cmds, 0 ); + return e; + } + Jim_SetEmptyResult( goi.interp ); + switch( n->value ){ + case JTAG_CMD_INTERFACE: + // return the name of the interface + // TCL code might need to know the exact type... + // FUTURE: we allow this as a means to "set" the interface. + if( goi.argc != 0 ){ + Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)"); + return JIM_ERR; + } + Jim_SetResultString( goi.interp, jtag_interface->name, -1 ); + return JIM_OK; + case JTAG_CMD_INIT_RESET: + if( goi.argc != 0 ){ + Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)"); + return JIM_ERR; + } + e = jtag_init_reset(context); + if( e != ERROR_OK ){ + Jim_SetResult_sprintf( goi.interp, "error: %d", e); + return JIM_ERR; + } + return JIM_OK; + } + + + return JIM_ERR; +} + int jtag_register_commands(struct command_context_s *cmd_ctx) { + register_jim( cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions"); + 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) []"); + COMMAND_ANY, "set jtag speed (if supported)"); register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command, COMMAND_ANY, "same as jtag_speed, except it takes maximum khz as arguments. 0 KHz = RTCK."); register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command, @@ -1498,7 +1580,7 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) COMMAND_EXEC, "move to Run-Test/Idle, and execute "); register_command(cmd_ctx, NULL, "irscan", handle_irscan_command, COMMAND_EXEC, "execute IR scan [dev2] [instr2] ..."); - add_jim("drscan", Jim_Command_drscan, "execute DR scan ..."); + register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan ..."); register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command, COMMAND_ANY, "verify value captured during Capture-IR "); @@ -1518,9 +1600,7 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) } if(hasKHz) { - /*stay on "reset speed"*/ - jtag_interface->khz(speed1, &jtag_speed); - jtag_interface->khz(speed2, &jtag_speed_post_reset); + jtag_interface->khz(speed_khz, &jtag_speed); hasKHz = 0; } @@ -1535,7 +1615,6 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) static int jtag_init_inner(struct command_context_s *cmd_ctx) { - int validate_tries = 0; jtag_device_t *device; int retval; @@ -1561,16 +1640,9 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx) LOG_ERROR("trying to validate configured JTAG chain anyway..."); } - while (jtag_validate_chain() != ERROR_OK) + if (jtag_validate_chain() != ERROR_OK) { - validate_tries++; - - if (validate_tries > 5) - { - LOG_ERROR("Could not validate JTAG chain, exit"); - return ERROR_JTAG_INVALID_INTERFACE; - } - usleep(10000); + LOG_ERROR("Could not validate JTAG chain, continuing anyway..."); } return ERROR_OK; @@ -1633,7 +1705,6 @@ int jtag_init(struct command_context_s *cmd_ctx) return jtag_init_reset(cmd_ctx); } - static int default_khz(int khz, int *jtag_speed) { LOG_ERROR("Translation from khz to jtag_speed not implemented"); @@ -1642,6 +1713,7 @@ static int default_khz(int khz, int *jtag_speed) static int default_speed_div(int speed, int *khz) { + LOG_ERROR("Translation from jtag_speed to khz not implemented"); return ERROR_FAIL; } @@ -1858,81 +1930,75 @@ int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { - int cur_speed = 0; + int retval=ERROR_OK; - if (argc != 0) + if (argc == 1) { - if ((argc<1) || (argc>2)) - return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("handle 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); + + int cur_speed = 0; + cur_speed = 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_div(jtag_speed, &speed1); - jtag->speed_div(jtag_speed_post_reset, &speed2); - jtag->speed(cur_speed); + retval=jtag->speed(cur_speed); } - } - command_print(cmd_ctx, "jtag_speed: %d, %d", jtag_speed, jtag_speed_post_reset); + } else if (argc == 0) + { + } else + { + return ERROR_COMMAND_SYNTAX_ERROR; + } + command_print(cmd_ctx, "jtag_speed: %d", jtag_speed); - return ERROR_OK; + return retval; } 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>2) - return ERROR_COMMAND_SYNTAX_ERROR; - - if(argc != 0) + if(argc == 1) { - - if (argc >= 1) - speed1 = speed2 = strtoul(args[0], NULL, 0); - if (argc == 2) - speed2 = strtoul(args[1], NULL, 0); - + speed_khz = strtoul(args[0], NULL, 0); if (jtag != NULL) { int cur_speed = 0; LOG_DEBUG("have interface set up"); - int speed_div1, speed_div2; - if (jtag->khz(speed1, &speed_div1)!=ERROR_OK) + int speed_div1; + if ((retval=jtag->khz(speed_khz, &speed_div1))!=ERROR_OK) { - speed1 = speed2 = 0; - return ERROR_OK; - } - if (jtag->khz(speed2, &speed_div2)!=ERROR_OK) - { - speed1 = speed2 = 0; - return ERROR_OK; + speed_khz = 0; + return retval; } - if (argc >= 1) - cur_speed = jtag_speed = jtag_speed_post_reset = speed_div1; - if (argc == 2) - cur_speed = jtag_speed_post_reset = speed_div2; + cur_speed = jtag_speed = speed_div1; - jtag->speed(cur_speed); + retval=jtag->speed(cur_speed); } else { hasKHz = 1; } + } else if (argc==0) + { + } else + { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (jtag!=NULL) + { + if ((retval=jtag->speed_div(jtag_speed, &speed_khz))!=ERROR_OK) + return retval; } - command_print(cmd_ctx, "jtag_khz: %d, %d", speed1, speed2); - return ERROR_OK; -} + command_print(cmd_ctx, "jtag_khz: %d", speed_khz); + return retval; +} int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { @@ -2009,7 +2075,6 @@ int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char ** } - int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int i; @@ -2053,7 +2118,7 @@ int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args) scan_field_t *fields; int num_fields; int field_count = 0; - int i, j, e; + int i, e; long device; /* args[1] = device