X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=e02b91f088d5d6a818232c7e2cc3a9de8ec2a1be;hp=c1e2648b95832ce33a86133c91701a0ef9645df8;hb=84dfdd4de680d2f16275dee2445c5bfcaa363538;hpb=55c39bae67cb3b26dacb78a9d45fcd900745c3d8 diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index c1e2648b95..e02b91f088 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -41,6 +41,9 @@ #ifdef HAVE_STRINGS_H #include #endif +#include + + /* 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 @@ -519,15 +522,65 @@ static void jtag_prelude(tap_state_t state) cmd_queue_cur_state = cmd_queue_end_state; } -void jtag_add_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state) +void jtag_add_ir_scan_noverify(int num_fields, scan_field_t *fields, tap_state_t state) { int retval; - jtag_prelude(state); retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state); if (retval!=ERROR_OK) jtag_error=retval; + +} + + +void jtag_add_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state) +{ + /* 8 x 32 bit id's is enough for all invoations */ + u32 id[8]; + int modified[8]; + + /* if we are to run a verification of the ir scan, we need to get the input back. + * We may have to allocate space if the caller didn't ask for the input back. + * + */ + if (jtag_verify_capture_ir) + { + int j; + for (j = 0; j < num_fields; j++) + { + modified[j]=0; + if ((fields[j].in_value==NULL)&&(fields[j].num_bits<=32)) + { + if (j<8) + { + modified[j]=1; + fields[j].in_value=(u8 *)(id+j); + } else + { + LOG_DEBUG("caller must provide in_value space for verify_capture_ir to work"); + } + } + } + } + + jtag_add_ir_scan_noverify(num_fields, fields, state); + + if (jtag_verify_capture_ir) + { + int j; + for (j = 0; j < num_fields; j++) + { + jtag_tap_t *tap=fields[j].tap; + jtag_check_value_mask(fields+j, tap->expected, tap->expected_mask); + + if (modified[j]) + { + fields[j].in_value=NULL; + } + } + } + } int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state) @@ -579,21 +632,6 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, { found = 1; (*last_cmd)->cmd.scan->fields[nth_tap].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); - (*last_cmd)->cmd.scan->fields[nth_tap].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); - - if (jtag_verify_capture_ir) - { - if (fields[j].in_handler==NULL) - { - jtag_set_check_value((*last_cmd)->cmd.scan->fields+nth_tap, tap->expected, tap->expected_mask, NULL); - } else - { - (*last_cmd)->cmd.scan->fields[nth_tap].in_handler = fields[j].in_handler; - (*last_cmd)->cmd.scan->fields[nth_tap].in_handler_priv = fields[j].in_handler_priv; - (*last_cmd)->cmd.scan->fields[nth_tap].in_check_value = tap->expected; - (*last_cmd)->cmd.scan->fields[nth_tap].in_check_mask = tap->expected_mask; - } - } tap->bypass = 0; break; @@ -604,7 +642,6 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, { /* if a tap isn't listed, set it to BYPASS */ (*last_cmd)->cmd.scan->fields[nth_tap].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); - (*last_cmd)->cmd.scan->fields[nth_tap].out_mask = NULL; tap->bypass = 1; } @@ -652,7 +689,6 @@ int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *f (*last_cmd)->cmd.scan->fields[i].tap = fields[i].tap; (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits; (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits); - (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits); (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value; (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value; (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask; @@ -673,6 +709,12 @@ void jtag_add_dr_scan(int num_fields, scan_field_t *fields, tap_state_t state) jtag_error=retval; } +void jtag_add_dr_scan_now(int num_fields, scan_field_t *fields, tap_state_t state) +{ + jtag_add_dr_scan(num_fields, fields, state); + jtag_execute_queue_noclear(); +} + int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state) { int j; @@ -729,7 +771,6 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, scan_size = fields[j].num_bits; (*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size; (*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); - (*last_cmd)->cmd.scan->fields[field_count].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); (*last_cmd)->cmd.scan->fields[field_count].in_value = fields[j].in_value; (*last_cmd)->cmd.scan->fields[field_count].in_check_value = fields[j].in_check_value; (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = fields[j].in_check_mask; @@ -750,7 +791,6 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, /* program the scan field to 1 bit length, and ignore it's value */ (*last_cmd)->cmd.scan->fields[field_count].num_bits = 1; (*last_cmd)->cmd.scan->fields[field_count].out_value = NULL; - (*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL; @@ -840,7 +880,6 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap, buf_set_u32(out_value, 0, scan_size, value[j]); (*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size; (*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); - (*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL; @@ -860,7 +899,6 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap, /* program the scan field to 1 bit length, and ignore it's value */ (*last_cmd)->cmd.scan->fields[field_count].num_bits = 1; (*last_cmd)->cmd.scan->fields[field_count].out_value = NULL; - (*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL; (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL; @@ -906,7 +944,6 @@ int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *f (*last_cmd)->cmd.scan->fields[i].tap = fields[i].tap; (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits; (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits); - (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits); (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value; (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value; (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask; @@ -946,7 +983,7 @@ int MINIDRIVER(interface_jtag_add_tlr)(void) void jtag_add_pathmove(int num_states, tap_state_t *path) { - tap_state_t cur_state=cmd_queue_cur_state; + tap_state_t cur_state = cmd_queue_cur_state; int i; int retval; @@ -964,6 +1001,7 @@ void jtag_add_pathmove(int num_states, tap_state_t *path) LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences"); exit(-1); } + if ( tap_state_transition(cur_state, true) != path[i] && tap_state_transition(cur_state, false) != path[i]) { @@ -975,7 +1013,7 @@ void jtag_add_pathmove(int num_states, tap_state_t *path) jtag_prelude1(); - retval=interface_jtag_add_pathmove(num_states, path); + retval = interface_jtag_add_pathmove(num_states, path); cmd_queue_cur_state = path[num_states - 1]; if (retval!=ERROR_OK) jtag_error=retval; @@ -1346,7 +1384,7 @@ static const char *jtag_tap_name(jtag_tap_t *tap) return (tap == NULL) ? "(unknown)" : tap->dotted_name; } -int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) +int jtag_check_value_inner(u8 *captured, scan_field_t *field, u8 *in_check_value, u8 *in_check_mask) { int retval = ERROR_OK; int num_bits = field->num_bits; @@ -1354,9 +1392,9 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) int compare_failed = 0; if (field->in_check_mask) - compare_failed = buf_cmp_mask(captured, field->in_check_value, field->in_check_mask, num_bits); + compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); else - compare_failed = buf_cmp(captured, field->in_check_value, num_bits); + compare_failed = buf_cmp(captured, in_check_value, num_bits); if (compare_failed){ /* An error handler could have caught the failing check @@ -1368,12 +1406,12 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) if (compare_failed) { char *captured_char = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); - char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); + char *in_check_value_char = buf_to_str(in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); - if (field->in_check_mask) + if (in_check_mask) { char *in_check_mask_char; - in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); + in_check_mask_char = buf_to_str(in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); LOG_WARNING("value captured during scan didn't pass the requested check:"); LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char); @@ -1394,11 +1432,16 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) return retval; } +int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) +{ + return jtag_check_value_inner(captured, field, field->in_check_value, field->in_check_mask); +} + /* set up checking of this field using the in_handler. The values passed in must be valid until after jtag_execute() has completed. */ -void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handler_t *in_error_handler) +void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, struct invalidstruct *obsolete) { if (value) field->in_handler = jtag_check_value; @@ -1409,6 +1452,25 @@ void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handle field->in_check_mask = mask; } +void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask) +{ + assert(field->in_value != NULL); + + if (value==NULL) + { + /* no checking to do */ + return; + } + + jtag_execute_queue_noclear(); + + int retval=jtag_check_value_inner(field->in_value, field, value, mask); + jtag_set_error(retval); + +} + + + enum scan_type jtag_scan_type(scan_command_t *cmd) { int i; @@ -1445,13 +1507,21 @@ int MINIDRIVER(interface_jtag_execute_queue)(void) return retval; } -int jtag_execute_queue(void) +void jtag_execute_queue_noclear(void) { int retval=interface_jtag_execute_queue(); - if (retval==ERROR_OK) + /* we keep the first error */ + if ((jtag_error==ERROR_OK)&&(retval!=ERROR_OK)) { - retval=jtag_error; + jtag_error=retval; } +} + +int jtag_execute_queue(void) +{ + int retval; + jtag_execute_queue_noclear(); + retval=jtag_error; jtag_error=ERROR_OK; return retval; } @@ -1492,12 +1562,11 @@ int jtag_examine_chain(void) field.tap = NULL; field.num_bits = sizeof(idcode_buffer) * 8; field.out_value = idcode_buffer; - field.out_mask = NULL; + field.in_value = idcode_buffer; - field.in_check_value = NULL; - field.in_check_mask = NULL; + + field.in_handler = NULL; - field.in_handler_priv = NULL; for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++) { @@ -1670,12 +1739,8 @@ int jtag_validate_chain(void) field.tap = NULL; field.num_bits = total_ir_length; field.out_value = ir_test; - field.out_mask = NULL; field.in_value = ir_test; - field.in_check_value = NULL; - field.in_check_mask = NULL; field.in_handler = NULL; - field.in_handler_priv = NULL; jtag_add_plain_ir_scan(1, &field, TAP_RESET); jtag_execute_queue(); @@ -2792,7 +2857,6 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c fields[i].tap = tap; fields[i].out_value = malloc(CEIL(field_size, 8)); buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0)); - fields[i].out_mask = NULL; fields[i].in_value = NULL; fields[i].in_check_mask = NULL; fields[i].in_handler = NULL; @@ -2908,7 +2972,6 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args fields[field_count].num_bits = bits; fields[field_count].out_value = malloc(CEIL(bits, 8)); str_to_buf(str, len, fields[field_count].out_value, bits, 0); - fields[field_count].out_mask = NULL; fields[field_count].in_value = fields[field_count].out_value; fields[field_count].in_check_mask = NULL; fields[field_count].in_check_value = NULL; @@ -3127,7 +3190,7 @@ static struct #define B8(bits,count) { ((u8)B8__(HEX__(bits))), (count) } -#if 0 && ((BUILD_FT2232_FTD2XX==1) || (BUILD_FT2232_LIBFTDI==1)) +#if 0 && ((BUILD_FT2232_FTD2XX==1) || (BUILD_FT2232_LIBFTDI==1) || (BUILD_JLINK==1)) /* this is the table submitted by Jeff Williams on 3/30/2009 with this comment: OK, I added Peter's version of the state table, and it works OK for @@ -3137,29 +3200,40 @@ static struct some long-standing problems. Jeff - I added the bit count into the table + I added the bit count into the table, reduced RESET column to 7 bits from 8. Dick + + state specific comments: + ------------------------ + *->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to + work better on ARM9 with ft2232 driver. (Dick) + + RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing. + needed on ARM9 with ft2232 driver. (Dick) + + RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing. + needed on ARM9 with ft2232 driver. (Dick) */ /* to state: */ - /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */ - { B8(11111,5), B8(0,1), B8(0010,4), B8(01010,5), B8(00110,5), B8(010110,6) }, /* RESET */ - { B8(11111,5), B8(0,1), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */ - { B8(11111,5), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */ - { B8(11111,5), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */ - { B8(11111,5), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */ - { B8(11111,5), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1) } /* IRPAUSE */ + /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */ + { B8(1111111,7), B8(0,1), B8(00101,5), B8(01010,5), B8(001101,6), B8(010110,6) }, /* RESET */ + { B8(1111111,7), B8(0,1), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */ + { B8(1111111,7), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */ + { B8(1111111,7), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */ + { B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */ + { B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1) } /* IRPAUSE */ #else /* this is the old table, converted from hex and with the bit_count set to 7 for each combo, like before */ /* to state: */ - /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */ - { B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */ - { B8(1111111,7), B8(0000000,7), B8(0100101,7), B8(0000101,7), B8(0101011,7), B8(0001011,7) }, /* IDLE */ - { B8(1111111,7), B8(0110001,7), B8(0000000,7), B8(0000001,7), B8(0001111,7), B8(0101111,7) }, /* DRSHIFT */ - { B8(1111111,7), B8(0110000,7), B8(0100000,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* DRPAUSE */ - { B8(1111111,7), B8(0110001,7), B8(0000111,7), B8(0010111,7), B8(0000000,7), B8(0000001,7) }, /* IRSHIFT */ - { B8(1111111,7), B8(0110000,7), B8(0011100,7), B8(0010111,7), B8(0100000,7), B8(0101111,7) } /* IRPAUSE */ + /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */ + { B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */ + { B8(1111111,7), B8(0000000,7), B8(0100101,7), B8(0000101,7), B8(0101011,7), B8(0001011,7) }, /* IDLE */ + { B8(1111111,7), B8(0110001,7), B8(0000000,7), B8(0000001,7), B8(0001111,7), B8(0101111,7) }, /* DRSHIFT */ + { B8(1111111,7), B8(0110000,7), B8(0100000,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* DRPAUSE */ + { B8(1111111,7), B8(0110001,7), B8(0000111,7), B8(0010111,7), B8(0000000,7), B8(0000001,7) }, /* IRSHIFT */ + { B8(1111111,7), B8(0110000,7), B8(0011100,7), B8(0010111,7), B8(0100000,7), B8(0101111,7) } /* IRPAUSE */ #endif