X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=f1e412476029e23ed9d4f2bd99c765b9b8c1ae94;hp=d45fd67ee7515538c9eec187e20f610f5b37617c;hb=c18947b947064e7eceed8047c42d4c8dfd8ae964;hpb=a485ded4bff2a4fafbcaf3c1094060b172d2af8d diff --git a/src/jtag/core.c b/src/jtag/core.c index d45fd67ee7..f1e4124760 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -58,9 +58,11 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s */ static int jtag_error = ERROR_OK; -static char* jtag_event_strings[] = +static const char *jtag_event_strings[] = { - "JTAG controller reset (RESET or TRST)" + [JTAG_TRST_ASSERTED] = "JTAG controller reset (RESET or TRST)", + [JTAG_TAP_EVENT_ENABLE] = "TAP enabled", + [JTAG_TAP_EVENT_DISABLE] = "TAP disabled", }; static int jtag_trst = 0; @@ -87,6 +89,13 @@ static int jtag_verify = 1; static int jtag_nsrst_delay = 0; /* default to no nSRST delay */ static int jtag_ntrst_delay = 0; /* default to no nTRST delay */ +typedef struct jtag_event_callback_s +{ + jtag_event_handler_t callback; + void* priv; + struct jtag_event_callback_s* next; +} jtag_event_callback_t; + /* callbacks to inform high-level handlers about JTAG state changes */ static jtag_event_callback_t *jtag_event_callbacks; @@ -96,7 +105,7 @@ static int speed_khz = 0; static bool hasKHz = false; static int jtag_speed = 0; -struct jtag_interface_s *jtag = NULL; +static struct jtag_interface_s *jtag = NULL; /* configuration */ jtag_interface_t *jtag_interface = NULL; @@ -165,9 +174,8 @@ jtag_tap_t *jtag_tap_by_string(const char *s) } /* no tap found by name, so try to parse the name as a number */ - char *cp; - unsigned n = strtoul(s, &cp, 0); - if ((s == cp) || (*cp != 0)) + unsigned n; + if (parse_uint(s, &n) != ERROR_OK) return NULL; return jtag_tap_by_position(n); @@ -195,13 +203,25 @@ jtag_tap_t *jtag_tap_by_position(unsigned n) return t; } +jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p) +{ + p = p ? p->next_tap : jtag_all_taps(); + while (p) + { + if (p->enabled) + return p; + p = p->next_tap; + } + return NULL; +} + 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) +int jtag_register_event_callback(jtag_event_handler_t callback, void *priv) { jtag_event_callback_t **callbacks_p = &jtag_event_callbacks; @@ -225,24 +245,30 @@ int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *pr return ERROR_OK; } -int jtag_unregister_event_callback(int (*callback)(enum jtag_event event, void *priv)) +int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv) { - jtag_event_callback_t **callbacks_p = &jtag_event_callbacks; + jtag_event_callback_t **callbacks_p; + jtag_event_callback_t **next; if (callback == NULL) { return ERROR_INVALID_ARGUMENTS; } - while (*callbacks_p) + for (callbacks_p = &jtag_event_callbacks; + *callbacks_p != NULL; + callbacks_p = next) { - jtag_event_callback_t **next = &((*callbacks_p)->next); + next = &((*callbacks_p)->next); + + if ((*callbacks_p)->priv != priv) + continue; + if ((*callbacks_p)->callback == callback) { free(*callbacks_p); *callbacks_p = *next; } - callbacks_p = next; } return ERROR_OK; @@ -256,8 +282,12 @@ int jtag_call_event_callbacks(enum jtag_event event) while (callback) { + jtag_event_callback_t *next; + + /* callback may remove itself */ + next = callback->next; callback->callback(event, callback->priv); - callback = callback->next; + callback = next; } return ERROR_OK; @@ -323,23 +353,23 @@ void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields, jtag_set_error(retval); } -void jtag_add_callback(jtag_callback1_t f, u8 *in) +void jtag_add_callback(jtag_callback1_t f, uint8_t *in) { interface_jtag_add_callback(f, in); } -void jtag_add_callback4(jtag_callback_t f, u8 *in, +void jtag_add_callback4(jtag_callback_t f, uint8_t *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { interface_jtag_add_callback4(f, in, data1, data2, data3); } -int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits); +int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits); -static int jtag_check_value_mask_callback(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) +static int jtag_check_value_mask_callback(uint8_t *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { - return jtag_check_value_inner(in, (u8 *)data1, (u8 *)data2, (int)data3); + return jtag_check_value_inner(in, (uint8_t *)data1, (uint8_t *)data2, (int)data3); } static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state), @@ -469,6 +499,50 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) cmd_queue_cur_state = path[num_states - 1]; } +int jtag_add_statemove(tap_state_t goal_state) +{ + tap_state_t cur_state = cmd_queue_cur_state; + + LOG_DEBUG( "cur_state=%s goal_state=%s", + tap_state_name(cur_state), + tap_state_name(goal_state) ); + + + if (goal_state==cur_state ) + ; /* nothing to do */ + else if( goal_state==TAP_RESET ) + { + jtag_add_tlr(); + } + else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) ) + { + unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); + unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state); + tap_state_t moves[8]; + assert(tms_count < DIM(moves)); + + for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) + { + bool bit = tms_bits & 1; + + cur_state = tap_state_transition(cur_state, bit); + moves[i] = cur_state; + } + + jtag_add_pathmove(tms_count, moves); + } + else if( tap_state_transition(cur_state, true) == goal_state + || tap_state_transition(cur_state, false) == goal_state ) + { + jtag_add_pathmove(1, &goal_state); + } + + else + return ERROR_FAIL; + + return ERROR_OK; +} + void jtag_add_runtest(int num_cycles, tap_state_t state) { jtag_prelude(state); @@ -619,7 +693,7 @@ void jtag_add_sleep(u32 us) jtag_set_error(interface_jtag_add_sleep(us)); } -int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits) +int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits) { int retval = ERROR_OK; @@ -668,7 +742,7 @@ int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, return retval; } -void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask) +void jtag_check_value_mask(scan_field_t *field, uint8_t *value, uint8_t *mask) { assert(field->in_value != NULL); @@ -724,6 +798,8 @@ static int jtag_reset_callback(enum jtag_event event, void *priv) if (event == JTAG_TRST_ASSERTED) { + tap->enabled = !tap->disabled_after_reset; + buf_set_ones(tap->cur_instr, tap->ir_length); tap->bypass = 1; } @@ -743,7 +819,7 @@ void jtag_sleep(u32 us) #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) +static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) { scan_field_t field = { .tap = NULL, @@ -760,10 +836,10 @@ static int jtag_examine_chain_execute(u8 *idcode_buffer, unsigned num_idcode) return jtag_execute_queue(); } -static bool jtag_examine_chain_check(u8 *idcodes, unsigned count) +static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count) { - u8 zero_check = 0x0; - u8 one_check = 0xff; + uint8_t zero_check = 0x0; + uint8_t one_check = 0xff; for (unsigned i = 0; i < count * 4; i++) { @@ -803,7 +879,7 @@ static bool jtag_idcode_is_final(u32 idcode) * 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) +static void jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max) { bool triggered = false; for ( ; count < max - 31; count += 32) @@ -831,7 +907,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap) } /* Loop over the expected identification codes and test for a match */ - u8 ii; + uint8_t ii; for (ii = 0; ii < tap->expected_ids_cnt; ii++) { if (tap->idcode == tap->expected_ids[ii]) @@ -861,7 +937,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap) */ int jtag_examine_chain(void) { - u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4]; + uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4]; unsigned device_count = 0; jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE); @@ -939,7 +1015,7 @@ int jtag_validate_chain(void) { jtag_tap_t *tap; int total_ir_length = 0; - u8 *ir_test = NULL; + uint8_t *ir_test = NULL; scan_field_t field; int chain_pos = 0; @@ -1011,6 +1087,7 @@ void jtag_tap_init(jtag_tap_t *tap) tap->expected_mask = malloc(tap->ir_length); tap->cur_instr = malloc(tap->ir_length); + /// @todo cope sanely with ir_length bigger than 32 bits 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); @@ -1029,6 +1106,8 @@ void jtag_tap_init(jtag_tap_t *tap) void jtag_tap_free(jtag_tap_t *tap) { + jtag_unregister_event_callback(&jtag_reset_callback, tap); + /// @todo is anything missing? no memory leaks please free((void *)tap->expected_ids); free((void *)tap->chip); @@ -1171,6 +1250,27 @@ unsigned jtag_get_speed_khz(void) { return speed_khz; } +int jtag_config_khz(unsigned khz) +{ + LOG_DEBUG("handle jtag khz"); + jtag_set_speed_khz(khz); + + int cur_speed = 0; + if (jtag != NULL) + { + LOG_DEBUG("have interface set up"); + int speed_div1; + int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1); + if (ERROR_OK != retval) + { + jtag_set_speed_khz(0); + return retval; + } + cur_speed = speed_div1; + } + return jtag_set_speed(cur_speed); +} + int jtag_get_speed(void) { return jtag_speed; @@ -1185,6 +1285,12 @@ int jtag_set_speed(int speed) return jtag ? jtag->speed(speed) : ERROR_OK; } +int jtag_get_speed_readable(int *speed) +{ + return jtag ? jtag->speed_div(jtag_get_speed(), speed) : ERROR_OK; +} + + void jtag_set_verify(bool enable) { jtag_verify = enable; @@ -1215,50 +1321,6 @@ int jtag_srst_asserted(int *srst_asserted) return jtag->srst_asserted(srst_asserted); } -int jtag_add_statemove(tap_state_t goal_state) -{ - tap_state_t cur_state = cmd_queue_cur_state; - - LOG_DEBUG( "cur_state=%s goal_state=%s", - tap_state_name(cur_state), - tap_state_name(goal_state) ); - - - if (goal_state==cur_state ) - ; /* nothing to do */ - else if( goal_state==TAP_RESET ) - { - jtag_add_tlr(); - } - else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) ) - { - unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); - unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state); - tap_state_t moves[8]; - assert(tms_count < DIM(moves)); - - for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) - { - bool bit = tms_bits & 1; - - cur_state = tap_state_transition(cur_state, bit); - moves[i] = cur_state; - } - - jtag_add_pathmove(tms_count, moves); - } - else if( tap_state_transition(cur_state, true) == goal_state - || tap_state_transition(cur_state, false) == goal_state ) - { - jtag_add_pathmove(1, &goal_state); - } - - else - return ERROR_FAIL; - - return ERROR_OK; -} - enum reset_types jtag_get_reset_config(void) { return jtag_reset_config;