X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=d5158126c9160bc9eac4638e1a4b416940f3442a;hb=dc33cb668d64e9ab3720b09db653f40c914efcde;hp=02272bd93b2278512034d9c8cc981bc317729310;hpb=0470a9652b6275981ec132cb74a4af942b12a6ac;p=openocd.git diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 02272bd93b..d5158126c9 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 * @@ -140,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; @@ -240,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 */ @@ -398,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; @@ -413,7 +416,7 @@ void cmd_queue_free() cmd_queue_pages = NULL; } -static void jtag_prelude1() +static void jtag_prelude1(void) { if (jtag_trst == 1) { @@ -761,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; @@ -854,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"); } @@ -1120,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) @@ -1309,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; @@ -1362,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; } @@ -1374,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; @@ -1394,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 */ @@ -1408,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; @@ -1473,7 +1496,7 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) 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, @@ -1516,9 +1539,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; } @@ -1565,10 +1586,10 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx) if (validate_tries > 5) { - LOG_ERROR("Could not validate JTAG chain, exit"); + LOG_ERROR("Could not validate JTAG chain"); return ERROR_JTAG_INVALID_INTERFACE; } - usleep(10000); + alive_sleep(10); } return ERROR_OK; @@ -1631,7 +1652,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"); @@ -1640,6 +1660,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; } @@ -1856,81 +1877,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) { @@ -2007,7 +2022,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; @@ -2051,7 +2065,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