X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=33330a09adaed2095dbeef9bee772d966a3a5e4e;hb=473dc89c24f3c17c04dcafbf9b5c79d73a35ffe4;hp=5738a0dc46df91d1b5ffd4e8a3de69503b7a5572;hpb=f86f2ab3f8e51129ccadcba4920be0f8bf47637e;p=openocd.git diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 5738a0dc46..33330a09ad 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -37,7 +37,8 @@ #endif -int jtag_flush_queue_count; /* count # of flushes for profiling / debugging purposes */ +/// The number of JTAG queue flushes (for profiling and debugging purposes). +static int jtag_flush_queue_count; static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state), int in_num_fields, scan_field_t *in_fields, tap_state_t state); @@ -62,7 +63,15 @@ const Jim_Nvp nvp_jtag_tap_event[] = { int jtag_trst = 0; int jtag_srst = 0; -static jtag_tap_t *jtag_all_taps = NULL; +/** + * List all TAPs that have been created. + */ +static jtag_tap_t *__jtag_all_taps = NULL; +/** + * The number of TAPs in the __jtag_all_taps list, used to track the + * assigned chain position to new TAPs + */ +static int jtag_num_taps = 0; enum reset_types jtag_reset_config = RESET_NONE; tap_state_t cmd_queue_end_state = TAP_RESET; @@ -85,7 +94,7 @@ jtag_event_callback_t *jtag_event_callbacks; /* speed in kHz*/ static int speed_khz = 0; /* flag if the kHz speed was defined */ -static int hasKHz = 0; +static bool hasKHz = false; /* jtag interfaces (parport, FTDI-USB, TI-USB, ...) */ @@ -227,23 +236,14 @@ static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, ch static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -jtag_tap_t *jtag_AllTaps(void) +jtag_tap_t *jtag_all_taps(void) { - return jtag_all_taps; + return __jtag_all_taps; }; int jtag_NumTotalTaps(void) { - jtag_tap_t *t; - int n; - - n = 0; - t = jtag_AllTaps(); - while(t){ - n++; - t = t->next_tap; - } - return n; + return jtag_num_taps; } int jtag_NumEnabledTaps(void) @@ -252,7 +252,7 @@ int jtag_NumEnabledTaps(void) int n; n = 0; - t = jtag_AllTaps(); + t = jtag_all_taps(); while(t){ if( t->enabled ){ n++; @@ -262,12 +262,23 @@ int jtag_NumEnabledTaps(void) return n; } +/// Append a new TAP to the chain of all taps. +static void jtag_tap_add(struct jtag_tap_s *t) +{ + t->abs_chain_position = jtag_num_taps++; + + jtag_tap_t **tap = &__jtag_all_taps; + while(*tap != NULL) + tap = &(*tap)->next_tap; + *tap = t; +} + jtag_tap_t *jtag_TapByString( const char *s ) { jtag_tap_t *t; char *cp; - t = jtag_AllTaps(); + t = jtag_all_taps(); /* try name first */ while(t){ if( 0 == strcmp( t->dotted_name, s ) ){ @@ -283,7 +294,7 @@ jtag_tap_t *jtag_TapByString( const char *s ) 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; @@ -308,13 +319,13 @@ jtag_tap_t * jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o ) } /* 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; orig_n = n; - t = jtag_AllTaps(); + t = jtag_all_taps(); while( t && (n > 0)) { n--; @@ -323,6 +334,12 @@ jtag_tap_t * jtag_TapByAbsPosition( int n ) return t; } +const char *jtag_tap_name(const jtag_tap_t *tap) +{ + return (tap == NULL) ? "(unknown)" : tap->dotted_name; +} + + int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv) { jtag_event_callback_t **callbacks_p = &jtag_event_callbacks; @@ -396,9 +413,7 @@ static void jtag_prelude(tap_state_t state) assert(state!=TAP_INVALID); - jtag_add_end_state(state); - - cmd_queue_cur_state = cmd_queue_end_state; + cmd_queue_cur_state = state; } void jtag_alloc_in_value32(scan_field_t *field) @@ -411,7 +426,7 @@ void jtag_add_ir_scan_noverify(int in_num_fields, const scan_field_t *in_fields, int retval; jtag_prelude(state); - retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, cmd_queue_end_state); + retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, state); if (retval!=ERROR_OK) jtag_error=retval; @@ -460,7 +475,7 @@ void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields, ta jtag_prelude(state); - retval=interface_jtag_add_plain_ir_scan(in_num_fields, in_fields, cmd_queue_end_state); + retval=interface_jtag_add_plain_ir_scan(in_num_fields, in_fields, state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -548,7 +563,7 @@ void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields, tap_stat jtag_prelude(state); - retval=interface_jtag_add_dr_scan(in_num_fields, in_fields, cmd_queue_end_state); + retval=interface_jtag_add_dr_scan(in_num_fields, in_fields, state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -567,7 +582,7 @@ void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields, ta jtag_prelude(state); - retval=interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, cmd_queue_end_state); + retval=interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -578,13 +593,11 @@ void jtag_add_dr_out(jtag_tap_t* tap, { assert(end_state != TAP_INVALID); - cmd_queue_end_state = end_state; - - cmd_queue_cur_state = cmd_queue_end_state; + cmd_queue_cur_state = end_state; interface_jtag_add_dr_out(tap, num_fields, num_bits, value, - cmd_queue_end_state); + end_state); } void jtag_add_tlr(void) @@ -644,7 +657,7 @@ void jtag_add_runtest(int num_cycles, tap_state_t state) jtag_prelude(state); /* executed by sw or hw fifo */ - retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state); + retval=interface_jtag_add_runtest(num_cycles, state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -754,7 +767,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) if (trst_with_tlr) { LOG_DEBUG("JTAG reset with RESET instead of TRST"); - jtag_add_end_state(TAP_RESET); + jtag_set_end_state(TAP_RESET); jtag_add_tlr(); return; } @@ -775,7 +788,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) } } -tap_state_t jtag_add_end_state(tap_state_t state) +tap_state_t jtag_set_end_state(tap_state_t state) { if ((state == TAP_DRSHIFT)||(state == TAP_IRSHIFT)) { @@ -787,6 +800,11 @@ tap_state_t jtag_add_end_state(tap_state_t state) return cmd_queue_end_state; } +tap_state_t jtag_get_end_state(void) +{ + return cmd_queue_end_state; +} + void jtag_add_sleep(u32 us) { keep_alive(); /* we might be running on a very slow JTAG clk */ @@ -796,11 +814,6 @@ void jtag_add_sleep(u32 us) return; } -static const char *jtag_tap_name(const jtag_tap_t *tap) -{ - return (tap == NULL) ? "(unknown)" : tap->dotted_name; -} - int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits) { int retval = ERROR_OK; @@ -896,6 +909,11 @@ void jtag_execute_queue_noclear(void) } } +int jtag_get_flush_queue_count(void) +{ + return jtag_flush_queue_count; +} + int jtag_execute_queue(void) { int retval; @@ -905,7 +923,7 @@ int jtag_execute_queue(void) return retval; } -int jtag_reset_callback(enum jtag_event event, void *priv) +static int jtag_reset_callback(enum jtag_event event, void *priv) { jtag_tap_t *tap = priv; @@ -927,7 +945,7 @@ void jtag_sleep(u32 us) /* Try to examine chain layout according to IEEE 1149.1 §12 */ -int jtag_examine_chain(void) +static int jtag_examine_chain(void) { jtag_tap_t *tap; scan_field_t field; @@ -1093,7 +1111,7 @@ int jtag_examine_chain(void) return ERROR_OK; } -int jtag_validate_chain(void) +static int jtag_validate_chain(void) { jtag_tap_t *tap; int total_ir_length = 0; @@ -1257,10 +1275,44 @@ static int jtag_tap_configure_cmd( Jim_GetOptInfo *goi, jtag_tap_t * tap) return JIM_OK; } + +static void jtag_tap_init(jtag_tap_t *tap) +{ + assert(0 != tap->ir_length); + + tap->expected = malloc(tap->ir_length); + tap->expected_mask = malloc(tap->ir_length); + tap->cur_instr = malloc(tap->ir_length); + + buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value); + buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask); + buf_set_ones(tap->cur_instr, tap->ir_length); + + // place TAP in bypass mode + tap->bypass = 1; + // register the reset callback for the TAP + jtag_register_event_callback(&jtag_reset_callback, tap); + + LOG_DEBUG("Created Tap: %s @ abs position %d, " + "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name, + tap->abs_chain_position, tap->ir_length, + tap->ir_capture_value, tap->ir_capture_mask); + jtag_tap_add(tap); +} + +static void jtag_tap_free(jtag_tap_t *tap) +{ + /// @todo is anything missing? no memory leaks please + free((void *)tap->expected_ids); + free((void *)tap->chip); + free((void *)tap->tapname); + free((void *)tap->dotted_name); + free(tap); +} + static int jim_newtap_cmd( Jim_GetOptInfo *goi ) { jtag_tap_t *pTap; - jtag_tap_t **ppTap; jim_wide w; int x; int e; @@ -1392,58 +1444,18 @@ static int jim_newtap_cmd( Jim_GetOptInfo *goi ) } /* switch(n->value) */ } /* while( goi->argc ) */ - /* Did we get all the options? */ - if( reqbits ){ - // no - Jim_SetResult_sprintf( goi->interp, - "newtap: %s missing required parameters", - pTap->dotted_name); - /* TODO: Tell user what is missing :-( */ - /* no memory leaks pelase */ - free(((void *)(pTap->expected_ids))); - free(((void *)(pTap->chip))); - free(((void *)(pTap->tapname))); - free(((void *)(pTap->dotted_name))); - free(((void *)(pTap))); - return JIM_ERR; - } - - pTap->expected = malloc( pTap->ir_length ); - pTap->expected_mask = malloc( pTap->ir_length ); - pTap->cur_instr = malloc( pTap->ir_length ); - - buf_set_u32( pTap->expected, - 0, - pTap->ir_length, - pTap->ir_capture_value ); - buf_set_u32( pTap->expected_mask, - 0, - pTap->ir_length, - pTap->ir_capture_mask ); - buf_set_ones( pTap->cur_instr, - pTap->ir_length ); - - pTap->bypass = 1; - - jtag_register_event_callback(jtag_reset_callback, pTap ); - - ppTap = &(jtag_all_taps); - while( (*ppTap) != NULL ){ - ppTap = &((*ppTap)->next_tap); - } - *ppTap = pTap; + /* Did all the required option bits get cleared? */ + if (0 == reqbits) { - static int n_taps = 0; - pTap->abs_chain_position = n_taps++; + jtag_tap_init(pTap); + return ERROR_OK; } - LOG_DEBUG( "Created Tap: %s @ abs position %d, irlen %d, capture: 0x%x mask: 0x%x", - (*ppTap)->dotted_name, - (*ppTap)->abs_chain_position, - (*ppTap)->ir_length, - (*ppTap)->ir_capture_value, - (*ppTap)->ir_capture_mask ); - return ERROR_OK; + Jim_SetResult_sprintf(goi->interp, + "newtap: %s missing required parameters", + pTap->dotted_name); + jtag_tap_free(pTap); + return JIM_ERR; } static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) @@ -1647,8 +1659,8 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) } if(hasKHz) { - jtag_interface->khz(speed_khz, &jtag_speed); - hasKHz = 0; + jtag_interface->khz(jtag_get_speed_khz(), &jtag_speed); + hasKHz = false; } if (jtag_interface->init() != ERROR_OK) @@ -1760,6 +1772,15 @@ int jtag_init(struct command_context_s *cmd_ctx) return jtag_init_reset(cmd_ctx); } +void jtag_set_speed_khz(unsigned khz) +{ + speed_khz = khz; +} +unsigned jtag_get_speed_khz(void) +{ + return speed_khz; +} + static int default_khz(int khz, int *jtag_speed) { LOG_ERROR("Translation from khz to jtag_speed not implemented"); @@ -1912,7 +1933,7 @@ static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cm { jtag_tap_t *tap; - tap = jtag_all_taps; + tap = jtag_all_taps(); command_print(cmd_ctx, " TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr "); command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------"); @@ -2064,7 +2085,7 @@ static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, ch } else { - jtag_nsrst_delay = strtoul(args[0], NULL, 0); + jtag_set_nsrst_delay(strtoul(args[0], NULL, 0)); } return ERROR_OK; @@ -2079,12 +2100,13 @@ static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, ch } else { - jtag_ntrst_delay = strtoul(args[0], NULL, 0); + jtag_set_ntrst_delay(strtoul(args[0], NULL, 0)); } 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; @@ -2118,17 +2140,17 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, int retval=ERROR_OK; LOG_DEBUG("handle jtag khz"); + int cur_speed = 0; if(argc == 1) { - speed_khz = strtoul(args[0], NULL, 0); + jtag_set_speed_khz(strtoul(args[0], NULL, 0)); if (jtag != NULL) { - int cur_speed = 0; LOG_DEBUG("have interface set up"); int speed_div1; - if ((retval=jtag->khz(speed_khz, &speed_div1))!=ERROR_OK) + if ((retval=jtag->khz(jtag_get_speed_khz(), &speed_div1))!=ERROR_OK) { - speed_khz = 0; + jtag_set_speed_khz(0); return retval; } @@ -2137,7 +2159,7 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, retval=jtag->speed(cur_speed); } else { - hasKHz = 1; + hasKHz = true; } } else if (argc==0) { @@ -2145,20 +2167,18 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, { return ERROR_COMMAND_SYNTAX_ERROR; } + cur_speed = jtag_get_speed_khz(); if (jtag!=NULL) { - if ((retval=jtag->speed_div(jtag_speed, &speed_khz))!=ERROR_OK) + if ((retval=jtag->speed_div(jtag_speed, &cur_speed))!=ERROR_OK) return retval; } - if (speed_khz==0) - { + if (cur_speed) + command_print(cmd_ctx, "%d kHz", cur_speed); + else command_print(cmd_ctx, "RCLK - adaptive"); - } else - { - command_print(cmd_ctx, "%d kHz", speed_khz); - } return retval; } @@ -2178,7 +2198,7 @@ static int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, command_print( cmd_ctx, "Invalid state name: %s\n", args[0] ); return ERROR_COMMAND_SYNTAX_ERROR; } - jtag_add_end_state(state); + jtag_set_end_state(state); jtag_execute_queue(); } command_print(cmd_ctx, "current endstate: %s", tap_state_name(cmd_queue_end_state)); @@ -2230,7 +2250,7 @@ static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, return ERROR_COMMAND_SYNTAX_ERROR; } - jtag_add_runtest(strtol(args[0], NULL, 0), jtag_add_end_state(TAP_INVALID)); + jtag_add_runtest(strtol(args[0], NULL, 0), jtag_get_end_state()); jtag_execute_queue(); return ERROR_OK; @@ -2473,7 +2493,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args) { - Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_flush_queue_count)); + Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count())); return JIM_OK; } @@ -2504,27 +2524,33 @@ static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, ch return ERROR_OK; } +void jtag_set_verify(bool enable) +{ + jtag_verify = enable; +} + +bool jtag_will_verify() +{ + return jtag_verify; +} + static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { + if (argc > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + if (argc == 1) { if (strcmp(args[0], "enable") == 0) - { - jtag_verify = 1; - } + jtag_set_verify(true); else if (strcmp(args[0], "disable") == 0) - { - jtag_verify = 0; - } else - { + jtag_set_verify(false); + else return ERROR_COMMAND_SYNTAX_ERROR; - } - } else if (argc != 0) - { - return ERROR_COMMAND_SYNTAX_ERROR; } - command_print(cmd_ctx, "verify jtag capture is %s", (jtag_verify) ? "enabled": "disabled"); + const char *status = jtag_will_verify() ? "enabled": "disabled"; + command_print(cmd_ctx, "verify jtag capture is %s", status); return ERROR_OK; } @@ -2680,3 +2706,13 @@ int jtag_add_statemove(tap_state_t goal_state) return retval; } +void jtag_set_nsrst_delay(unsigned delay) +{ + jtag_nsrst_delay = delay; +} +void jtag_set_ntrst_delay(unsigned delay) +{ + jtag_ntrst_delay = delay; +} + +